实现大型状态机的最佳方法是什么?

时间:2011-06-16 20:54:09

标签: java switch-statement state-machine

基本上我有一个控制游戏角色攻击的状态机,其时间基于动画长度。

例如:

我从默认状态开始,如果玩家点击攻击按钮,它会启动攻击,切换状态并根据攻击长度设置计时器。状态机变得更复杂但是当我考虑可以取消的充电攻击时,可以根据击中的内容移动到不同状态的攻击,并且每个州都有独特的方式来处理受到攻击的角色。 目前我有大型的switch语句。我考虑过多态,但是对于每个状态都需要一个新类(例如,开始攻击,攻击和完成攻击都需要单独的状态)。

switch语句有效,但它非常大,并且不像基于继承的系统那样容易修改。

有关良好实施的任何建议吗?

编辑: 这是使用java。

5 个答案:

答案 0 :(得分:9)

对于较大的状态机,您必须注意“过渡爆炸”现象。事实证明,传统的有限状态机不提供重用许多状态的公共转换的机制,所以你最终重复过多而你的状态机“爆炸”(这也反对不要重复你自己( DRY)原则)。

出于这个原因,我建议使用分层状态机和实现技术,以便将这些状态机轻松映射到代码。有关分层状态机的更多信息,请参阅Wikipedia文章http://en.wikipedia.org/wiki/UML_state_machine

答案 1 :(得分:3)

考虑构建一个由表驱动的状态机。如果你考虑一个状态机的定义,你基本上有一组状态具有一个独特的初始状态,一个转换函数,并且(在这种情况下)是一个输入和输出字母表。

您可以构造一个由当前状态和输入索引的表,并使用指向函数的指针或函数类来表示发生的情况。该函数应该返回下一个状态。然后你可以将状态机构建为(伪代码):

 state := initial state
 while(state != STOP)
    state := (lookupTransition(inputs))()

其中lookupTransition(inputs)只是找到下一个状态。我在这里假设转换函数是没有参数返回状态的函数,所以lookupTransition(inputs)必须是你有很多输入的函数,返回一个返回状态的void参数函数的指针。

正确设置,您可以将所有状态机和行为放在一个表中,这可以很容易地修改和重新编译。

(有关额外的功劳,请弄清楚如何从文件加载该表,因此您根本不需要重新编译。)

<强>更新

在Java中,使用类似函数类的函数代替函数指针。

另一次更新

当然,另一种选择是使用状态机编译器,如Ragel

答案 2 :(得分:1)

Boost有一个完美的状态机,唯一的缺点就是习惯了模板/类型编程

http://www.boost.org/doc/libs/1_46_1/libs/statechart/doc/index.html

答案 3 :(得分:1)

在我身边,我正在使用stateforge和HFSM(http://www.stateforge.com/)。 并行状态,分层方法和观察者可以解决很多复杂的情况。

答案 4 :(得分:0)

我不能说我曾经使用它,但有http://commons.apache.org/scxml/。使用其他人建议的基于表格的方法手写也不难。