Abe Getzler
This is a simulation of ball collision in the case where the cue ball hits a stationary target ball.
(The project name came from my initial attempt to launch the cue ball
from a slingshot. I gave up on that mechanic, but kept the cute name.)
The cue stick, cue ball, and target ball can all be dragged around to
set up shots.
This is a partial result. It only works for collisions against stationary balls.
That's why I called it V2.
Screen shot
Designer
The screen components include a canvas with a cue stick, cue ball, and target ball, plus controls. The controls include a speed slider, and four buttons: Reset, Shoot, Pause/Resume, and Options (speed). For debugging, there’s a List Picker to show a log of calculations.
The draggable cue stick, cue ball and target ball let you set up shots
The cue stick always points to the center of the cue ball when dragged:
Its graphic is a 2 by 100 bar, given a 4 by 100 size to make it easier to grab.
We keep track of all our balls at initialization time…
Resetting the board…
The four buttons: Reset, Shoot, Pause/Resume, Options …
The Options button reveals a speed slider.
Pause/Resume
The Pause/Resume button is used to Pause and Resume alternately, depending on its Text.
⦁ To Pause, it collects the balls’ speeds, saves them in a list with their components, and sets their speeds to zero.
⦁ To Resume, it goes through that list of saved balls and speeds, and resets the balls’ speeds from their saved values.
The Shoot procedure sets the pool cue in motion towards the cue ball.
When the cue stick hits the cue ball, transfer its speed and direction to the cue ball …
We make the pool cue invisible and disable it so it doesn’t interact with other balls.
This also helps to hide the pool cue stabbing thru the cue ball, though you can catch a glimpse of that happening if you are quick.
To avoid a cannibalism effect, we keep a list of balls that are in the midst of a collision. This will be used to stop multiple CollidedWith blocks from handling the same collision.
When the collision is over, remove the balls from the colliding balls list …
When balls hit the edges of the canvas, have them bounce off the walls.
There’s a bug here - when a ball hits a corner it sticks to the corner. If there were a “DepartedEdge” block I might be able to deal with it. It’s no big deal for a little demo like this.
When the pool cue hits the cue ball, we give the cue ball the speed and heading of the pool cue, then remove the pool cue from action.
Ball Collisions
Collision of balls is handled by a procedure that accepts as arguments the two colliding balls’ components. For this simplified case we deal only with a cue ball hitting a stationary target ball.
We will ignore collisions with balls that are already colliding, as recorded in the colliding_balls list.
We add the two colliding balls to the colliding_balls list, and leave it to the NoLongerColliding blocks to “uncollide” them from that list.
First half of the bounce procedure
We send the target ball off in the direction of a line from the cue ball to the target ball. This is done the easy way, by using the Ball.PointTowards block to point the target ball towards the cue ball, then reversing the target ball’s heading by subtracting 180 degrees from it.
Normalizing directions to avoid anomalies
The expression of directions as degrees is problematic, because there is always a place on the dial where there will be a discontinuity, the same way the International Date Line can cause air travelers in the Pacific to gain or lose a day by crossing this imaginary longitudinal line.
We will choose between two different normalization schemes to express our angles, to keep the discontinuity behind the cue ball so it doesn’t mess up our bounce calculations.
⦁ Normal180 will bring an angle into the range -180 to 180. This good for directions heading to the right of the canvas.
⦁ Normal360 will bring an angle into the range 0 to 360. This good for directions heading to the left of the canvas.
We add or subtract 360 degrees to our input angles to bring them into our desired ranges.
We will package up the choice between these schemes in a single normalization procedure:
Second half of the bounce procedure
The angle of incidence is defined as the angle between the incoming cue ball direction and the outgoing target ball direction.
We then transfer some speed from the cue ball to the target ball, taking care to conserve energy and momentum in the x and y directions. For a frictionless spinless collision with a stationary ball of equal mass and size, the speeds are proportional to the sine and cosine of the angle of incidence. ((sin(theta))^2 + (cos(theta))^2 = 1)
The cue ball heads off at right angles to the target ball heading in this special case, heading off to the left or right (+/- 90 degrees) depending on which side of the target ball it hit, as measured by the sign of the angle of incidence.
To avoid a negative speed for the cue ball, we take its abs() value.
Intermediate angles are logged at three stages of this process for debugging.
Feel free to copy this with attribution.
Source code …
angry_balls_v2.aia
This doc …