模拟两个圆圈相互弹跳 [英] Simulating two circles bouncing off each other

查看:166
本文介绍了模拟两个圆圈相互弹跳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有许多粒子在四处移动并触摸检测以查看它们何时接触。如果两个粒子接触,它们应该以相反的方向反弹。

  particle.moveSelf = function(){
var radians = this.angle * Math.PI / 180;

var moveX = this.velocity * Math.sin(弧度);
var moveY = this.velocity * Math.cos(弧度);

for(var i = 0; i< particles.length; i ++){
var distance = this.position.getDistance(new Point(particles [i] .position.x,颗粒[I] .position.y));
//如果距离<半径1 +半径2,如果(距离<(this.radius + particles [i] .radius)&& this.id!== particles [i] .id){$},则将此圆圈反弹
b $ b this.velocity = -this.velocity;

}
}

this.position.x + = moveX;
this.position.y + = moveY;
};

当我运行此代码时,圆圈相互卡住,来回移动1 *速度每一帧。



关于如何计算反弹的速度或角度有很多问题,但我的问题只是它陷入无限振荡。 / p>

解决方案

我之前做过这个,所以这里有一些见解:


  1. 最安全的方法是为每个粒子添加碰撞列表




    • in首先通过检测碰撞

    • 并清除/填充碰撞列表,其中所有粒子的索引互相碰撞

        for(i = 0; i< particles; i ++)particle [i] .collide.clear(); 
      for(i = 0; i< particles; i ++)
      for(j = i + 1; j< particles; j ++)
      if(colide(particle [i],particle [j] ]))
      {
      particle [i] .collide.add(j);
      particle [j] .collide.add(i);
      }


    • 你也可以用里面的一个列表来做(i = 0; i< ...)循环


    • 但这不是那么精确


  2. 仅更新碰撞物品的位置和速度




    • 现在是棘手的部分

    • 我向每个粒子添加新的方向向量并将其设置为零

    • 然后在每次碰撞中添加一个反射(单位或速度或力量) (i = 0; i< particles; i ++)
      for(j = 0) ; j< particle [i] .collides; j ++)
      {
      //这里计算反射方向,速度无论反弹到矢量dir
      particle [i] .reflect + = dir;
      particle [particle [i] .collide [j]]。reflect + = dir;
      }


    • 完成后再更新仓位/速度.. 。


    • 但你需要添加更新所需的东西,例如

    • 如果你使用单位向量然后标准化反射,并设置它大小到新的速度

    • 同样适用于位移,因此粒子不会重叠

    • 你还可以计算出的组合动能矢量所有反弹的粒子并通过质量能量分布计算新的速度

        for(i = 0; i< particles; i ++) 
      {
      particle [i] .speed = compute_speed_from(particle [i] .reflect);
      }



[注意]




  • 最好是存储驾驶反射力

  • 很容易在它上面正确实现弹跳的物理模拟

  • 以及处理弹簧和其他东西

  • 如果你有永久债券,那么你可以在一些永久性碰撞清单中预先计算一次

  • 以提高绩效

  • bullet 2 可以使用没有碰撞列表但是它不是那么精确的一次多次跳出


I have many particles moving around and hit detection to see when they touch. If two particles touch they should bounce off in the opposite direction.

            particle.moveSelf = function() {
            var radians = this.angle * Math.PI / 180;

            var moveX = this.velocity * Math.sin(radians);
            var moveY = this.velocity * Math.cos(radians);

            for (var i = 0; i < particles.length; i++) {
                var distance = this.position.getDistance(new Point(particles[i].position.x, particles[i].position.y));
                //if distance < radius 1 + radius 2, bounce this circle away
                if (distance < (this.radius + particles[i].radius) && this.id !== particles[i].id) {
                    this.velocity = -this.velocity;

                }
            }

            this.position.x += moveX;
            this.position.y += moveY;
        };

When I run this code, the circles get stuck in each other moving back and forth by 1*velocity every frame.

There are lots of questions on how to work out the velocity or angle of the bounce but my problem is just that it gets stuck in an infinite oscillation.

解决方案

I done this before so here are some insights:

  1. the safest way is add list of collisions per each particle

    • in first pass you just detect the collisions
    • and clear/fill the collision lists with indexes of all particles that collide to each other

      for (i=0;i<particles;i++) particle[i].collide.clear();
      for (i=0;i<particles;i++) 
       for (j=i+1;j<particles;j++)
        if (colide(particle[i],particle[j]))
         {
         particle[i].collide.add(j);
         particle[j].collide.add(i);
         }
      

    • you can also do this with one list inside for (i=0;i<...) loop instead

    • but that is not that precise
  2. update position and speed of collided items only

    • now comes the tricky part
    • I add new direction vector to each particle and set it to zero
    • then add in each collision a reflection (unit or speed or force impulse) vector to it

      for (i=0;i<particles;i++) 
       for (j=0;j<particle[i].collides;j++)
         {
         // here compute reflected direction ,speed whatever of the bounce to vector dir
         particle[                       i].reflect+=dir;
         particle[particle[i].collide[j]].reflect+=dir;
         }
      

    • when it is done then just update the positions/speed ...

    • but you need add the stuff needed for update for example
    • if you used unit vectors then normalize reflect, and set it size to new speed
    • the same goes for displacement so the particles do not overlap
    • you can also compute the combined kinetic energy vector of all bounced particles and compute the new speeds form it via mass energy distribution

      for (i=0;i<particles;i++) 
         {
         particle[i].speed=compute_speed_from(particle[i].reflect);
         }
      

[Notes]

  • the best is to store driving reflection force
  • it is easy to implement physics simulation of bounce properly on it
  • and also for handling springs and other stuff
  • if you have permanent bonds then you can have them precomputed once in some permanent collide lists
  • to improve performance
  • bullet 2 can be used without collide list but then it is not so precise for multiple bounces at once

这篇关于模拟两个圆圈相互弹跳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆