
Two Balls in a Confined Area
 The two dots in motion look like they are bouncing off each other
and the rectangular boundary as if they are two balls of equal mass
rolling on a frictionless billiard table. How is this done? Consider
easy things first. There is a thread that recomputes ball positions
based on ball velocities and redraws the balls on the table every 25
milliseconds. Suppose the balls are in an array created by
Ball balls[] = new Ball[2]; // Array of Balls
Each ball is initialized (by the constructor) with a random horizontal
velocity component, a random vertical velocity component, and
x and y position. These are accessed via
balls[a].vx // horizontal velocity, ball 'a'
balls[a].vy // vertical velocity, ball 'a'
balls[a].x // horizontal position, ball 'a'
balls[a].y // vertical position, ball 'a'
respectively. Both balls have the same diameter which is given by
variable ballDia. It is easy to compute the next position of
a ball given its current velocity and position if the ball does not
hit anything. Just do this:
balls[a].x += balls[a].vx*time;
balls[a].y += balls[a].vy*time;
where time is some constant factor that exists to make
adjustments easy. It is also fairly easy to bounce a ball off a
boundary: if it bounces off a vertical boundary its horizontal
velocity is reversed and if it bounces off a horizontal boundary its
vertical velocity is reversed. But first it has to be determined
whether it hits a boundary. This is done by computing the distance
from ball center to the boundary and, if the distance is less than
ballDia/2, a velocity is reversed. The test, and change if
needed, looks like this for the left vertical boundary:
if (balls[n].x <= ballDia/2 ) {
balls[n].x = ballDia/2;
balls[n].vx = balls[n].vx;
}
which reverses the horizontal velocity and 'cheats' by repositioning
the ball flush against the boundary. This turns out not to present a
problem for the viewer because the change from what the actual
position would be is quite small.
 Now we get to the hard part: how to deal with balls hitting each
other. This actually would be quite simple if the direction of the
balls is exactly the same and is also the same as the direction of an
imaginary line connecting the centers of the balls. In that case the
velocities would switch! Seem strange? Try it! Roll a ball at a
stationary ball so that it hits dead center. The stationary balls
takes the velocity of the hitting ball and the hitting ball comes to a
stop (I am sure you have seen this demonstration many times).
Similarly, if the target ball is moving away or toward the throw  the
velocities switch. Generally, the balls do not hit dead center. But
we can transform the horizontal and vertical velocities of the balls
to velocity components that are perpendicular to a line between
centers and parallel to that line. The perpendicular components will
not change. The parallel components change as stated about. The
change is a simple switch. Then it is necessary to transform back to
horizontal and vertical velocity components. The following code does
all this between balls 'a' and 'b'.
// find cos and sin of angle between centers line and horiz
double dx = (balls[a].xballs[b].x);
double dy = (balls[a].yballs[b].y);
double dist = Math.sqrt(dx*dx+dy*dy);
double sinalpha = dy/dist; // sin of angle of centers line
double cosalpha = dx/dist; // cos of angle of centers line
// find velocity components parallel to and perpendicular
// to the centers line
double vapara = balls[a].vx*cosalpha + balls[a].vy*sinalpha;
double vaperp = balls[a].vx*sinalpha  balls[a].vy*cosalpha;
double vbpara = balls[b].vx*cosalpha + balls[b].vy*sinalpha;
double vbperp = balls[b].vx*sinalpha  balls[b].vy*cosalpha;
// Switch
double temp = vapara;
vapara = vbpara;
vbpara = temp;
// Reestablish x and y velocity directions
balls[a].vx = vapara*cosalpha + vaperp*sinalpha;
balls[a].vy = vapara*sinalpha  vaperp*cosalpha;
balls[b].vx = vbpara*cosalpha + vbperp*sinalpha;
balls[b].vy = vbpara*sinalpha  vbperp*cosalpha;
