rolland wrote:K-Bal wrote:I discussed the game state system with Tank and we ended up with a very different approach, that is much less error prone. I will go into further details on this soon.
First, I'd like to say that your project looks pretty amazing so far. Second, I'll be waiting for that update.
Thank you! I'll give a brief explanation of how it works
Game states are now self-managed and contain a full game loop (this is managed by the base class, so no need to reimplement it every time a state is created). There is no extern game state managing class anymore. There is still a game engine class, but it's only purpose is to provide shared data to all game states. Game states can spawn sub-states (e.g. main game spawns item inventory). Here is the interface:
Code: Select all
#pragma once
#include <Cell/GameEngine.hpp>
namespace sf
{
class Event;
}
class GameState
{
public:
// Construction and destruction
GameState( GameEngine& engine );
virtual ~GameState();
//
bool Run( GameState* parent = 0 );
protected:
// Allocate and deallocate Memory
virtual bool Init() { return true; }
virtual void Cleanup() { }
// Logic
virtual void Update( float time ) = 0;
virtual void Render() const = 0;
virtual void HandleEvent( const sf::Event& event ) = 0;
// State changing
void LaunchSubState( GameState* state, bool cleanup = true );
void LeaveState();
private:
// Non-Copyable
GameState( const GameState& );
GameState& operator=( const GameState& );
// Enums
enum Result
{
Continue = 0,
LaunchState,
Leave
};
// Member
GameState* mSubState;
bool mCleanUp;
Result mResult;
protected:
GameEngine& mEngine;
GameState* mParentState;
};
EDIT:
1) Since states are singletons you obviously can't have more than one state of one type. It is fine for what I'm doing right now, but it looks messy to me.
Game states are no singletons anymore.
2) States have startup and cleanup functions which are called on a state change. However, if a state triggers a state change, the change is instantanious. That means while the main function of the state is still running, it's cleanup function is called and the startup function of the other state is called. This is bad but should be quite easy to change.
State changes are now queued until the end of the game loop cycle.
3) To create a state I have to create a new class, let it derive from GameState and implement all the functions. It works well enough but it is kinda slow. I want to have something that allows rapid development of game structures, e.g. through scripting.
This is unfortunately still the case, but I came to the conclusion that it is not really that bad since state structures are very static and normally there are only a few states.
4) I'm wondering what would be the best way to share common data between states, e.g. the GUI. I currently keep that stuff as a member of the game class with get/set-methods. Don't ask me why, but somehow it does not feel right to me.
Common data is in the GameEngine class. Didn't come up with a better solution but it doesn't seem that bad for now.