Probably the most important method in cGame is step(Real dt). This is the method that controls the animation of the critters. First we'll outline the order in which step does things, then we'll explain why we use this order, and then we'll go over the outline again.
Updating a simulation of multiple objects is a delicate thing. You need to do things in the right order, and you need to try and have the objects being updated in parallel, but all at the same time. For this reason, step is not a virtual method of cGame ; you are not supposed to override it. (All rules have exceptions, though. If you really want to override it, change it to a virtual!)
Here's what step does in brief.
Adjust. Adjust game parameters. (Game over? Need to reseed? Change levels?)
Listen. Pass recent user input to the critter feellistener methods, particularly to the onscreen player critter. (Use keypresses, mouse actions.)
Move. Call the critters' move methods to keep physics working.
Update. Call the critters' update methods to let the critters react to their environment.
Collide. Check for and compute the collisions between pairs of critters which are sensitive to touching each other.
Clean up. Remove any critters ready to die, and add any new ones that have been requested.
Animate. Possibly animate the critters' sprites. (Flip-book, rotate, morph, etc.)
Draw. After each call to step, all of the critters get drawn to the active views.
Why does the Pop Framework use this particular order of doing things?
Adjust comes first. It's reasonable to make any overall adjustments to the game at the start of each step, as there's no point continuing with a step if we're about the change the rules.
We want the onscreen player critter to have the most immediate possible response to the user's actions, so we do the move step right after the listen step.
After all the critters have moved, have them 'look around' and respond to their new positions. The looking-around process has two phases, the update phase and the collide phase.
The update and collide methods can be overridden to tell critters to die, and to tell critters to spawn off new critters. Once all these requests are in place, we process them right away with the clean up stage. Certainly if some critters are dead, we want to get rid of them right away before drawing them.
The animate step does some matrix work to bring the sprite's appearance into line with the critter's latest orientation. Clearly we want to do this before drawing, and we want to do it after having removed any dead critters and adding any newborn critters.
Now let's take a more detailed look at the sequence of events in the cGame::step process.
Adjust. The game parameters are adjusted, usually on the basis of the score and the number of critters. Possibly the _gameover flag is turned on. Perhaps the critter population needs to be reseeded, or the game should be switched to a new 'level' mode.
Listen. Before step was called, the CPopView passed any keyboard or mouse messages to the cGame. The cGame has reacted by putting these messages into a cController _pcontroller member. In addition, the timestep dt since the last full update is fed into the step as an argument.
Any interested critters use feellistener to listen to any keyboard or mouse messages. This may change the critters' acceleration, velocity or position. Commonly the only visible critter that has a non-trivial listener is the player.
Move. Each critter does a move(dt). This changes the critters' age, velocity, position, and outcode.
Update. Each critter updates itself by calling feelforce to react to its various _pforcearray members. It may react to the other critters' positions. The update may change the critters' acceleration or velocity. The critter may also make a 'service request' to be deleted or to create a new critter, as when a critter is shooting bullets from a gun.
Collide. Each pair of touching critters that has been registered to the game's cCollider object generates a call to a cCritter::collide(cCritter *pcritterother) method which changes the position and velocity of the two critters involved.
Clean up. The service requests from the update stage are processed, possibly deleting some critters and constructing some new ones. The method used is cBiota::processServiceRequests.
Animate. Each critter and its sprite are optionally tumbled or animated in some other fashion.
Draw. And then the CPopView::OnDraw is called to draw the critters on the screen.
Let's draw a sequence diagram (Figure 10.1) for some of this. Keep in mind that the cBiota is an array collection which holds some array walking methods. In addition, cBiota holds a queue of 'service requests' posted during the update phase. We don't really put in any details about the collide process yet.