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 2

 

Setting Up a Menu

 

 

Although its not often the first thing written, the first thing you see when you start a game is the menu. In this chapter we will create a menu class for our breakout game. It will be fairly simple, only having 2 options - new game and quit.

Topics Covered in this Chapter:
  • Setting up a New Project
  • Creating The Menu
  • Getting the quit message

The Menu class is the first class in starting the actual programming of breakout. In the Part 2 Chapter 2 code I have started a new project, and I have a new layout for the classes. All of the classes we created in part one have been place in a common folder outside the chapter folders. The files are included with ../common/ . This way all of the DirectX classes we wrote in part one, which will not be changing will not be duplicated for each of part 2's chapters.

The Menu:

The menu itself is fairly simple, and just consists of a background image, and images of each menu item. There are two images for each menu item, one highlighted to indicate the item is selected and one normal. The currently selected menu item is kept track of as a number. When the up or down arrow is pressed the selected menu item is adjusted accordingly. When the enter key is pressed the menu message is set based on the item selected. Like previous examples the menu has an update and render function that are called from the main game update and render loop. At each update call the main game loop also checks the menu for messages so it can take action accordingly.

Take a look at the BreakoutMenu class from the part 2, chapter 2 code. You will notice in the header I make use of a function called ENUM. ENUM is used to define constants, I have defined NEW_GAME, and EXIT. They will be used to check and set the menu message which is just an integer. The code is a lot more readable if the message is being set to NEW_GAME instead of 1. The constants are accessible from outside the BreakoutMenu class and can be accessed as BreakoutMenu::NEW_GAME etc.

The Deconstructor is worth noting, as we start writing the game we are going to be creating many objects that use memory. If we don't explicitly free the memory when we are finished with an object the memory remains allocated to our program. If you don't unallocated memory you are not using anymore your program will grow over time and will eventually fill all the system ram. So always remember to free up any memory you are finished using.

The first main function in BreakoutMenu is init. Init loads all of our images and sets the starting menu state.

bool BreakoutMenu::init(InputManager* input, LPDIRECT3DDEVICE9 device){
     myInput = input;
     //0 is new game, 1 is exit;
     menuItemSelected = 0;
     message = 0;
     //load menu Images
     //load background menubackground.jpg
     background = new Surface();
     background->loadSurface(device, "menubackground.jpg");
    
     //load new game image
     newGame = new Surface();
     newGame->loadSurface(device, "newgame.jpg");
     newGame->setPosition(200,300);
     newGameHighlighted = new Surface();
     newGameHighlighted->loadSurface(device, "newgameh.jpg");
     newGameHighlighted->setPosition(200,300);
     //load exit image
     exit = new Surface();
     exit->loadSurface(device, "exit.jpg");
     exit->setPosition(200,400);
     exitHighlighted = new Surface();
     exitHighlighted->loadSurface(device, "exith.jpg");
     exitHighlighted->setPosition(200,400);

     return true;
}

The update function is next, it gets the input from the keyboad and sets the active menu item, and menu message.
void BreakoutMenu::update(){
     myInput->getInput();
     //get menu movement input
     if (myInput->keyPress(DIK_UP) || myInput->keyPress(DIK_DOWN)){
         if (menuItemSelected == 0){
             menuItemSelected = 1;
         } else {
             menuItemSelected = 0;
         }
     }

     //get menu pressed input
     if (myInput->keyPress(DIK_RETURN)){
         switch (menuItemSelected){
         case 0: {message = NEW_GAME; break;}
         case 1: {message = EXIT; break;}
         }

     }
}

Render, renders the background and menu items base on which is selected.
void BreakoutMenu::render(LPDIRECT3DDEVICE9 device){
     //render menu
     //render background
     background->render(device);
    
     //render menu items based on which is highlighted
     if (menuItemSelected == 0){
         newGameHighlighted->render(device);
         exit->render(device);
     } else {
         newGame->render(device);
         exitHighlighted->render(device);
     }
    
}

The last funciton getMessage returns the current message.
int BreakoutMenu::getMessage(){
     return message;
}

The BreakoutMenu needs to be added to the GameMain in order to use it. I have removed all of the testing objects from the GameMain so we are starting with a clean one.
Changes to GameMain init:

bool GameMain::init(HWND wndHandle, HINSTANCE hInst)
{
     dxManager = new dxMgr(); //create our direct Manager
     dxManager->init(wndHandle, 800, 600, true); //Initialize our DirectX Manager
     if (!dxManager){
         return false;
     }

     //Create a new InputManager
     input = new InputManager();
     input->init(hInst, wndHandle);

     //create a new Menu
     menu = new BreakoutMenu();
     menu->init(input, dxManager->getD3DDevice());
     active = MENU;


     //create a new frame timer
     timer = new FrameTimer();
     timer->init(60);

     return true;
}

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){
             PostQuitMessage(0);
         }
         if (menu->getMessage() == BreakoutMenu::NEW_GAME){
             active=GAME;
         }
     }


     //game update calls go here
     if (active == GAME){


     }

     // begin rendering
     dxManager->beginRender();
     //menu render calls go here
     if (active == MENU){
         menu->render(dxManager->getD3DDevice());
     }
    
     //game render calls go here
     if (active == GAME){


     }

     //end render
     dxManager->endRender();

}


I have added an active variable to the GameMain, to keep track of which objects it should be rendering. In this case it is just the game or the menu. In the case of a large number of items, adding an active state to the classes themselves is a better idea.

Compile and run the project. You now have a simple menu.



Summing Up - Chapter 2

The menu is just a couple of images and states. Enumeration is used so the menu states are readable in the code. The getMessage needs to be called by the main loop to take action based on the menu selection.
 ©2008 David Whittaker