私はかつてあなたの問題を非常にエレガントに解決する記事に出会いました。これは基本的なFSM実装であり、メインループで呼び出されます。この回答の残りの部分では、記事の基本的な概要を説明しました。
基本的なゲームの状態は次のようになります。
class CGameState
{
public:
// Setup and destroy the state
void Init();
void Cleanup();
// Used when temporarily transitioning to another state
void Pause();
void Resume();
// The three important actions within a game loop
void HandleEvents();
void Update();
void Draw();
};
各ゲームの状態は、このインターフェイスの実装によって表されます。バトルチェスの例では、これは次の状態を意味します。
- イントロアニメーション
- メインメニュー
- チェスボードセットアップアニメーション
- プレイヤー移動入力
- プレイヤー移動アニメーション
- 相手の動きのアニメーション
- 一時停止メニュー
- ゲーム終了画面
状態は、状態エンジンで管理されます。
class CGameEngine
{
public:
// Creating and destroying the state machine
void Init();
void Cleanup();
// Transit between states
void ChangeState(CGameState* state);
void PushState(CGameState* state);
void PopState();
// The three important actions within a game loop
// (these will be handled by the top state in the stack)
void HandleEvents();
void Update();
void Draw();
// ...
};
各状態には、ある時点でCGameEngineへのポインタが必要なので、状態自体が新しい状態に入るかどうかを決定できることに注意してください。この記事では、CGameEngineをHandleEvents、Update、Drawのパラメーターとして渡すことを提案しています。
最終的に、メインループは状態エンジンのみを処理します。
int main ( int argc, char *argv[] )
{
CGameEngine game;
// initialize the engine
game.Init( "Engine Test v1.0" );
// load the intro
game.ChangeState( CIntroState::Instance() );
// main loop
while ( game.Running() )
{
game.HandleEvents();
game.Update();
game.Draw();
}
// cleanup the engine
game.Cleanup();
return 0;
}