Game State Management


As promised, here is my implementation of a game state manager. My last project was done in OGRE3D and as such, I was introduced to game state management through this wiki:

Managing Game States With OGRE

Which is inspired by:

Managing Game States in C++

-and-

State Pattern in C++ Applications

Which together inspired:

An Architecture For Game State Management Based On State Hierarchies

My code derives heavily from (see: almost exact replica of) the first 3 sources while the 4th is slightly different.

Without further ado:

GameEngine.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <vector>
#include "SDL.h"
 
class GameState;
 
class GameEngine {
 
public:
	void Init(int width, int height, int bpp, Uint32 flags,FILE *pFile); //Initialize SDL
	void Cleanup(); //Cleanup SDL
 
	//The following 3 functions loop through the respective
        //functions from the states contained in the states vector
	void HandleEvents();
	void Update();
	void Draw();
 
	void ChangeState(GameState* state);
 
	//The following 2 functions are used seperately from ChangeState()
        //when one wishes to overlap states (ex. pop up menus)
	void PushState(GameState* state);
	void PopState();
 
	bool Running() { return m_running; }
	void Quit() { m_running = false; }
 
private:
 
	std::vector  states;
	bool m_running;
	SDL_Surface* m_mainSurface;
 
};

GameEngine.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
 
#include "GameEngine.h"
#include "MainMenuState.h"
#include "SDL.h"
 
void GameEngine::Init(int width, int height, int bpp, Uint32 flags,FILE *pFile){
 
//SDL_GetError() seems like a logical thing to add to the failed if calls below (in the fprintf).
//Maybe implement with a DEBUG flag
if (SDL_Init(SDL_INIT_VIDEO)==-1)
{
	fprintf(pFile,"Could not initialize SDL!\n");
	exit(1);
}
else
{
	fprintf(pFile,"SDL initialized properly!\n");
	atexit(SDL_Quit);
}
 
m_mainSurface = SDL_SetVideoMode(width,height,bpp,flags);
 
if(!m_mainSurface)
{
	fprintf(pFile,"Could not create main surface!\n");
	exit(1);
}
}
 
//as of now, SDL_Quit cleans everything that I need it to and that's been set with atexit().
//But left this here anyway so it can be used for more than SDL.
void GameEngine::Cleanup(){}
 
void GameEngine::HandleEvents(){
 
	states.back()->;HandleEvents(this);
 
}
void GameEngine::Update(){
 
	states.back()->;Update(this);
 
}
void GameEngine::Draw(){
 
	states.back()->;Draw(this);
 
}
 
void GameEngine::ChangeState(GameState* state){
 
	if(!states.empty()){
		//Cleanup is not in destro because the object is never actually destroyed (singleton),
                //but all of its resources are unloaded with Cleanup so its memory becomes negligible
		states.back()->;Cleanup();
		states.pop_back();
	}
		states.push_back(state);
		states.back()->;Init();
 
}
 
void GameEngine::PushState(GameState* state){
 
	if(!states.empty())  //no reason to use if states is empty, but accounts for it anyway
		states.back()->;Pause();
 
		states.push_back(state);
		states.back()->;Init();
 
} //pause and push back
 
void GameEngine::PopState(){
 
	if(!states.empty()){
	states.back()->;Cleanup();
	states.pop_back();
	states.back()->;Resume();
	}
} //remove back and unpause

GameState.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class GameEngine;
 
class GameState
{
public:
 
 
  virtual void Init() = 0;
  virtual void Cleanup() = 0;
 
  virtual void Pause() = 0;
  virtual void Resume() = 0;
 
  virtual void HandleEvents(GameEngine* game) = 0;
  virtual void Update(GameEngine* game) = 0;
  virtual void Draw(GameEngine* game) = 0;
 
  void ChangeState(GameEngine* game,GameState* state) {
    game->ChangeState(state);
  }
 
  protected: GameState() { }
 
};

Implementation of the states is very dependent on tech so I’ve left an example out. States should typically be implemented as Singletons, which will be done on a class by class basis to classes that inherit from GameState.

I’ll continue my work and keep you all updated as major engine features get added. In the mean time though, I think I’ll post about the creation of the new header :) . Be on the lookout and make sure to tell your friends about this site! <3


4 Comments, Comment or Ping

  1. Hi!

    Its just a co-incidence or let me say, this phenomenon is very common! I just read through your first post and it made me chuckle since I am in the same boat ;) (I also haven’t completed any of my games, yet!)

    On that note, I am trying to complete this very simple game I did sometime back. Its a simple pong game that I did but I want to implement a game menu system for that to make it look like a complete game product. I need some help with that..

    Would it be possible for you to help me implement the game-menu system for that ?

    In case you are wondering, this pong game serves as my guinea pig experiment test-bed. I try and implement everything there and then use that generic code in other games :D

    December 31st, 2008

  2. Tyler

    Sure, I can help you out. Shoot me an email and I’ll see what I can do.

    “I try and implement everything there and then use that generic code in other games” , that’s the best way to get started! Just make sure your code is of high quality, if you’re reusing flawed code your problems will compound over time in every program that you make.

    January 1st, 2009

  3. Hi Tyler!
    The article “Managing Game States in C++” is the one I’ve read before and after I’ve always used the game states like that!

    Consider also the possibility to divide the phase of init with the phase of resource loading, maybe with a method (init) that initalize all the game-state classes BUT doesn’t allocate memory, and another (enter) that physically load all the resources (and vice-versa with leave and cleanup).
    This ensure that you can have a longer lifecycle of a state (maybe it contains some useful informations for other states) but it has no resources loaded in memory.

    Well, this is only my thought! Hope it helps! :D

    January 11th, 2009

  4. I’ve thought about it before, if we’ve got the state loading up resources on a per state basis, and we change states, but need resources that the last state loaded and subsequently unloaded upon it’s close…we’re wasting cycles reloading the same resources. This really comes seriously into play when one is changing between states frequently, for example using states to represent “levels” in a game individually rather than with an umbrella PlayState. Even if we’re not changing states that frequently, your suggestion can cut load times by a large margin. My states as they stand are too abstract too worry about the resource loading times, as the transitions between each are infrequent but I like your idea, thanks :) .

    January 11th, 2009

Reply to “Game State Management”