Remember that when you get into tweaking one particular game mode, it saves time to have the Pop program start up in the game mode that you want to play with. The way to control this is to edit the CPopDoc constructor in popdoc.cpp. Simply comment in exactly the one setGameClass line corresponding to the game you want to play. If you make a new game class, add a line for it.
A general principle in designing games is that things shouldn't happen abruptly. When an object is destroyed it shouldn't instantly disappear; instead it should show itself dying. Change Pop so that when you pop a bubble, it puts on a 'dying act.' You might do this by overriding the die methods by turning on a BOOL _dying flag instead of calling delete_me right away. And now override the animate(dt) method to shrink the bubbles. We might think of the bubbles as losing volume at some constant negative rate dV/dt called LEAKRATE. Since radius is proportional to the cube root of the volume, a little calculus reveals that dr/dt should be proportional to LEAKRATE/(r*r). So we do something like setRadius(radius() ? dt*LEAKRATE/(radius()*radius())) inside animate(dt). And when a bubble's radius gets below 0.0, then you actually call its delete_me method, so do a check something like if (radius() <= 0.0) delete_me. Call the base cCritter::animate (dt) too.
Show your jewels as spheres in the OpenGL graphics. Perhaps make the peanuts a 3D shape as well, maybe cubes. Do some OOA and OOD before you start coding, in particular, it would be a good idea to do Exercise 9.10: Three-dimensional sprites first.
What if we had a fourth kind of critter in our game? Let's say we have a small, slow-moving deathstar critter that bursts any jewel that it gets close to, but doesn't harm the peanuts. Maybe the deathstar should have a sprite like a star-shaped polygon. The place to have it kill the jewels would be inside the cGamePicknpop::collide code. Maybe make the deathstar non-draggable by overriding its draggable() to return FALSE.
Make the game more challenging by having the bubbles move away from the cursor. Do this by giving them a cForceObjectSeek with a negative acceleration. Add a static Real cGamePickNPop::FLEECURSOR multiplier to adjust the strength of the flight effect.
To keep them from getting too hyper you should probably use a cForceDrag as well.
Complete a Memory game as outlined above. To make it more interesting, allow the separate cCritterMemory to have _pspritehide that look slightly different from each other, and have the critters slowly move about.
Can you make a checkers game? Laying out the board and putting on the men should be easy enough. A little work would let you drag a man only to a legal position. The tough thing here is figuring out code to make the computer play back. See if you can find some easier kinds of board games to try and program.