我正在写一个游戏,我想以一种干净的,面向对象的方式来模拟它的不同状态(Game Maker类比将是帧,我猜).以前,我是通过以下方式完成的:
class Game { enum AppStates { APP_STARTING, APP_TITLE, APP_NEWGAME, APP_NEWLEVEL, APP_PLAYING, APP_PAUSED, APP_ENDED }; typedef AppState(Game::*StateFn)(); typedef std::vectorStateFnArray; void Run() { // StateFn's to be registered here AppState lastState(APP_STARTING); while(lastState != APP_ENDED) { lastState = GetCycle_(lastState); } // cleanup } protected: // define StateFn's here AppState GetCycle_(AppState a) { // pick StateFn based on passed variable, call it and return its result. } StateFnArray states_; };
这对于一个较小的项目来说几乎无法管理.状态所使用的所有变量都被转储到Game类中,但是我希望将面向对象保持为最大值,只显示由多个状态共享的变量.我还希望能够在切换到新状态时初始化,而不是必须在刚完成的状态下进行(因为它可能有多个结果 - APP_PLAYING可以切换到APP_PAUSED,APP_GAMEOVER,APP_NEWLEVEL等).
我想到了这样的事情(小心!模糊的东西!):
struct AppState { enum { LAST_STATE = -1; } typedef int StateID; typedef std::vectorStateArray; static bool Add(AppState *state, StateID desiredID); // return false if desiredID is an id already assigned to static void Execute(StateID state) { while(id != LAST_STATE) { // bounds check etc. states_[id]->Execute(); } } AppState() {}; virtual ~AppState() {}; virtual StateID Execute() =0; // return the ID for the next state to be executed protected: static StageArray stages_; };
这里的问题是类和实例级别混乱(静态与虚拟).状态需要从AppState继承,但是 - 我怎么想 - 它们中的大多数都是具有全静态成员的类,或者,至少我不需要一个类中的多个实例(TitleState,LevelIntroState,PlayingState) ,GameOverState,EndSequenceState,EditorState ... - 暂停将不再是一个状态,而不是在有意义的状态下处理.
怎样才能优雅高效地完成?
以下文章提供了一种管理游戏状态的简单方法:
http://gamedevgeek.com/tutorials/managing-game-states-in-c/
基本上,你保持一堆游戏状态,然后运行顶级状态.你是对的,许多州只有一个实例,但这不是一个真正的问题.实际上,你所谈论的许多州可能有多个实例.例如:
push TitleState push MenuState push LevelIntroState change_to PlayingState change_to GameOverState pop (back to MenuState)
...你可以从一个新的实例开始LevelIntroState
,依此类推.