Game state management

Started by
2 comments, last by AnthonyDivitto 12 years, 1 month ago
Hello everyone,
Recently in school a friend and i were discussing game states, and that interested me to do some research. I checked out the tutorial on msdn but unfortunatly i couldn't get it to run. The reason we were discussing game states is i was looking for a way to set up a menu for a space invaders clone i want to work on. I found another topic on the forum about states but it involved stacks and lists and was a lot more complicated then i think it needs to be. My original idea was using something like a switch statement to controll which state the game was currently in. So my question is, how would you design a method to control game states? My clone of space invaders would include a main menu, an options screen, a game screen and a high score screen. i would also like the game screen to be able to jump to a pause screen.
The computing scientist's main challenge is not to get confused by the complexities of his own making.
— E. W. Dijkstra
Advertisement
A switch statement can be very good for a small game. If you're using C#, you can simply use delegates to link a callback to a method. Therefore, you can store the delegates as dictionary values, and the keys can be the state name. For example, states[currentState].invoke() can be in your update loop. You can simply remove large switch statements this way.

You'd also definitely want ways of disposing your current state and adding screen transition effects (say if you exit the game to the main menu, fade-out then back in). Things like this can be handled by setting up a getter/setter property and handle disposing particular states and automatically setting up tranistion states when a new state is set. You could also create a state interface (for example with name, update, render, and dispose methods). Then you'd simply create MainMenuState, OptionsScreenState, GameScreenState, etc. classes, with all of them implementing your state interface. Then just store them into a dictionary/hashtable and call them in your update and/or render loop (for example in your update loop: state[currentState].update() or render loop state[currentState].render()).

State management can be very difficult. It's definitely something I've been trying to perfect.


public interface IState {
string Name {get;}
void Update();
void Render();
void Dispose();
}


How setting a new state could work in your application:


public IState CurrentState {
get {return _currentState;}
set
{
if (_currentState != null) // If we already have a state running.
_currentState.Dispose();
_currentState = value;
}
}

public void Update() {
_currentState.Update();
}

public void Render() {
_currentState.Render();
}


An example of a state implementing the IState interface:


public class GameState : IState {
public string Name {get {return "GameState";}}
public bool IsPaused {get{return _isPaused;} set {_isPaused = value;}}
public void Update() {
if (!_isPaused)
runGame();
}
public void Render() {}
public void Dispose() {}
}
Switch statements definitely work for a small project. For my current C++ project, I use something similar to what Ryman outlined above, with a few modifications.

A game state interface, 'GameState'.
Virtual functions: Draw(screen), Think(), Update(deltaTime), React(event)
(I have a few others as well, but they aren't needed. You could also merge Update() and Think() together if you wanted)

And each game state has it's own list of children. Only the topmost of each list is active.
The gamestates pop themselves when finished.

So:
RootState.Push(MainMenuState)
RootState.Push(GameStartupScreen)

That puts 'GameStartupScreen' on top of RootState's children list, so it is the active state (With RootState also being active). Once it pops itself, control automaticly goes to MainMenuState.

I also have 'Activated()' and 'Deactivated()' virtual functions, so game states can load / unload their resources only when needed.

It's not perfect, but it works for my large-ish project.
thank you for replying, do you think you could provide a small example of how you would implement a switch like you said?
The computing scientist's main challenge is not to get confused by the complexities of his own making.
— E. W. Dijkstra

This topic is closed to new replies.

Advertisement