Tuesday, 21 February 2012

More ball-wall collisions

The observant among you might have noticed that the ball in my last test app was only bouncing off the floor not the wall. I've fixed this in a new version of the app, which improves on the previous version in another significant way.

It now bounces off both both walls as well as the floor, using essentially the same code, which is compact enough to reproduce in full:

fBallV += fGravity;
fBallX += fBallU;
fBallY += fBallV;

if (fBallY > fMaxH) {
fBallY = 2 * fMaxH - fBallY;
fBallV *= -0.8;
iBounces++;
}
if (fBallX > fMaxW) {
fBallX = 2 * fMaxW - fBallX;
fBallU *= -0.8;
iBounces++;
}
if (fBallX < 0) {
fBallX = -fBallX;
fBallU *= -0.8;
iBounces++;
}

It essentially does the same for the walls as the floors, testing whether it has crossed the wall, putting it back on the other side and multiplying its speed in that direction to both reverse its direction and to take some energy out of it, using a coefficient of restitution of 0.8.

Note that to simplify the code still further the first line inside each block that puts it back on the right side of the wall or floor could be omitted. This lets the ball spend a frame on the wrong side of the boundaries, before its changed direction returns it to the right side. Whether this is acceptable depends on the game.

Because the ball now bounces off the sides it cannot use that to reset itself. So it resets after eight collisions or bounces. This also deals with another limitation of the code: its behaviour at small speeds.

The code is only approximate because it only updates the speed once a frame, not continuously. This can be seen in how it misses the target slightly, unlike the exact calculations in e.g. this version. But it causes a more significant problem as the ball loses energy and slows down. As it does so the collisions bunch together, eventually happening multiple times a frame which the code simply doesn't handle. Nor does it doesn't simulate the ball stopping or rolling, as would normally happen at the end of such a motion.

Limiting the number of bounces avoids this problem, and is a perfectly reasonable way to solve this. In all games I can think of the number of bounces is strictly limited, or they only continue if extra energy is contributed so the bounce height never goes to zero.

The updated app is included below. The old app with endless collisions (aim straight up to see them) is still here.