我曾经见过一篇文章,非常优雅地解决了您的问题。这是一个基本的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();
};
每个游戏状态都由该接口的实现表示。对于您的Battlechess示例,这可能意味着以下状态:
- 介绍动画
- 主菜单
- 棋盘设置动画
- 玩家移动输入
- 玩家移动动画
- 对手移动动画
- 暂停菜单
- 残局屏幕
在您的状态引擎中管理状态:
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;
}