Programming4us
         
 
 
Windows Phone

Developing for Windows Phone and Xbox Live : Multiplayer Games (part 2) - Main Menu and State Management

7/18/2011 5:44:14 PM

Main Menu and State Management

The sample consists of multiple text menu screens and a game play screen that consists of moving the player’s gamertag around. Depending on the current state of the game, you will want to display a different menu and update a different set of logic. To do this, use a simple enumeration that tracks the game’s current state.

Outside the Game class but within the same file and namespace, add the following enumeration:

// Different states the game can be in
public enum GameState { MainMenu, CreateSession, FindSession, GameLobby, PlayingGame };


As you can see from the GameState enumeration, the sample game contains five different states. As you progress through this article, you implement the update and display logic for each of these.

During the course of the game, you will want to display some text for a short period of time. Use this for a number of notifications including when a player joins or leaves a session. Use a new structure that contains the message and the time remaining to display the text. Add the following structure to your game:

// Structure used to display game messages over a TimeSpan
public struct DisplayMessage
{
public string Message;
public TimeSpan DisplayTime;

public DisplayMessage(string message, TimeSpan displayTime)
{
Message = message;
DisplayTime = displayTime;
}
}

The Game class needs a few member variables. You need to hold the current state that you created an enumeration for and you need a list of the game messages to be displayed. Add the following member variables to your Game class:

// Current state our game is in we start at the main menu
GameState gameState = GameState.MainMenu;

// The messages to display on the screen
// We will use this to show events that occur like
// a player joining a session
List<DisplayMessage> gameMessages = new List<DisplayMessage>();

SpriteFont spriteFont;
GamePadState currentGamePadState;
GamePadState lastGamePadState;
Random random = new Random();

In addition to the gameState and gameMessages, create variables for the SpriteFont you will use, the GamePadState for the current and last frame, and a new Random generator that you will use within the game.

In your game’s LoadContent method, load the SpriteFont you plan to use for the text in the sample. Create a new SpriteFont in the content pipeline and set the text size to 24. Add the following to the LoadContent method:

spriteFont = Content.Load<SpriteFont>("SpriteFont1");

Add the following code to your game’s Update method:

// If there is no user signed in after 5 seconds
// then we show the sign in
if (gameTime.TotalGameTime.Seconds > 5)
{
if (Gamer.SignedInGamers.Count == 0 &&
!Guide.IsVisible)
Guide.ShowSignIn(1, false);
}

// Store the current GamePadState
currentGamePadState = GamePad.GetState(PlayerIndex.One);

// Switch to determine which update method to call
// based on the current game state
switch (gameState)
{
case GameState.MainMenu:
MainMenuUpdate();
break;
}

// Store the game pad state for next frame
lastGamePadState = currentGamePadState;

// Update the DisplayTime of the current display message
if (gameMessages.Count > 0)
{
DisplayMessage currentMessage = gameMessages[0];
currentMessage.DisplayTime -= gameTime.ElapsedGameTime;

// Remove the message if the time is up
if (currentMessage.DisplayTime <= TimeSpan.Zero)
{
gameMessages.RemoveAt(0);
}
else
{
gameMessages[0] = currentMessage;
}
}


Check whether any user is currently signed in. If a user is not signed in after 5 seconds, call Guide.ShowSignIn, which displays the sign-in dialog in the guide. Use a switch statement to call the appropriate update method depending on the current gameState value. Right now, you have only the MainMenuUpdate method, but as you progress through the article, you add more for each of the different GameState values. The last part of the Update method loops over the gameMessages to determine whether any of them need to be removed so they are no longer displayed.

Add the MainMenuUpdate method that will handle user input and logic when our sample is at the main menu. Add the following method to your Game class:

// Update method for the MainMenu GameState
private void MainMenuUpdate()
{
// Exit the game
if (ButtonPressed(Buttons.Back))
Exit();
}

The main menu update does not do much now, but later you add the capability to create and find a session. If the user presses the Back button, you exit the sample.

To check for a single button press in many of your menus, use a helper method that you can add to your Game class.

// Helper to determine if a button was pressed but will
// not allow repeat presses over several frames
bool ButtonPressed(Buttons button)
{
// Don't process buttons when the guide is visible
if (Guide.IsVisible)
return false;
return currentGamePadState.IsButtonDown(button) &&
lastGamePadState.IsButtonUp(button);
}

The ButtonPressed method returns true if the button was pressed on this frame and does not allow for multiple button presses.

To call the draw methods for the different menu screens in the sample, add the following to your game’s Draw method.

// Switch to call the correct draw method for the
// current game state
switch (gameState)
{
case GameState.MainMenu:
MainMenuDraw();
break;
}

// Draw the current display message
if (gameMessages.Count > 0)
{
DisplayMessage currentMessage = gameMessages[0];
spriteBatch.Begin();
Vector2 stringSize = spriteFont.MeasureString(gameMessages[0].Message);
spriteBatch.DrawString(spriteFont, gameMessages[0].Message, new Vector2((1280 -
stringSize.X) / 2.0f, 500), Color.White);
spriteBatch.End();
}


To implement MainMenuDraw to display the text for the main menu, add the following method to your Game class.

// Draw method for the MainMenu GameState
private void MainMenuDraw()
{
spriteBatch.Begin();
spriteBatch.DrawString(spriteFont, "MAIN MENU", new Vector2(10, 10), Color.White);
spriteBatch.DrawString(spriteFont, "Create Session - Press A",
new Vector2(10, 50), Color.White);
spriteBatch.DrawString(spriteFont, "Find Session - Press B",
new Vector2(10, 90), Color.White);
spriteBatch.DrawString(spriteFont, "Exit - Press Back",
new Vector2(10, 130), Color.White);
spriteBatch.End();
}


The main menu text is simple and displays the menu title and three menu options for creating a session, finding a session, and exiting the game.

Running the sample at this point should just display the simple main menu. The A and B buttons won’t do anything yet because you have not wired them in your MainMenuUpdate method. Pressing the Back button exits the sample.

The sample should look like Figure 4.

Figure 4. Main menu screen
Other -----------------
- User Interface : Using the ApplicationBar Control
- User Interface : Creating an Animated Splash Screen
- Windows Phone 7 Game Development : The World of 3D Graphics - Vertex and Index Buffers
- Windows Phone 7 Game Development : The World of 3D Graphics - Hidden Surface Culling
- Windows Phone 7 Game Development : The World of 3D Graphics - The Depth Buffer
- Windows Phone 7 Game Development : The World of 3D Graphics - Rendering 3D Objects
- Windows Phone 7 Game Development : The World of 3D Graphics - Perspective Projection
- Developing for Windows Phone and Xbox Live : Let the 3D Rendering Start
- Developing for Windows Phone and Xbox Live : Reach and HiDef Graphics Profiles
- Developing for Windows Phone and Xbox Live : Graphics Pipeline
- Developing for Windows Phone and Xbox Live : Graphics Pipeline
- Programming Windows Phone 7 : Elements and Properties - More on Images
- Programming Windows Phone 7 : TextBlock Properties and Inlines
- Programming Windows Phone 7 : The Phone’s Photo Library
- Programming Windows Phone 7 : Capturing from the Camera
- Windows Phone 7 : Loading Local Bitmaps from Code
- Windows Phone 7 : Image and ImageSource
- Windows Phone 7 : Images Via the Web
- Windows Phone 7 : Customizing Your E-Mail Signature
- Windows Phone 7 : Managing Mail Folders
 
 
Most View
- Windows Server 2012 : Backup and Recovery (part 8) - Backing up and restoring Active Directory
- Managing Windows Server 2012 Storage and File Systems : Storage Management (part 4) - Installing and configuring file services - Configuring Hyper-V
- Setting Up a Full-Text Index (part 3) - Diagnostics
- Windows Server 2008: Using Capacity-Analysis Tools (part 2) - Network Monitor
- Windows 7 : Customizing the Windows Security Window
- Windows Phone 7 : Using the Touch Screen (part 4) - Sprite Hit Testing - Elliptical Hit Tests, Building the Hit Tests into the Game Framework
- Client Credentials
- SharePoint 2010 : Create a Personal or Public View for a List or Library (part 2) - Create a Calendar View
- Programming Windows Azure : Table Operations - Using Partitioning
- SharePoint 2010 : Customizing Out of the Box Workflows
Top 10
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 3) - Configuring Recipient Filtering
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 2)
- Implementing Edge Services for an Exchange Server 2007 Environment : Utilizing the Basic Sender and Recipient Connection Filters (part 1)
- Implementing Edge Services for an Exchange Server 2007 Environment : Installing and Configuring the Edge Transport Server Components
- What's New in SharePoint 2013 (part 7) - BCS
- What's New in SharePoint 2013 (part 6) - SEARCH
- What's New in SharePoint 2013 (part 6) - WEB CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 5) - ENTERPRISE CONTENT MANAGEMENT
- What's New in SharePoint 2013 (part 4) - WORKFLOWS
- What's New in SharePoint 2013 (part 3) - REMOTE EVENTS