65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 应用程序中的状态模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.68/5 (29投票s)

2001 年 9 月 14 日

4分钟阅读

viewsIcon

183189

downloadIcon

2624

基于状态模式的小型游戏框架

引言

当一个对象的行为需要根据其状态的改变而改变时,状态模式就非常有用。本文的目的是提供一个状态模式的实际应用示例。在这个例子中,状态模式被应用于一个小型的游戏框架。

在过去的一年中,我编写了一些小型 DirectX 游戏。我遇到的一个问题是游戏状态之间的转换。例如,当游戏开始时,我通常会显示一个介绍页面,其中包含一个显示游戏选项的菜单。然后,根据用户的选择,我需要启动游戏、显示最高分数或其他内容。我通过将所有这些选择视为不同的状态来解决了这个问题。

下面是一个展示我基于状态模式构建的游戏逻辑的图表。

Class diagram

在应用程序类 (CStatePattern_GameApp) 中,有一个名为 Run() 的函数,它提供了一个默认的消息循环。基本上,这个函数会更新游戏,然后处理所有其他消息。Update 函数只是简单地请求视图渲染当前帧。

为了避免开销,DoFrame 函数会根据帧率检查是否需要重绘内容。我不会过多地详细介绍帧率方面的内容,因为这并不是我文章的重点。但如果您感兴趣,所有与帧率相关aneous的代码都位于 CStatePattern_GameView 类中。

让我们回到状态模式。在下一节中,我将解释调用 DoFrame 函数时会发生什么。该函数主要有两个部分。首先完成的是游戏更新。通常,这就是您会更新当前状态下的所有游戏对象(例如飞船位置、碰撞检测等)的地方。

	m_GameManager.Update();

第二部分是游戏渲染。

	m_GameManager.Draw(pDC /* device context */ );

游戏管理器持有一个指向 CGameState 对象的指针。因此,当我们调用 CGameManager 对象的 Update 函数时,它将简单地把调用转发给当前状态对象。

	 m_pGameState->Update(this);

这个调用代表了状态模式的重要组成部分。如您所见,我们正在调用当前状态对象的 Update 函数,同时也将指向自身的指针作为参数传递。这样做的原因是,在执行完特定于状态的工作后,当前状态对象的 Update 函数将能够改变游戏的当前状态。

理解一个重要的点是,CGameManager 对象对游戏一无所知。正是 CGameState 的子类定义了游戏的逻辑以及游戏进行过程中的每个状态转换。

上面的声明非常重要。例如,假设在我们的游戏中,当用户按下空格键时,飞船会开火。基本上,CStatePattern_GameView 会收到一个键盘事件。视图会简单地将事件转发给游戏管理器。游戏管理器不了解任何游戏逻辑,因此它会将此事件转发给当前的状态对象。如果 PlayState 是当前状态,那么该状态的 KeyEvent 函数将检查按下的是哪个键。在这种情况下,它将开火。如果当前状态是 IntroductionState,那么该事件可能会产生完全不同的效果。

过渡

状态转换是该模式的另一个重要组成部分。

例如,CPlayStateUpdate 函数可能会检查玩家是否还有剩余的飞船。如果没有,该函数将像这样调用 CGameManagerChangeState 函数:

pGameManager->ChangeState(CGameOverState::Instance() /* singleton pattern */);
状态不是由游戏管理器改变的,而是由状态本身改变的。

上面的声明可能看起来很奇怪,但仔细想想,这只是逻辑。假设玩家在介绍页面时需要按 F1 来开始游戏。介绍页面知道当用户按下 F1 时该做什么。在这种情况下,它会通知游戏管理器将当前状态更改为 PlayState

演示项目

在我的演示项目中,我只是演示了一些状态转换。游戏开始时,我们处于介绍状态。该状态将等待用户按下某个键。根据按下的键,介绍状态将更改 CGameManager 的状态。F1 将切换到 CPlayState,F2 将切换到 CHighScoreState

在我的演示项目中,我进行了一些 TRACE 调用,以向您展示每次转换的详细信息。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.