Diary Of A Game: Hot Pursuit: Part 1
Introduction
Welcome, Ladies and Gentlemen, to the first peek inside the development of a game called Hot Pursuit. Over the coming parts, I will take you on an adventure into the world of game development. I'm certainly no expert on the subject, so you'll find that we'll probably run in to numerous issues, but hopefully we'll make it out the otherside with a playable and enjoyable game.
Technologies and setup
I am primarily a Windows developer and user, so my setup will running off Windows, using Microsoft Visual Studio 2008.
However, the Pandora (and by extension, Linux) are being considered in the development process.
So, what am I using:
BASS might yet be exchanged for the Allegro library, which will reduce a dependancy, but I need to look at the API a bit more.
Game Engine Structure
Engine Flow
The design goal was to try and build a very modular engine than would allow easy interchange of libraries and functionality. However, such things get awfully complicated, and I usually get myself in a tangled mess, and end up scratching the project. So I need to maintain some flexibility, whilst making sure I don't get too bogged down in the engine. Allegro became the "core" because I've used it in a couple of games, and am very comfortable with it. Hopefully I'll be able to find somebody able to make a nice Pandora compile for me (watch out for a bounty in the near future).
So, with Allegro chosen, I wanted to be able to seperate various parts of the game out, so I created a class called Stage (shown below), and I created a LIFO (Last In, First Out) stack class, that is at the very heart of the engine.
class Stage
{
public:
// Stage control
virtual void Begin() = 0;
virtual void Pause() = 0;
virtual void Resume() = 0;
virtual void Finish() = 0;
virtual void Event(ALLEGRO_EVENT e) = 0;
virtual void Update() = 0;
virtual void Render() = 0;
};
A stage will be a specific portion of the game, and will only control information within it's boundaries. For example, there will be a Title Screen stage, which displays the game logo, plays the title music, and waits for a key. Once pressed, it will add the a Menu stage to the stack (more on the stack shortly). The Menu stage will display options and read the user input to select the required options, and load the additional stages based upon the option selected.
So what does the stage stack do? It maintains a list of active game stages, however, the game engine will only process the stage at the very top of the stack. So this means that when you start a new Game, the Menu stage will still be "available" underneath the new game, that when you quit, it will revert back to the Menu in exactly the same state you left it.
There are pros and cons to this method. The biggest con is that all stages will continue to consume memory, even whilst they are sat in the back burner. Technically you could still unload all the resources (music and graphics) reducing this, but the stage overhead will still be there. However, benefits to this method, means you can pause/interrupt game play, by pushing a new stage, but return to the game exactly where it was after the new stage has finished.
Game and UI Objects
Rather than write lots of code to draw all my pictures and text, I decided to create an abstract class called Entity that I will use as the core of everything related to the game; such as on-screen text, images, game pieces.
class Entity
{
public:
Entity(void);
~Entity(void);
vector3 Position;
rotation Rotation;
virtual void Update() = 0;
virtual void Render(vector3 CameraPosition, rotation CameraRotation) = 0;
};
So what's going on here? Well, everything is going to have a location (up to 3 dimensions), and a rotation (pitch, yaw and roll). At the minute, I'm not intending to use pitch or roll at any point, even when the 3D graphics come in, however, they are there for the sake of completion. Update and Render will be called from the Update and Render functions of the currently running stage. The stages must be coded to call these, but that's as simple as
void GameStage::Render()
{
int idx;
if( gameElements.size() > 0 )
{
for( idx = 0; idx < gameElements.size(); idx++ )
{
gameElements[idx]->Render(CameraPos, CameraRot);
}
}
if( uiElements.size() > 0 )
{
for( idx = 0; idx < uiElements.size(); idx++ )
{
uiElements[idx]->Render(CameraPos, CameraRot);
}
}
}
You'll see there are two loops here, one to make draw game items (such as the world, cars, etc.) and the other for the HUD and other user interfaces (score, lives, etc.). The code currently lacks any z-ordering, but we will tackle this later.
You may have also noticed that the render function accepts two inputs related to the "Camera". This can be used so that entities themselves can determine whether or not to draw, and what exactly to draw. I think this will be useful when switching to 3D, but hope it doesn't complicate things in the mean time. Time will tell.
Current Progress
At the time of writing, I have a number of basic classes covering humans, vehicles, scenery, and bullets. I have a demo running on Windows where you can drive the car around the screen with some UI elements being rendered above.
Late Addition: There's been some additional information on the boards from Pickle and sebt3 about using GLES. Prior to starting the Allegro version, I made a test 3D OpenGL app that wasn't really anything more than a 3D world, however, I have just ported this using SDL and using OpenGL[ES] and compiles under Windows and Linux. You can see a screenshot below (from the Windows compile).
What's next
The next stage is to design the world map structure, and create an editor to easily construct them, followed by a demo that lets you drive a car around the world. I also need to test the SDL/GL|ES app on the Pandora, and if it works okay I'll start porting my Allegro code to SDL and go straight to 3D.
About the Author
My name is Marq Watkin, I am a computer programmer by profession and by hobby. You can find my software at http://www.pmprog.co.uk