Last active
October 31, 2015 15:43
-
-
Save CarloMaker/8689585 to your computer and use it in GitHub Desktop.
Managing game states in Urho3d
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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