I have a program which simulates many bouncing balls. The balls can bounce off each other and off the sides of the container.
The problem I am having is that sometimes when two balls collide, they get stuck together, overlapping very slightly. They will not come apart on their own, but may disperse if another ball knocks into them.
Here is my collision detection and resolution code:
public void handleCollisions(){
double xDist, yDist, distanceBetween;
for(int i = 0; i < balls.size(); i++){
Ball A = balls.get(i);
for(int j = i+1; j < balls.size(); j++){
Ball B = balls.get(j);
xDist = Math.abs(A.getCenterX() - B.getCenterX());
yDist = Math.abs(A.getCenterY() - B.getCenterY());
distanceBetween = Math.sqrt(xDist*xDist + yDist*yDist);
if(distanceBetween <= (A.radius + B.radius)){
double dx = A.getCenterX() - B.getCenterX();
double dy = A.getCenterY() - B.getCenterY();
double collisionAngle = Math.atan2(dy, dx);
double magnitudeA = Math.sqrt(A.xVel*A.xVel + A.yVel*A.yVel);
double magnitudeB = Math.sqrt(B.xVel*B.xVel + B.yVel*B.yVel);
double directionA = Math.atan2(A.yVel, A.xVel);
double directionB = Math.atan2(B.yVel, B.xVel);
double xVelOnCollisionAxisA = magnitudeA*Math.cos(directionA - collisionAngle);
double yVelOnCollisionAxisA = magnitudeA*Math.sin(directionA - collisionAngle);
double xVelOnCollisionAxisB = magnitudeB*Math.cos(directionB - collisionAngle);
double yVelOnCollisionAxisB = magnitudeB*Math.sin(directionB - collisionAngle);
double postCollisionXVelA = ((A.mass - B.mass)*xVelOnCollisionAxisA + (B.mass*2)*xVelOnCollisionAxisB) /(A.mass + B.mass);
double postCollisionXVelB = ((A.mass*2) * xVelOnCollisionAxisA + (B.mass - A.mass)*xVelOnCollisionAxisB)/ (A.mass + B.mass);
A.xVel = (Math.cos(collisionAngle)*postCollisionXVelA + Math.cos(collisionAngle+Math.PI/2)*yVelOnCollisionAxisA);
A.yVel = (Math.sin(collisionAngle)*postCollisionXVelA + Math.sin(collisionAngle+Math.PI/2)*yVelOnCollisionAxisA);
B.xVel = (Math.cos(collisionAngle)*postCollisionXVelB + Math.cos(collisionAngle+Math.PI/2)*yVelOnCollisionAxisB);
B.yVel = (Math.sin(collisionAngle)*postCollisionXVelB + Math.sin(collisionAngle+Math.PI/2)*yVelOnCollisionAxisB);
}
}
}
}
So essentially, the method iterates through all possible combinations of two balls. If the distance between them is less than the sum of their radii then a collision is detected and the velocities of each ball are changed.
The next method to run will update the positions of the balls, before the above method is called again.
It appears that my problem occurs when a collision is detected, but on the next pass of the function, the ball is still seen as being inside the other ball and receives a collision whilst trying to get out.
I have tried adding this code when a collision is detected. I expected this to solve the problem by moving the balls to their last position before the collision, but the problem persists
A.posX -= A.xVel;
A.posY -= A.yVel;
B.posX -= B.xVel;
B.posY -= B.yVel;
Actually for multiple balls, I'm not sure the above snippet is a good idea anyway.