2008-03-02

The Secret Posts - Now We're Getting Somewhere

(Written 02/02/2008)

Finally, some progress. There’s quite a lot of new stuff in the code now, so I’ll have to try and remember what I’ve added.

Following on from the ideas I had a few days ago, I’ve created “MovementEngine” and “CannonEngine” classes. The MovementEngine and its subclasses plug into the “GameSprite” class to provide movement. At the moment, I’ve got a “PlayerMovementEngine” written that watches the joypad and moves its container sprite around to match. It implements inertia, too. Using this system I’ll be able to write a range of movement engine subclasses that perform different types of movement - straight down the screen, sine waves, circles, etc - and plug them in and swap them around whenver I like. I’ve created a “MathTools” class with a sine lookup table and a few accessor functions in preparation for intricate movement patterns.

I encountered another problem with the GP2x’s design whilst writing the PlayerMovementEngine class. I’d initially got a standard SDL event switch() statement set up to determine which buttons were pressed and released. It works when the hardware implements a sensible 4-way d-pad, but it breaks when used with the GP2x’s 8-way pad.

The GP2x joypad defines include “GP2X_BUTTON_UP” and “GP2X_BUTTON_LEFT”, which make sense, but they also include “GP2X_BUTTON_UPLEFT”. The latter is triggered when both up and left are pressed at the same time. This is problematic because triggering a “down” event on the “UpLeft” button also triggers an “up” event on the “Up” and “Left” buttons. The sequence of events looks like this:

  • User presses and holds “Up”
  • Down event triggered for “Up”
  • User presses “Left”
  • Down event triggered for “UpLeft”
  • Up event triggered for “Up”

If we map both “Up” and “UpLeft” to a single “up” state variable in our code, the final event means we can’t tell what really happened to the “Up” button. We lose track of its state.

Instead of using events, I resorted to using “SDL_JoystickGetButton()” instead. It’s a much better solution, because the joypad code is now completely encased within the PlayerMovementEngine class.

The second Engine idea was the CannonEngine. This was originally called “BulletEngine” until Dunk pointed out that it’s not a bullet; it’s a firing mechanism. No subclasses yet, but this will let me have all kinds of different bullet patterns. I’ll need a “PlayerCannonEngine” that watches the GP2x’s fire buttons and responds appropriately.

I’ve added another engine in - the “RenderEngine”. This is another sprite plugin that provides the drawing functionality a sprite needs. There are now two subclasses of this. One is a wrapper around the Animation class, meaning I can have animated sprites with no effort. The second provides storage space for a number of bitmaps and lets the coder choose which one to display. This will allow the helicopter to display its tilt frames just by telling the renderer to switch to a different bitmap.

This combination of plugin modules gives me enough functionality to get some sprites working. The game has a “Chopper” class that represents the player’s helicopter, which now moves around the screen. It also has a “Rocket” class that represents the SAM, which will be one of the simplest enemies. I’m quite pleased to see that the rotation frames I drew for the rocket look good when animated. The helicopter blades are modelled as a “Blades” class that belongs to the chopper, and they too look great when animated.

The ParticleEngine class now has a “createSmokeTrail()” function that (if called every VBL) creates a particle-based trail of smoke behind a sprite. The trail moves in the opposite direction to the sprite that created it. Should look good when attached to the back of the SAM.

I’ve done a lot of refactoring. All of the code for working with SDL, such as initalisation and shutdown, is now contained within an “SDLTools” class. The SDL screen surface pointer is stored in there so that I don’t have to create a new surface for the title screen and any other non-game sections. Bitmaps are preloaded from the SD card when the game is initialised by a new “BitmapServer” class. It stores them in an array that can be accessed via a static method by any other class.