Saturday, October 17, 2015

Game state management techniques?


First off, I'm not referring to scene management; I'm defining game state loosely as any sort of state in a game which has implications about whether or not user input should be enabled, or if certain actors should be temporarily disabled, etc.


As a concrete example, let's say it's a game of the classic Battlechess. After I make a move to take another player's piece, a short battle sequence plays. During this sequence, the player shouldn't be allowed to move pieces. So how would you track this sort of state transition? A finite state machine? A simple boolean check? It seems the latter would only work well for a game with very few state changes of this sort.


I can think of a lot of straightforward ways of handling this using finite state machines, but I can also see them quickly getting out of hand. I'm just curious if there's a more elegant way to keep track of game states/transitions.



Answer



I once came across an article that solves your problem quite elegantly. It is a basic FSM implementation, that is called in your main loop. I have outlined the basic rundown of the article in the rest of this answer.


Your basic game state looks like this:


class CGameState
{
public:

// Setup and destroy the state
void Init();
void Cleanup();

// Used when temporarily transitioning to another state
void Pause();
void Resume();

// The three important actions within a game loop
void HandleEvents();

void Update();
void Draw();
};

Each game state is represented by an implementation of this interface. For your Battlechess example, this could mean these states:



  • intro animation

  • main menu

  • chess board setup animation

  • player move input


  • player move animation

  • opponent move animation

  • pause menu

  • endgame screen


States are managed in your state engine:


class CGameEngine
{
public:
// Creating and destroying the state machine

void Init();
void Cleanup();

// Transit between states
void ChangeState(CGameState* state);
void PushState(CGameState* state);
void PopState();

// The three important actions within a game loop
// (these will be handled by the top state in the stack)

void HandleEvents();
void Update();
void Draw();

// ...
};

Note that each state needs a pointer to the CGameEngine at some point, so the state itself can decide whether a new state should be entered. The article suggest passing in the CGameEngine as a parameter for HandleEvents, Update and Draw.


In the end, your main loop only deals with the state engine:


int main ( int argc, char *argv[] )

{
CGameEngine game;

// initialize the engine
game.Init( "Engine Test v1.0" );

// load the intro
game.ChangeState( CIntroState::Instance() );

// main loop

while ( game.Running() )
{
game.HandleEvents();
game.Update();
game.Draw();
}

// cleanup the engine
game.Cleanup();
return 0;

}

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...