Adding the "Game Menu"
Last updated: 17-06-2006
Project: Game Programming with DirectX 9
Prerequisites: Completion of all the preceding tutorials in this project is required.
Downloads: DirectXLightWithMenu.zip
In this version of our application we add a "Game Menu" so we could select a "New game" option from the menu when the game is over. The source code that comes with this tutorial (see Downloads section above) extends the previous solution. To see all the tutorials that belong to this project click on the project name above.
First of all we have to create the menu resource (see the Resources section bellow). Menu will normally add some pixels to the height of the window. That’s why we have modified the main window height constant.
MAIN_WINDOW_HEIGHT = 510;
In the DlgProcControlPanel function we did modify the following:
case ID_GAME_OVER:
{
    SetDlgItemText(hwnd, ID_GAME_OVER, "GAME OVER!");
    eraseAllObjects();
    isGameOver = true;
}
break;
case ID_GAMEMENU_NEWGAME:
    SetDlgItemText(hwnd, ID_GAME_OVER, "..........");
    eraseAllObjects();
    numberOfAsteroidsGenerated = 0;
    numberOfFireballsFired = 0;
    score = 0;
    isGameOver = false;
    SetDlgItemText(hwnd, ID_FIREBALLS, 
    (LPCSTR)CStr(numberOfFireballsFired).c_str());
    SetDlgItemText(hwnd, ID_ASTEROIDS, 
    (LPCSTR)CStr(numberOfAsteroidsGenerated).c_str());
    SetDlgItemText(hwnd, ID_SCORE, 
    (LPCSTR)CStr(score).c_str());
break;
Notice that we set the isGameOver variable to true in the first case block. A second case block adds processing of the "New game" menu option. All the variables are reset to 0. Text of the labels shown to the user is set to the initial values. Notice that we also call the eraseAllObjects() method to clear the memory from a previous game. We do that because user can start a new game without finishing the current game (so the game over message will not be sent).
In the WndProc function the following was added:
case WM_COMMAND:
    switch(LOWORD(wParam)){
        case ID_GAMEMENU_EXIT:
            DestroyWindow(hwnd);
        break;

        case ID_GAMEMENU_NEWGAME:
        SendMessage(hwndControlPanel, WM_COMMAND, ID_GAMEMENU_NEWGAME, 0);
        break;
    }
break;
If "Exit" menu option was selected then we destroy the window as usual. If "New game" menu option is selected then we send a message to the hwndControlPanel for further processing.
Finally in WinMain function we define the menu so it could be loaded by the program in the right window:
w.lpszMenuName = MAKEINTRESOURCE(ID_GAMEMENU);
Resources:
Since all the resource files are provided with the source code, you are not required to perform the described bellow steps. For detailed information on how to add resources to your application, please advice the Visual Studio documentation.
Bellow is a short explanation on how the menu resource was created. Adding the menu resource with Visual Studio made easy. It is a matter of typing the desired values into the fields.
If you already have a .rc file in your project, double click it to open the Resource View. To add additional resources to your project in Resource View right click on .rc folder and select Add Resource > Menu > New.
If your project does not yet have a .rc file then such can be usually created by right clicking your project name in Solution Explorer, selecting Add New Item, opening the Resource folder, clicking on Resource.rc icon and giving the name to your file.
We use Resource Editor that generates the menu resource definition automatically. Alternatively you can just type the menu resource definition if you open the resource file with a text editor. It is strongly recommended to check the numerical values of the generated id's in the corresponding resource header file (with the extension .h). Sometimes these values are not generated correctly and are equal to other id’s that were generated before causing problems to IntelliSence (This is the part of Visual Studio that helps inserting code automatically. For example you don't have to type the variable names, IntelliSence will do that for you, you only need to type the first letter or select the necessary objects from the list).
After we did add our menu with the Resource Editor the following was generated automatically in the corresponding menu header file:
#define ID_GAMEMENU                     104
#define ID_GAMEMENU_NEWGAME             40004
#define ID_GAMEMENU_EXIT                40005
Note that the numerical values might change. To avoid problems with IntelliSence you only need to check that all the generated values in the header file are unique.
Finally in the ControlPanel.rc file the following menu definition was generated for our menu.
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

ID_GAMEMENU MENU 
BEGIN
    POPUP "Game Menu"
    BEGIN
        MENUITEM "&New game",    ID_GAMEMENU_NEWGAME
        MENUITEM "&Exit",        ID_GAMEMENU_EXIT
    END
END