Experiments In Game Programming
Main
 Home
XNA - C#
 Coming Soon!
 Level Editing - GTK
DirectX 9 - C++
 Downloads
 Disclaimer
 Introduction
Part 1 - DirectX
 1 - Breakout
 2 - Create DX
 3 - 2d Images
 4 - 3d Models
 5 - Cameras & Lights
 6 - Animation Timing
 7 - Keyboard/Mouse
 8 - Sound
Part 2 - Breakout
 1 - Art and Sounds
 2 - The Menu
 3 - Starting Breakout
 4 - The Level
 5 - The Paddle
 6 - The Ball
 7 - Finishing Touches

Untitled Document

Chapter 7

 

Finishing Touches

 

 

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.

Changes to the BallControllers init:

bool BallController::init(SoundManager* sounds, Level* level, PaddleController* paddle, LPDIRECT3DDEVICE9 device){
     ....

     //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.
void BallController::render(LPDIRECT3DDEVICE9 device){
     ball->setPosition(D3DXVECTOR3(ballX,ballY,0.0f));
     ball->render(device);

     //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.
void BallController::restart(){
     //reduce the ball count
     balls--;
     ballX = 0.0f;
     ballY = 0.0f;

     //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.

changes to Level loadLevel:
bool Level::loadLevel(std::string filename){
     numberOfBricks = 0;
     ...
    

     //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


file.close();
//end token collection
return true;
}

Each time the destroy brick function is called the brick count is reduced.

Changes to destroyBrick:
void Level::destroyBrick(int x, int y){
     //set the brick to 0, (no brick)
     levelData[x][y] = 0;
     numberOfBricks--;
}

I have added a new function to the Level class called levelComplete. levelComplete returns true if the brick count has reached 0.
bool Level::levelComplete(){
     if (numberOfBricks == 0){
         return true;
     } else {
         return false;
     }
}

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.

Changes to updateFrames:
void BallController::updateFrames(int framesToUpdate){
    
     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.

 
 ©2008 David Whittaker