Skip to content

Instantly share code, notes, and snippets.

@CarloMaker
Last active October 31, 2015 15:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save CarloMaker/8689585 to your computer and use it in GitHub Desktop.
Save CarloMaker/8689585 to your computer and use it in GitHub Desktop.
Managing game states in Urho3d
/*
This is a simple game state inspired from a good article about managing game states
at http://gamedevgeek.com/tutorials/managing-game-states-in-c/ , i tried to adapt it in Urho3d
using events rather than loops update on virtual methods that kill performance.
*/
gamestateshandler expect a scene already create , you can simply modified as you like,
main.cpp{
....
scene = new scene(context_);
....
Wiki::GameStateHandler * gsh= new Wiki::GameStateHandler(context_);
gsh->start(scene);
}
#include "Object.h"
#include "Context.h"
#include "Scene.h"
#include "Node.h"
#include "Vector.h"
#include "Str.h"
namespace Wiki{
/// fw declaration
class IGameState;
class GameStateHandler : public Urho3D::Object
{
OBJECT(GameStateHandler);
public:
///costructor
GameStateHandler(Urho3D::Context * context );
/// Destruct.
~GameStateHandler();
/// start point
void start(Urho3D::Scene * scene_);
// handler events
void onStateChange(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData );
private:
/// create state classname
void createState( Urho3D::String newState );
/// register all states
void RegisterGameStates();
/// change state
void changeState(IGameState* state);
/// exit and remove last state.
void RemoveLastState();
/// scene
Urho3D::Scene * scene;
/// mainNode ,
Urho3D::SharedPtr<Urho3D::Node> mainNode;
/// states container
Urho3D::Vector<IGameState*> mStates;
};
}
#pragma once // using #ifdef out of vs
#include "Context.h"
#include "Node.h"
#include "UI\UIElement.h"
#include "Component.h"
namespace Wiki
{
class IGameState : public Urho3D::Component
{
OBJECT(IGameState);
public:
IGameState(Urho3D::Context * context);
virtual ~IGameState();
/// enter
virtual void Enter();
/// exit
virtual void Exit();
/// update event handler
virtual void OnUpdate(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData ){};
/// on node attach
virtual void OnNodeSet( Urho3D::Node* node ){};
protected:
/// scene dedicated
virtual void CreateScene(){};
/// ui dedicated
virtual void CreateUI(){};
/// all GUI elements
Urho3D::Vector<Urho3D::UIElement *> guiElements;
};
class GameIntroSample : public IGameState
{
OBJECT(GameIntroSample);
public:
// 2 second splash screen
GameIntroSample(Urho3D::Context * context,float timeSplash = 2.0f );
virtual ~GameIntroSample();
virtual void Enter();
virtual void Exit();
virtual void OnUpdate(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData );
virtual void OnNodeSet( Urho3D::Node* node );
private:
virtual void CreateUI();
protected:
float timesplash_;
float elapsed;
};
/// generic state
class GameMainMenuSample : public IGameState
{
OBJECT(GameMainMenuSample);
public:
GameMainMenuSample(Urho3D::Context * context );
virtual ~GameMainMenuSample();
virtual void OnNodeSet( Urho3D::Node* node );
private:
virtual void CreateScene();
virtual void CreateUI();
};
}
namespace Wiki
{
/// P_CMD
enum GameStates{
GAME_STATE_LOAD_MAIN_MENU,
GAME_STATE_SETTING_REQUEST,
GAME_STATE_LOAD_TRACK,
GAME_STATE_LOAD_LOBBY_SERVER,
GAME_STATE_ON_TRACK,
GAME_STATE_ON_BOX,
GAME_STATE_EXIT_SIM
};
/// Key pressed.
EVENT(G_STATES_CHANGE, GameState)
{
PARAM(P_CMD, cmdType); // States
PARAM(P_OBJ, sender); // class
}
}
#include "GameStateHandler.h"
#include "Object.h"
#include "CoreEvents.h"
#include "ResourceCache.h"
#include "Context.h"
#include "Log.h"
#include "GameStatesEvents.h"
#include "GameStates.h"
#include "Node.h"
#include "ProcessUtils.h"
using namespace Urho3D;
namespace Wiki
{
GameStateHandler::GameStateHandler(Urho3D::Context * context):
Object(context)
,scene(0)
{
SubscribeToEvent(G_STATES_CHANGE, HANDLER(GameStateHandler, onStateChange));
RegisterGameStates();
}
GameStateHandler::~GameStateHandler()
{
RemoveLastState();
LOGINFO("Destroyng GameComponent" );
}
void GameStateHandler::RegisterGameStates()
{
/// .... all states here
context_->RegisterFactory<GameIntroSample>();
context_->RegisterFactory<GameMainMenuSample>();
}
void GameStateHandler::start(Urho3D::Scene * scene_)
{
scene=scene_;
if(scene){
mainNode = scene->CreateChild("Main");
createState(GameIntroSample::GetTypeNameStatic());
}else{
ErrorExit("Scene null");
}
}
void GameStateHandler::onStateChange( Urho3D::StringHash eventType, Urho3D::VariantMap& eventData )
{
/// intercept state event
GameStates newState= static_cast<GameStates>(eventData[GameState::P_CMD].GetInt());
LOGINFO("New State " + (String)((int)newState)) ;
switch (newState)
{
case GAME_STATE_LOAD_MAIN_MENU: //called from intro GameIntroSample
//add component
createState(GameMainMenuSample::GetTypeNameStatic());
break;
case GAME_STATE_LOAD_TRACK: //called from button on GameMainMenuSample form
createState(GameIntroSample::GetTypeNameStatic());
break;
default:
ErrorExit("Unkown State " + (String)(int) newState );
break;
}
}
void GameStateHandler::createState( String newState )
{
/// add a node and a component
/// so will be possible create / remove models attached it
Node * stateNode = scene->CreateChild(newState);
IGameState * gameState = dynamic_cast<IGameState*>(stateNode->CreateComponent(newState));
if(gameState)
changeState(gameState);
else
ErrorExit("Unkown GameState ");
}
void GameStateHandler::changeState( IGameState* state )
{
LOGINFO("Adding state" + state->GetTypeName());
//exit from old state
RemoveLastState();
//enter new state
mStates.Push(state);
mStates.Back()->Enter();
}
void GameStateHandler::RemoveLastState()
{
if ( !mStates.Empty() ) {
mStates.Back()->Exit();
//remove component's node remove node and component
mStates.Back()->GetNode()->Remove();
mStates.Pop();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment