modeling billiard table

modeling billiard table

Post by Dean War » Mon, 21 Mar 2005 11:09:14

I am trying to construct a model for use in a video game

Basically I have boiled things down to the following situation that needs to
be modelled:

Think of a snooker/pool table (without the pockets) with two balls on it.

The balls bounce around colliding with the sides of the table and each
other. Perfectly elastically for simplicity.

For further simplicity, there is no friction. Maybe they have unit mass.

Basically picture two circles bouncing around inside a rectangle.

My question is:


1) the dimensions of the rectangle and the circles.

2) the initial velocities of the circles

Is there an equation where I can find the location of the circles at time t?


circle_one_centre(x,y) = f(t)

circle_two_centre(x,y) = f(t)

If so, how do i go about finding this equation?

what about the same thing for n circles?

Different shaped tables??

Any ideas?

Thanks for any help


modeling billiard table

Post by Bill9 » Mon, 21 Mar 2005 15:49:15

I wouldn't expect one, especially if you are allowing for collisions. Start
by thinking about 1 ball bouncing around by itself. Decide how long the
ball will be in motion (and at what velocity) and use a loop to track its
position (iterating every 10th of a second, say).

Good luck, Bill


modeling billiard table

Post by Evan » Mon, 21 Mar 2005 17:01:49

don't think so. What you can do though is to break up the path into a
series of discrete chunks. You don't have to do it like Bill97 says
though, checking the position every short interval of time, because the
only time the equation changes will be when it collides with something.
(Though if there are a lot of balls that might be the easiest way.)

Look at just one ball bouncing around for a minute. Let's set up a
couple variables:
- x will be the current x location of the ball (say that x is the
short distance)
- y is the current y position of the ball
- width is the x dimension of the table
- height is the y dimension of the table
- v is the velocity of the ball
- a is the angle the ball is traveling (0 will be positive x and no y;
90 is positive y and no x; I'm actually going to use v and a at the
very beginning then ignore them)
- t is the current time

The table is set with a corner at (0, 0) and extending into the first
quadrant. I'm using real coordinates, not the reversed y axis you see
in CG a lot. ;-)

Furthermore, we assume one of two things: either the ball has zero
radius or the variables width and height should be increased by the
radius, and the whole table offset by r/2 left and down. In other
words, if the ball is sitting at (0,0) it should be touching the left
and bottom sides, and if it is at (width, height) it is touching the
right and top sides.

If we ignore the edges, the position of the ball can be found as
follows (I'm gonna use a bunch of temporary variables from here on to
make this clearer to both me and you):

The x component of the velocity is vx = v*cos(a)
The y component of the velocity is vy = v*sin(a)

Thus x(t) = x + vx*t and y(t) = y + vy*t.

But this only holds until it hits the side, so we have to find when
this will occur:

If the ball will hit the right rail, it will happen at tr = (width -
If the ball will hit the left rail, it will happen at tl = -x/vx
Similarily tt = (height -y)/vy and tb = -y/vy

So we have these equations holding until t reaches reaches the minimum
of the appropriate x choice and the appropriate y choice:
tm = min( (vx > 0) ? tr : tl),
(vy > 0) ? tt : tb) );

At that point, it hits the rail(s) so we bounce it by flipping the
velocity of the appropriate direction(s):
if( tm == tl || tm == tr) vx = -vx;
if( tm == tt || tm == tb) vy = -vy;

(Note that these both might be true if it hits the exact corner, so you
can't use else if)

Then repeat. (You'll need to make allowances for vx or vy being 0.)

So we have an algorithm for computing the position at time t (I'm
assuming height and width are global constants):

pair<double, double> position(double t, double x, double y, double v,
double a)
double vx = v * cos(a);
double vy = v * sin(a);

double t_until; // tm above

if( t_until == t_left || t_until == t_right) vx = -vx;
if( t_until == t_top || t_until == t_bottom) vy = -vy;

double t_right = (width - x)/vx;
double t_left = -x/vx;
double t_top = (height - y)/vy;
double t_bottom = -y/vy;

t_until = min( (vx > 0) ? t_right : t_left),
(vy > 0) ? t_top : t_bottom) );

} while (t + t_until > t_max);

return make_pair( x + vx * t, y + vy * t);

(This won't work if a = 0, 90, 180, 270, ..., or if the

modeling billiard table

Post by Evan » Mon, 21 Mar 2005 17:05:32

D'oh, move the lines that swap the directions AFTER the four 'double
t_<rail name> = <blah>' lines....

modeling billiard table

Post by Chris Crou » Mon, 21 Mar 2005 20:32:38

On 20 Mar 2005 00:01:49 -0800, Evan

It's worse than that (it's dead, Jim!). The resultant trajectories of
balls with non-zero size colliding deoends on where they hit as well as
the velocities involved. A 'clip' or 'graze' has a very different
effect from a collision where the two centers of mass are on the same
line as the relative velocity, even assuming that the balls have no
friction between each other.

If you are doing a complete simulation of friction, there is a residual
value which still acts at zero speed so things will come to a complete
stop in the Real World(tm) as well (ignoring molecular and atomic
motions). Friction is decidedly non-linear.

Friction between balls on glancing shots will also introduce spin (and
spinning balls colliding will be an 'interesting' (in the sense of the
curse) exercise).

Nor do they bounce off other things in expected ways.

I think the phrase is "The rest is left as an exercise for the reader"

(There is probably a better newsgroup as well, one on games algorithms
possibly. It's not a C++ problem, anyway, it's a physics one, possibly
some of the sci.* newsgroups will have answers to some of the

Chris C

modeling billiard table

Post by Thomas Mat » Wed, 23 Mar 2005 23:23:12

A better method is to convert the table into a coordinate system.
Give each ball a location.
In your simulation, just query each ball's location.

_I_ would create a ball class that has properties of the ball,
such as magnitude and velocity as well as current position.
Add some methods for calculating the next position as well
as some methods for bouncing off of the rectangle and
intersecting with other balls.

Let your simulation work in chunks of time, dt (the difference in
time or lenght of a chunk). Add methods to the ball to calculate
its next or current position based on dt. The main loop would
call this method for each ball. You could also add some display
methods too, which would erase their old position and draw themself
at the new position.

In summary, I believe the simulation will be easier if you
think in terms of time chunks. Think of what needs to be performed
during one slice or chunk of time. Think not of trying to figure
out how to perform a window or subscript of the big picture.

Thomas Matthews

C++ newsgroup welcome message: ~shiva/welcome.txt
C++ Faq: ++-faq-lite
C Faq: ~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
Other sites: -- C++ STL Library book