|
|
|
PgPoolGameShellPgPoolGameShell is the shell presenter for the CoolPool sample application. The application uses a single CcOpenglView to render a view of a pool table and enclosing room. Keyboard input is based on the Dolphin event mechanism. The game makes use of CcToolManager and CcSelectionManager for ball and cue stick selection and manipulation via the mouse. An instance of CcTimer is used to control the animation process. PgPoolGameShell is responsible for initializing scene components and keystroke mappings, responding to keyboard input and menu commands, and starting and stopping the animation process. The shell uses an instance of PgPoolEngine to control ball movement and perform ball-to-ball and ball-to-bumper collision detection. PgPoolEngine, in turn, uses an instance of CcBallCollisionDetector to find the ball-to-ball collisions. During initialization, PgPoolGameShell loads the pool table and room from disk (see roomTable2.stb) and adds them to the root node of its scene graph. It then initializes the balls and cue (subinstances of CcQuadricShape) and applies appropriate textures. Balls are then set into their "racked" positions (see #rackEmUp). The game operates in two distinct modes. In the first mode, the animation process is controlled by timer ticks generated by the CcTimer and keyboard input is disabled. This mode is active when 1) at least one ball on the table is in motion (has a non-zero velocity) or 2) when the camera is automatically being aligned with the cue ball following a shot or 3) when a cue stroke is in progress. When none of these conditions is met, the game is in its second mode where the CcTimer is disabled and animation, if any, occurs as the result of keyboard events generated as the user positions the viewpoint within the scene or adjusts the orientation of the cue. When the game shell first opens, all balls are stationary and the viewpoint and cue can be positioned with the keyboard. If the shell is subsequently sent the message #break, a cue stroke operation is started (see #animateCueStroke) and the CcTimer is activated. When the cue stroke is completed, the shell receives the message #shoot: which sets the cue ball in motion. Once the cue ball has reached the vicinity of the racked balls, the racked balls are given their break velocities. The animation process continues under the control of the CcTimer until all balls have come to rest. PgPoolGameShell receives the message #timerTick: each time a tick event is generated by the CcTimer. PgPoolGameShell>>timerTick: determines the time elapsed since the previous timer tick and, with the assistance of PgPoolEngine, updates the state of the balls based on that interval. It also checks to see if all balls have come to rest and, if so, disables the timer (Note: methods #activateTimer and #deactivateTimer on PgPoolGameShell ensure that keyboard input is ignored while the timer active). After the state of the balls has been updated, #timerTick: refreshes the view.
Collision DetectionFor every #timerTick: message it receives, PgPoolGameShell sends the PgPoolEngine message #advanceStateBy:. The message argument is the interval of time by which the engine is to advance the state of the balls. The engine accomplishes this by determining the series of collisions that will occur during the interval and adjusting ball positions and velocities accordingly. The steps involved in this process are as follows (remember that a balls velocity includes both direction and magnitude):
In addition to performing collision detection, the engine decelerates ball velocities as they roll across the table and checks to see if any balls have rolled into a pocket. The engine also generates sound effects for ball-to-ball collisions. |