Simulating two circles bouncing off each other

2019-06-09 03:03发布

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.

1条回答
做自己的国王
2楼-- · 2019-06-09 03:23

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
查看更多
登录 后发表回答