基本上我有一个控制游戏角色攻击的状态机,其时间基于动画长度。
例如:
我从默认状态开始,如果玩家点击攻击按钮,它会启动攻击,切换状态并根据攻击长度设置计时器。状态机变得更复杂但是当我考虑可以取消的充电攻击时,可以根据击中的内容移动到不同状态的攻击,并且每个州都有独特的方式来处理受到攻击的角色。 目前我有大型的switch语句。我考虑过多态,但是对于每个状态都需要一个新类(例如,开始攻击,攻击和完成攻击都需要单独的状态)。
switch语句有效,但它非常大,并且不像基于继承的系统那样容易修改。
有关良好实施的任何建议吗?
编辑: 这是使用java。
答案 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/。使用其他人建议的基于表格的方法手写也不难。