问题
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:
I done this before so here are some insights:
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
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
来源:https://stackoverflow.com/questions/26455960/simulating-two-circles-bouncing-off-each-other