We may have a working game, however we still have a few loose ends, like loosing,
loading the next level and exiting to the menu when you press the escape key.
Topics Covered in this Chapter:
Checking for Level Complete
Tracking Balls
Reloading the Menu
Making it So You Can Lose:
If you are going to be able to lose, we need to be able to keep track of the
number of balls the player is allowed to lose. I have added a balls variable
to the BallController, as well as the dxText class so the balls remaining can
be printed.
//set the ball start to 4, (will be 3 after the restart is called)
balls = 4;
//create a text object to print the remaining balls
text = new dxText();
text->init(14, device);
....
return true;
}
The a call to print the number of balls remaining, or to print 'Game Over'
if no balls are left is added to the render function.
//print the number of balls remaining
if (balls > -1){
char textOut[25] = "";
sprintf(textOut,"%d Balls Remaining", balls);
text->drawText(textOut, 700,550,100,50);
} else {
text->drawText("Game Over", 700,550,100,50);
}
}
The last changes are made to the restart function.
Each call to restart decrements the ball count, and if there are no balls remaining
it does not restart the balls movement.
//if there are no balls left, do not start the ball moving again.
if (balls > -1){
ballXMovement = 0.25f;
ballYMovement = 0.25f;
} else {
ballXMovement = 0.0f;
ballYMovement = 0.0f;
}
}
Now, when you run out of balls the game stops, and prints 'Game Over' at the
bottom of the screen.
Making it So You Can Win:
In order to complete a level, we need to track how many bricks have been destroyed.
When all are destroyed the level is complete. I have added a numberOfBricks
variable to the Level class, and it is set by the loadLevel
function.
//place the first brick data into the array
intarray[0] = atoi(token);
//increase the brick count
if (intarray[0] != 0){numberOfBricks++;}
//fill the array with the rest of the level data
for (unsigned int n = 1; n < LEVEL_LENGTH; n++)
{
token = strtok(0, " ");
//if there are no tokens left break
if (!token) break;
//convert the token to an integer and store it in the array
intarray[n] = atoi(token); //increase the brick count
if (intarray[n] != 0){numberOfBricks++;}
}
//place the line of level data into the leveldata vector
levelData.push_back((int*)intarray);
}
} //end get level data
Now that we have a way to check if the level is complete, we need to add a
call to check if the level is complete, and take appropriate action if it is.
In the BallController, I have added a check in the updateFrames
function. If the level is complete, it reloads the first level, because currently
we have no other levels.
for (int i=0; i < framesToUpdate; i++){
//check for collide in this frame before we move the ball
checkCollide();
//Move the ball
ballX+= ballXMovement;
ballY+= ballYMovement;
}
//check if the level is complete
if (myLevel->levelComplete()){
//if it is complete reload level 1
myLevel->loadLevel("level1.txt");
}
}
Returning to the Menu:
The last change I'm going to make is to the GameMain update function. Currently
when the escape key is pressed in the game, it quits. I have changed it so it
reloads the menu instead.
Changes to GameMain update:
void GameMain::update(void)
{
int framesToUpdate;
//call our update function
framesToUpdate = timer->framesToUpdate();
....
//game update calls go here
if (active == GAME){
breakout->updateFrames(framesToUpdate);
if (breakout->getMessage() == Breakout::QUIT){
active = NOTHING;
delete breakout; //reactive the menu
menu = new BreakoutMenu();
menu->init(input, dxManager->getD3DDevice());
active = MENU;
}
}
....
//end render
dxManager->endRender();
}
Theses are the final changes we are going to make to our breakout game.
Summing Up - Chapter 7
With the final changes complete you can now start, finish the level, or lose
the game by running out of balls. If you hit escape you are returned to the
menu and can start a new game. Clearly the game is in a most basic state, and
only has one level. I leave it to you to create more levels, and add the ability
to go to each new level as each level is completed.