Now that we are ready to begin programming the game itself we need to decide
how the control flow is going to work and how the responsibilities are going
to be broken down.
Topics Covered in this Chapter:
Planning The Game Classes
Laying out some Functions
In order to decide the control flow and to designate responsibilities, we need
to have a reasonable idea of everything that will be going on. Missing something
important could mean having to add additional parameters or functions to your
classes, often in inconvenient locations. Finding out you need a variable that
would need to be passed through 2 or 3 objects to get it is a good example of
this. For breakout we don't have a lot of things going on so its not too difficult
to design a control flow and designate responsibility.
I have divided the responsibilities into 3 classes: the Level Class for loading
levels and keeping track of the level blocks, the PaddleController for controlling
the paddle based on user input, and the BallController for controlling the movement
of the ball. The BallController has access to the Level and the PaddleController
because it needs to know where the paddle and bricks are to do collisions. Below
is a diagram of the class structure and a list of what each class is responsible
for.
Level:
Loading the Level File
Loading the Brick Models
Storing the Level Information
Rendering the Level Bricks
PaddleController:
Getting Player Input
Loading the Paddle Model
Setting the Paddle Position
Rendering the Paddle
BallController:
Loading the Ball Model
Controlling the Ball Movement
Handling Collisions
Playing Collision Sounds
Messaging the Level To Remove Collided Bricks
Next Level / Lose Conditions
Rendering the Ball
The Level, PaddleController and BallController are created in the next few
chapters. For the rest of this chapter we will be looking at the Breakout class
itself and laying out some empty functions as place holders for filling in as
we create the classes.
Take a look at the Breakout class in the part 2 chapter 3 code. Init
is the first function of interest, and has an InputManager, a SoundManager,
and the device as parameters. Because of the nature of the Input and Sound classes
we only ever want one of the instanciated at a time, so we create them in the
game main, and pass them to the functions that require them. Init
loads the background and you see in the comments it will also create a Level,
BallController, PaddleController, Camera, and LightManager.
background = new Surface();
background->loadSurface(device, "background.jpg");
//create the level object
//create the paddle controller
//create the ball controller
//create A Camera
//Create a Light Manager
return true;
}
UpdateFrames is next and the number of frames
to update is its only parameter. UpdateFrames will
propagate the update call to the PaddleController and the BallController.
void Breakout::updateFrames(int numberOfFrames){
//update the ball controller
//update the paddle controller
}
The next function is render. Render
currently renders the background and will render the level, the ball, and the
paddle when they are complete.
void Breakout::render(LPDIRECT3DDEVICE9 device){
//render the background
background->render(device);
//render the level
//render the ball
//render the paddle
}
The last function is getMessage. The getMessage
returns the current message to the GameMain, this will be used if the user has
requested to quit, or the game is over.
int Breakout::getMessage(){
return message;
}
I have added the Breakout class to the GameMain. A new Breakout is created
when the menu message returns new game.
Changes to GameMain Update:
void GameMain::update(void)
{
int framesToUpdate;
//call our update function
framesToUpdate = timer->framesToUpdate();
//update the menu
if (active == MENU){
menu->update();
if (menu->getMessage() == BreakoutMenu::EXIT){
active = NOTHING;
PostQuitMessage(0);
delete menu;
}
if (menu->getMessage() == BreakoutMenu::NEW_GAME){ //if an exiting game exists delete it
if (breakout != NULL){
delete breakout;
}
//start a new game
breakout = new Breakout();
breakout->init(input, sound, dxManager->getD3DDevice());
active=GAME;
}
}
//game update calls go here if (active == GAME){
breakout->updateFrames(framesToUpdate);
}
// begin rendering
dxManager->beginRender();
//game render calls go here
if (active == MENU){
menu->render(dxManager->getD3DDevice());
}
//game render calls go here if (active == GAME){
breakout->render(dxManager->getD3DDevice());
}
//end render
dxManager->endRender();
}
With the Breakout class now added to the GameMain, compiling and running the
project and selecting new game from the menu should create the game, and draw
the game background.
Summing Up - Chapter 3
Overall the structure of the Breakout class is not overly complicated. Designating
responsiblities out to sub-classes like Level, PaddleController, and BallController
help to simplify the main Breakout class. Creating empty functions with comments
helps remind us what we intend to do in each function when we come back to fill
in the details later.