Learning and Applying Mathematics using Computing

In this post we will continue building our pool game. One of the aspects of a pool game that we will need is the ability for the balls to bounce off the edges/cushions of the table (which I’ll refer to as walls).

Simple Bouncing

If a wall is horizontal or vertical, there is a very simple way to implement bouncing off it, which many programmers figure out quite quickly. If you want to bounce off a horizontal wall (e.g. top or bottom of the screen), simply reverse your Y velocity. If you want to bounce off a vertical wall (e.g. left or right edge) then reverse your X velocity. These are actually two specific cases of the more general problem of bouncing off an arbitrarily-angled wall.

Any Which Way But Loose

The basic principle when bouncing is that the angle at which you hit the wall (orange line) should be mirrored when you bounce off (blue line):

The dotted line protruding perpendicularly from the wall, which acts as the mirror, is called the surface “normal”. Let’s rotate the wall and incoming angle and work out what the outgoing angle should be:

So, we have the incoming angle (which is calculated using the start of the incoming orange line, at the top left). We will assume we have the angle of the normal. What we want to know is the outgoing angle. If we label the gap between the incoming/outgoing as “diff”, then it’s fairly clear that:

\text{outgoing} = \text{normal} - \text{diff}

So, how do we work out diff? Well, we can calculate the angle at the end of the incoming arrow quite simply: it’s 180 degrees away from incoming. Then we can see by looking at the point of impact that:

\text{diff} = (180 + \text{incoming}) - \text{normal}

So overall, expanding this out:

\text{outgoing} = 2 \times \text{normal} - 180 - \text{incoming}

It’s a simple matter to implement straight-line walls that perform this collision resolution by bouncing balls using the normal angle:

        for (Wall w : (List<Wall>)getObjects(Wall.class))
            if (w.intersectsCircle((int)newX, (int)newY, b.getRadius()))
                double angle = Math.toDegrees(Math.atan2(vy, vx));
                int normalAngle = w.getNormalAngle((int)newX, (int)newY, b.getRadius());
                angle = 2 * normalAngle - 180 - angle;
                double mag = 0.9 * Math.hypot(vx, vy);
                vx = Math.cos(Math.toRadians(angle)) * mag;
                vy = Math.sin(Math.toRadians(angle)) * mag;


The cushions on a pool table are not solely straight-lines, however. Next to the pockets, you have rounded sections: the jaws. I’m going to conceive of these sections as quarter-circles, as that makes the maths more straightforward. So we might have a situation like this, where the ball should bounce off the jaws:

We can use the same calculation for resolving bounces as before — we just need a surface normal angle. Well, the surface normal for a circle is actually trivial: it always points away from the centre of the circle, you just have to work out where you hit the edge. So using our previous diagram, the normal angle is just the angle pointing from the centre of the jaw quarter-circle towards the centre of the ball:


I’ve added some pockets to the scenario using some very simple maths: a ball goes in the pocket if its centre is over the pocket (not merely if part of the ball is over the pocket). You can have a play with the live scenario on the Greenfoot site — the cue ball heads towards the mouse when you click it. I may need to adjust the size of the pockets though, it may end up a bit hard to pocket anything!


Comments on: "Bouncing Off The Walls" (1)

  1. […] In a previous post we saw one way to bounce a ball off walls, by using angles and rotation. In maths, there are often several ways to approach a problem, with different techniques that can be used to achieve the same result. In this post, I’m going to solve the same problem of bouncing off the walls, but using a different technique: the dot product. […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s