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
#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
#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,
        //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 account for it 
        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
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

Follow us @purple_pwny and the author @noxsucks. thank you :)