替代游戏状态系统?


30

据我所知,大多数游戏都有某种“游戏状态系统”,可以在不同的游戏状态之间进行切换。这些可能是“ Intro”,“ MainMenu”,“ CharacterSelect”,“ Loading”和“ Game”之类的东西。

一方面,将它们分成一个状态系统是完全有意义的。毕竟,它们是完全不同的,否则将需要包含在大的switch语句中,这显然很混乱。它们肯定由国家系统很好地代表。但是同时,我查看了“游戏”状态,想知道这种状态系统方法是否存在问题。因为就像房间里的大象。这是巨大且显而易见的,但没人质疑游戏状态系统的方法。

对我来说,“游戏”与“主菜单”处于同一级别似乎很愚蠢。但是,没有办法打破“游戏”状态。

游戏状态系统是最好的方法吗?是否有一些更好的技巧来管理“游戏状态”?有一个介绍电影的状态并听其进入的介绍状态,然后是在资源管理器上循环的加载状态,然后是实际上可以完成所有工作的游戏状态,这可以吗?这对您来说似乎也不平衡吗?我想念什么吗?

Answers:


30

我认为您在这里只是在争论语义。之所以称为游戏状态,是因为它的行为类似于有限状态机,具有有限数量的状态以及它们之间的过渡。“游戏状态系统”中的“游戏”是指整个系统,其中“加载”,“ MainMenu”等是游戏状态。这些可以轻松地称为“场景”或“屏幕”或“级别”。它只是语义。

我不确定严格的FSM是否适用。在我的实现中,我将状态称为“屏幕”,并允许它们可堆叠-即。可以在其他屏幕之上绘制屏幕,​​控制是否更新或绘制其下方的屏幕。这样,我可以同时激活多个屏幕,并具有针对该屏幕的独立逻辑和代码,而不必担心任何其他屏幕。

例如,可以在我的主要游戏屏幕上方打开“暂停”屏幕,该屏幕不允许更新,但允许在其下方绘制。角色清单屏幕可能同时允许绘制和更新-因此,在您处理清单时,游戏可以继续玩。


这正是应该做的。屏幕应能够在树状体系结构中包含多个其他屏幕。因此,您的程序包含一个游戏屏幕,其中包含一个暂停菜单屏幕,其中包含一个音频设置屏幕和一个游戏设置屏幕。等等
伊恩(Iain)2010年

1
我希望看到示例源代码!(最好使用C ++ / C#/ Java)
Zolomon

1
不幸的是,目前我只有生产代码,但是XNA Game State示例中有一个类似的概念:creators.xna.com/en-GB/samples/gamestatemanagement
DrDeth 2010年

7

当然,游戏状态将是巨大的,但没有理由使游戏状态本身不能包含状态机来管理其数据。分层状态机非常有用。


4

我总是喜欢将每个“状态”都视为一个“场景”。因此,开幕视频只是一个场景,只是一个静态的场景。学分是一个场景。菜单是一个场景。它们之间的唯一区别是交互性和游戏逻辑的水平。


3

实际上,我对此也有问题。

假设您有一个游戏。

不要将“游戏”的状态设置为“正在加载”,“主菜单”等状态-IMO,最好让游戏具有以下几种状态:

“正在加载” - “显示菜单” - “已暂停”

游戏仍在运行,但是当它显示主菜单时它将处于“显示菜单”模式。

而当Game不在任何特定状态时,它就在运行。

至少对我来说,这更有意义。:)


我同意。没有人想退出游戏状态只是进入暂停状态。另一方面:它仍然是一个状态系统..只是嵌套的:)
bummzack 2010年

2

在线程序(按照在线的传统含义,即持续运行并响应输入,而不是连接到互联网的意思)通常由三部分组成:

  • 输入收集和处理
  • 逻辑更新
  • 输出

一般来说,这三个是同时关联和变化的。例如,在显示初始屏幕时,您可能会将所有按键映射到“关闭屏幕”命令,并且更新可能会使图形逐渐褪色,而输出仅显示该图形。但是在玩游戏时,按键可能都映射到不同的命令,并且更新操作正在更改许多游戏对象的属性。

当您以这种方式查看它时,将Intro和Character Creation和Game分开是有意义的:每个Intro都有自己的一组输入,更新和输出规则。它们几乎就像是独立的程序,恰好共享一些数据和库代码。而且,考虑到这一点,通常只有一个游戏状态才有意义,因为整个游戏过程都相当同质。

当然,如果您确实有不同类型的游戏方式(例如,RPG示例-世界地图,城镇地图,过场动画,战斗),并且输入,更新和输出不同,那么就没有理由没有多个状态也不仅仅是1个游戏状态。但这取决于您的游戏。


1

我换种方式看。“菜单”,“高分”,“积分”或您拥有的所有东西都可以被视为另一个级别,然后该状态不一定比您的“游戏”状态轻(游戏状态通常恰好具有更多实体,和不同的对象,但最后只是实体碰巧显示出更多可预测行为的另一层次,而“地图”通常不太复杂)。
在您的思维中进行切换肯定会使您脱离“无聊的菜单”综合症。


我要说的也是一样...我所有的菜单,屏幕,无论是什么,都只是另一个层次。
speeder 2010年

1

在我的游戏中,我有:

执行管理器,用于初始化应用程序(游戏),加载资源,在应用程序退出时释放资源等。它会初始化应用程序引擎,GameViewEngine和GameLogicEngine。

游戏状态管理器,位于GameLogicEngine中,负责控制与游戏主循环有关的事物:碰撞检测,物理计算,键盘读取,数学运算等。

最初,我倾向于只有一个Game State Manager,这是我的GameLogicEngine的一部分。但是,在控制主要子系统(GameLogic,ApplicationEngine等)的初始化方面,我遇到了一些困难。本可以做到的,但是它更加混乱了,imo。

现在事情对我来说看起来更加透明,我对设计感到满意。


0

将“游戏”状态重命名为“游戏性”。这样您的逻辑似乎更好了;您停止播放以转到菜单:退出游戏状态以进入MainMenu状态。

另外,我认为诸如暂停之类的事情不应要求游戏处于与暂停游戏时相同的状态,而暂停等则要求游戏处于与暂停游戏时相同的状态。子状态和嵌套,也许吗?游戏具有-暂停菜单。


0

我认为有一个很好的方法,称为游戏状态堆栈。我还没有看过任何关于它的论文或文章,但是它已经通过声音传播了一点。本质上,栈中最顶层的游戏状态被首先调用,并且可以通过输入/渲染等方式完成它想要做的任何事情。最顶层的游戏状态是唯一允许推入或弹出状态的状态。

在我的引擎中,游戏状态实际上只是游戏实体的列表。然后,我有充当菜单的实体。我的菜单状态要么暂停游戏(不更新堆栈中的下一个项目),但让其他状态将其模型推送到渲染器,以便我的暂停菜单(不覆盖整个屏幕)仍然背面有游戏渲染。

我希望能给出一些不基于状态机的不同系统的想法。


0

有一个介绍电影的状态并听其进入的介绍状态,然后是在资源管理器上循环的加载状态,然后是几乎可以完成所有工作的游戏状态,可以吗?这对您来说似乎也不平衡吗?我想念什么吗?

很好 或至少,这是对“根据游戏的状态进行较大的难看的切换”的改进。

我想指出的是,在大多数游戏中,为了处理简单的实体AI,您已经需要某种有限状态机。典型的例子是处于空闲状态,正在攻击或死亡的敌人。

如果您拥有足够抽象的有限状态机,则可以将其用于Game对象和您的AI。突然之间,您没有在“游戏”状态上“投入”大量精力-而是您正在重用您一直使用的代码。

随之而来的是无耻的自拔:我已经在我的Lua游戏库MiddleClass中实现了这样的有限状态机(具体来说,名为MindState的附加组件)。这是您如何使用Game State做事的方法


0

解决此问题的另一种方法是使用函数式编程世界中的一个称为“区别联盟”的概念。尽管通常可以在FP语言中找到它们,但是您可以使用classes模拟它们

基本上,“ 区分联合”是一种始终为n个案之一的类型,并且存储的数据可能会因个案而异。

例如:

type GameState =
  | Menu of MenuState
  | Playing of SimulationState

在这里,我们的GameState类型可以是MenuPlaying。如果为Menu,则它将包含一个MenuState对象。如果为Playing,则它将包含一个SimulationState对象。

要进行更新,我们将match在状态上,并相应地调用另一个函数:

let update gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> updateMenu gameTime menuState
    | Playing simulationState -> updateSimulation gameTime simulationState

  // Mutate the current state
  gameState <- nextState

并且类似的渲染:

let render gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> renderMenu menuState
    | Playing simulationState -> renderSimulation simulationState

这种方法的一个优势是,您可以更轻松地跨状态(例如资源)处理事务,而无需全局变量或传递“服务”对象。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.