What's on the menu?

Main menus may have disappeared in many applications, but they are still alive and well in games. The main menu gives the player a chance to decide what to do once the game has loaded. We are going to create a simple menu that allows the player to start the game, display the credits, or exit the game.

Creating the menu

Our menu will be built out of two components. First, we will load an image to use as the background. Next, we will load additional images to use as UI buttons. Together, these images will create a screen that will allow the player to navigate our game.

We will start by defining a sprite to represent the menu. Add the following line of code to the variable declarations in RoboRacer2D.cpp:

Sprite* menuScreen;

Next, we will instantiate the menu in the LoadTextures function. Add the following code to LoadTextures:

  menuScreen = new Sprite(1);
  menuScreen->SetFrameSize(800.0f, 600.0f);
  menuScreen->SetNumberOfFrames(1);
  menuScreen->AddTexture("resources/mainmenu.png", false);
  menuScreen->IsActive(true);
  menuScreen->IsVisible(true);

Make sure that you have downloaded the menu.png texture from the book website, or that you have created your own background at 800 by 600 pixels.

Now, we must modify the Update and Render functions. Modify the GS_Menu case in Update to the following code:

case GameState::GS_Menu:
 {
  menuScreen->Update(p_deltaTime);
  inputManager->Update(p_deltaTime);
  ProcessInput(p_deltaTime);
 }
 break;

Next, modify the GS_Menu case in the Render function:

case GameState::GS_Menu:
{
  menuScreen->Render();
}
break;

If you run the game now, the splash screen should display for five seconds, followed by the menu screen.

Defining the menu buttons

Our next task is to add buttons to the menu screen that the player can click. These buttons will work similar to the pause and resume buttons that we have already created.

We will start by declaring variables for the buttons. Add the following declarations to the variables section in RoboRacer2D.cpp:

Sprite* playButton;
Sprite* creditsButton;
Sprite* exitButton;

These three pointers will manage the three buttons on our main menu. Next, add the following code to LoadTextures to instantiate the buttons:

playButton = new Sprite(1);
playButton->SetFrameSize(75.0f, 38.0f);
playButton->SetNumberOfFrames(1);
playButton->SetPosition(390.0f, 300.0f);
playButton->AddTexture("resources/playButton.png");
playButton->IsVisible(true);
playButton->IsActive(false);
inputManager->AddUiElement(playButton);

creditsButton = new Sprite(1);
creditsButton->SetFrameSize(75.0f, 38.0f);
creditsButton->SetNumberOfFrames(1);
creditsButton->SetPosition(390.0f, 350.0f);
creditsButton->AddTexture("resources/creditsButton.png");
creditsButton->IsVisible(true);
creditsButton->IsActive(false);
inputManager->AddUiElement(creditsButton);

exitButton = new Sprite(1);
exitButton->SetFrameSize(75.0f, 38.0f);
exitButton->SetNumberOfFrames(1);
exitButton->SetPosition(390.0f, 500.0f);
exitButton->AddTexture("resources/exitButton.png");
exitButton->IsVisible(true);
exitButton->IsActive(false);
inputManager->AddUiElement(exitButton);

This code is mostly the same as the code that we used to instantiate the pause and resume buttons. One small difference is that we set all three buttons to be visible. Our code already enforces that these buttons will not render unless we are in the game state GS_Menu.

We do, however, want to set the buttons as inactive. This way the input class will ignore them until we want them to be activated.

As with all of our objects, we now need to wire them into the Update and Render functions. Change the GS_Menu case in the Update function to the following code:

 case GameState::GS_Menu:
 {
  menuScreen->Update(p_deltaTime);
  playButton->IsActive(true);
  creditsButton->IsActive(true);
  exitButton->IsActive(true);
  playButton->Update(p_deltaTime);
  creditsButton->Update(p_deltaTime);
  exitButton->Update(p_deltaTime);
  inputManager->Update(p_deltaTime);
  ProcessInput(p_deltaTime);
 }
 break;

This is where we set the buttons on our menu to be active. We want to guarantee that the buttons on the menu are active when we are in the game state GS_Menu.

Next, change the GS_Menu case in the Render function to the following code:

case GameState::GS_Menu:
 {
  menuScreen->Render();
  playButton->Render();
  creditsButton->Render();
  exitButton->Render();
 }
 break;

In order for the buttons to actually do something, we need to add the following code to the CM_UI case in ProcessInput:

if (playButton->IsClicked())
{
  playButton->IsClicked(false);
  exitButton->IsActive(false);
  playButton->IsActive(false);
  creditsButton->IsActive(false);
  m_gameState = GameState::GS_Running;
}

if (creditsButton->IsClicked())
{
  creditsButton->IsClicked(false);
  exitButton->IsActive(false);
  playButton->IsActive(false);
  creditsButton->IsActive(false);
  m_gameState = GameState::GS_Credits;
}

if (exitButton->IsClicked())
{
  playButton->IsClicked(false);
  exitButton->IsActive(false);
  playButton->IsActive(false);
  creditsButton->IsActive(false);
  PostQuitMessage(0);
}

Notice that we change the game state if the play button or credits button are clicked (if the exit button is clicked, we simply post the quit message). Notice that we have to do a little button management, setting the buttons on the menu to be inactive once we are no longer in the GS_Menu game state. This is because our input class checks the input for all buttons that are active. Leaving the buttons active would mean that they could still be clicked even though they are not being displayed on the screen.

We don't have to set the buttons to be invisible. This is because changing the state will automatically stop these buttons from updating or rendering. The same is true of the menu screen. Once the game state is changed, it will not render or update. This is one of the big advantages of utilizing a state machine.

Defining the menu buttons

If you run the program right now, the main menu will display. If you click the play button, the game will start. If you click the exit button, the game will exit. We will implement the credit screen next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.185.47