Monday, 19 March 2012

Ball-ball collisions

In this post I discussed how to handle collisions in general, at least when one of the objects is a ball for collision purposes. My intention was to follow it up with an example but I never got around to it. Well now I have, and it shows how to turn the theory in that post into practice.

The demo app is here. It is based on my previous ballistics app with one addition, a slightly off-centre fixed circle which the ball bounces off as well as the walls. This is simpler than having two moving balls but not by much as the calculations are the same up to a point.


The main code change (apart from initialising and drawing the circle) is the following few lines.


var fDX:Number = fBallX - fColX;
var fDY:Number = fBallY - fColY;
var fDist:Number = fDX * fDX + fDY * fDY;
var fRSum:Number = fSize + fColR;


if (fDist < fRSum * fRSum) {
fDist = Math.sqrt(fDist);
fDX /= fDist;
fDY /= fDist;
var fApproachSpeed:Number = -(fDX * fBallU + fDY * fBallV);
if (fApproachSpeed > 0) {
fBallU += fApproachSpeed * fDX * 1.9
fBallV += fApproachSpeed * fDY * 1.9;
}
}

Initially it checks whether the circles overlap using Pythagoras's theorem. fDist at this point is the square of the distance between the centres, and this is compared with the (square of the) sum of the radii as the circles overlap if the distance between the centres is less than this.

fDX and fDY are then scaled by the length of the vector (fDX, fDY), to normalise this vector, generating a unit vector. This is the normal vector n in the theory. The normal vector in this case can't be pre-calculated, it has to be determined on the fly. This is common though, especially once rotation and friction are incorporated into such systems.


The dot product of n with the ball's velocity gives the approach speed s. This is compared with zero to make sure the ball is approaching (if moving nearly parallel to the fixed ball it could move within range but already be separating from it. Not doing this check would then pull one ball into the fixed one).

The last two lines calculate the new velocity by adding the product of sn and (1 + e), where e is the coefficient of restitution. In this case the coefficient of restitution is 0.9, increased slightly so it will bounce more often before coming to rest. It doesn't do anything to move the ball out from the surface, but this could easily be added.


Everything up to the last two lines is the same if two balls are moving. For two moving balls two velocities need to be updated and the masses of the balls needs to be taken into account.


As before this ignores friction and rotational effects, including air resistance. But as before provided the simulation does not go on for too long (so it doesn't come too close to coming to rest) it works very well. The application is available on Wonderfl, where the code can be examined and forked, and embedded below.


No comments:

Post a Comment