Personal tools
You are here: Home Resources XNA Tutorials Game State Management Sample

Game State Management Sample

DOWNLOAD WHOLE TUTORIAL

This sample shows how to manage the transitions between different menus and gameplay states.

Sample Overview

The sample implements a simple game flow with a main menu, an options screen, some actual gameplay, and a pause menu. It displays a loading screen in between the menus and gameplay, and uses a popup message box to confirm whether the user really wants to quit.

The ScreenManager class is a reusable component that maintains a stack of one or more GameScreen instances. It coordinates the transitions from one screen to another, and takes care of routing user input to whatever screen is on top of the stack.

Each screen class (including the actual gameplay, which is just another screen) derives from GameScreen. This provides Update, HandleInput, and Draw methods, plus some logic for managing the transition state. GameScreen does not actually implement any transition rendering effects, however: it merely provides information such as "you are currently 30% of the way through transitioning off," leaving it up to the derived screen classes to do something sensible with that information in their drawing code. This makes it easy for screens to implement different visual effects on top of the same underlying transition infrastructure.

Minimum Shader Profile

Vertex Shader Model 1.1
Pixel Shader Model 1.1

Sample Controls

This sample uses the following keyboard and gamepad controls.

Action Keyboard Control Gamepad Control
Select a menu entry. UP ARROW, DOWN ARROW Left thumb stick, D-Pad up and down
Accept the menu selection. SPACEBAR, ENTER A, START
Cancel the menu. ESC B, BACK
Move a game entity. UP ARROW, DOWN ARROW, LEFT ARROW, and RIGHT ARROW Left thumb stick
Pause the game. ESC START, BACK

How the Sample Works

The source files in the ScreenManager folder (ScreenManager.cs, GameScreen.cs, and InputState.cs) provide a reusable state management component that could be used by any game. The files in the Screens folder implement the specific screens used by this sample: you would probably want to change or replace these to re-skin the menu system before using it in a game of your own.

Several different things can happen when one screen is stacked over the top of another:

  • If the topmost screen is flagged as being a popup, it is drawn over the top of the screen below it. This is used for the "are you sure you want to quit?" message boxes, and for the pause menu that is displayed over the top of the gameplay screen.
  • If the topmost screen is not flagged as a popup, the screen below it automatically transitions off to get out of the way. This is used for the options screen, which is brought up over the top of the main menu. The main menu screen automatically transitions off while the options screen is active, and when the options screen exits, the main menu automatically transitions back on, without the options screen having to do anything specific to make this happen. This behavior isn't really necessary for such a small sample, but comes in handy when building larger user interfaces with more complicated structures of nested menus.
  • Because all the transition logic is implemented inside GameScreen.Update, specific screens can override this to achieve whatever custom stacking behaviors they want. For instance the BackgroundScreen class, which sits behind all the different menu screens and is used to display a background image that will not be affected by menu transitions, overrides the Update behavior to prevent itself transitioning off even though it has another screen on top of it.

The ScreenManager component doesn't directly update the screen transition states. It just calls Update on each of the screens, telling them whether they are covered by some other non-popup screen, and whether some other screen on top of them has the input focus. The GameScreen.Update method is responsible for updating the transition state in response to this information, transitioning on or off as appropriate.

The ScreenManager also calls GameScreen.HandleInput for the topmost active screen. Unlike the Update method, this is only ever called for one screen per frame, because there should never be more than one screen responding to user input at the same time. Screens are considered to be active even while they are in the process of transitioning on. This lets players who are familiar with the game navigate quickly through the menus without having to bother waiting for transitions to complete. If they dismiss a menu before it has finished transitioning on, the transition will simply turn around and move back off again: you can see this in action if you toggle rapidly back and forth between the main menu and options screens.

Note that transitions are entirely optional. If a GameScreen leaves its TransitionOnTime and TransitionOffTime properties set to zero, it will instantly pop on and off, and thus will have no need to implement transition effects in its rendering code.

The LoadingScreen coordinates transitions between the menu system and the game itself. Normally, one screen transitions off at the same time as the next screen is transitioning on, but for larger transitions that can take a longer time to load their data, and we want the menu system to be entirely gone before we start loading the game. This is done as follows:

  • Tell all the existing screens to transition off.
  • Activate a loading screen, which will transition on at the same time.
  • The loading screen monitors the state of the previous screens.
  • When it detrmines they have finished transitioning off, it activates the real next screen, which may take a long time to load its data. The loading screen will be the only thing displayed while this load is taking place.

Extending the Sample

You can extend the sample by adding new screens, changing the menu options, and altering the drawing code used by the MenuScreen, MessageBoxScreen, and BackgroundScreen classes. For example, you could make the MenuScreen transition effect slide vertically rather than horizontally, or add some subtle animation to the BackgroundScreen.

In the interest of simplicity, this sample implements GameScreen as a standalone class rather than deriving from DrawableGameComponent. If you want to use components together with this menu system, you could extend GameScreen to host other components inside itself. Each screen would maintain a list of the components it is using, call Initialize on new components when they are added, and plumb the Update and Draw calls through to every component in this list.

by Ashey Reid last modified 2008-06-01 14:58
« September 2010 »
Su Mo Tu We Th Fr Sa
1234
567891011
12131415161718
19202122232425
2627282930
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: