一、混乱的控制代码
首先考虑一个简单的“按B键触发玩家跳跃的场景”:
好,它拥有了基本的跳跃功能,但是会有一些问题:当你疯狂的按跳跃键时,主角就会一直浮空。最容易想到的处理办法就是添加一个状态字段,用来判断主角是否处于跳跃状态:
(资料图)
现在如果想添加另外一个动作:当玩家按下方向键时,如果角色在地上,我们想要她卧倒,而松开按键时站起来:
好,现在又出现了另外一个问题:玩家可以先按下键卧倒,再按跳跃键跳起,在空中放开下键,这将导致主角在跳一半时贴图变成了站立时的贴图。如果我们要修复,很容易想到:再加一个状态字段用来标识:
这看起来目前还算过得去,但是一个游戏主角能做的动作可能多达十多个几十个,每加入一个动作都会使代码数量增加一个级别,使代码可读性和可维护性、可拓展性减少一个量级,最重要的是,它会带来一堆BUG。
二、有限状态机
有限状态机(FSMs)可以很好地解决这一类问题,它有几个关键点:
状态机拥有所有可能状态的集合
状态机同时只能处于一个状态
一连串的输入和事件被发送给状态机
每个状态都有一系列的转移,每个转移与输入和另一状态相关
将上面的玩家控制的例子用状态机来表示:
将上述的有限状态机用代码来表示,首先想到的会是用enum和switch来实现:
四、状态模式
用枚举和分支来实现有限状态机明显会导致可读性和可维护性差,对于对OOP非常熟悉的人来说,每一个case分支都可能是一个使用面向对象的机会,由此产生了状态模式。在GoF中这样描述状态模式;
允许一个对象在其内部状态发生变化时改变自己的行为,该对象看起来好像修改了它的类型
把之前的枚举都转化成一个状态类,把switch的每个分支转换成一个共用方法(这里给卧倒状态新添加了一个chargeTime来实现蓄力释放技能的功能):
再将HeroineState作为Heroine类的一个字段,并将输入参数委托给HeroineState的handleInput和update方法来处理:
好,现在我们要改变主角Heroine的状态,只需要将HeroineState字段指向不同的HeroineState对象。让主对象通过改变委托的对象,来改变它的行为,这就是状态模式的基本思想了。
五、关于状态类的实例化
我们现在需要考虑如何来实例化状态类,用于状态之间的转换。
静态状态:如果状态对象没有其他数据字段,那么每个状态类就只需要一个实例,因为每个实例都将完全一样(享元模式)。当然,当状态对象中有其他状态相关的字段时,就不得不为这个状态类实例化多个对象。
六、入口行为和出口行为
状态模式的目标是将状态的行为和数据封装到单一类中。我们现在已经将状态的行为封装好,但是在状态的数据上还有一些问题。比如:
修改贴图的代码和状态耦合在了一起,在DuckingState类中出现了IMAGE_STAND的贴图代码,此时可以给状态一个入口行为来解决这个问题(出口行为同理):
七、并发状态机
假设现在要给主角一个拿枪的能力,并且在拿枪的时候它也同时能做完全一样的行为:跑动、跳跃、跳斩、卧倒、站立等,现在如何来设计状态类?或许需要翻倍的状态类:站立,持枪站立,跳跃,持枪跳跃……,此时不仅增加了大量的状态,而且增加了大量的冗余,持枪和不持枪的状态是完全一样的,只是多了一点负责射击的代码。
问题在于我们将两种状态绑定在了一个状态机上,所以处理方法就很明显了:使用两个单独的状态机:
如果在做什么有n个状态,而携带了什么有m个状态,要塞到一个状态机中,则需要n × m个状态。使用两个状态机,就只有n + m个
实现很简单,只是在原有基础上添加了几乎完全一样的少量代码:
八、分层状态机
如果对OOP敏感,很容易发现可以继续进行优化,站立、行走、奔跑、滑铲这些状态或许有很多重复的代码来处理与地面碰撞和跳跃的行为,此时可以定义一个地面类来处理这些行为,然后将它们继承自这个类(当然继承也会在这些类之间建立一些耦合,此时就需要进行平衡取舍):
九、下推自动机
考虑一个场景:给主角添加了一个射击状态,不管现在是什么状态,都能在按下开火按钮时跳转为射击状态,但关键问题是,如何在射击后转换为之前的状态。
解决方法是下推自动机,有限状态机有一个指向状态的指针,下推自动机有一个栈指针,它也可以实现状态之间的转换,并且:
可以将新状态压入栈中
可以弹出最上面的状态
标签:
精彩推荐
状态模式在AI、编译器和游戏开发领域应用广泛。游戏开发引擎unity中也
各位网友们好,我是编辑小夏,为大家解答996工作制和807工作制是什么意
今年,抚远市启动城市治理“路长制”工作,实现“路长制”与“网格化”
1、是husband吧!是老公的意思!采纳吧!。本文到此分享完毕,希望对大
朱棣造反夺取皇位后,发现一道朱允炆圣旨,看完顿时痛哭流涕,1399年,
你是我的专属恶魔恶魔女孩天使爱人恶魔毕业生恶魔右耳钉遇上恶魔军团恶
“颁奖礼仪”机器人亮相成都大运会
随着互联网的不断发展,大家在申请互联网小额贷款的时候,只需要在线上
免联考dba报名一般包括以下环节:1、提交登记材料;2、资格审查;3、面
1、好男友标准之一:成熟稳重。2、成熟的男人勇于承担责任,虽然有些过
工人日报-中工网记者邢生祥近日,青海省人社厅、省政法委等九部门联合
证券时报e公司讯,雄韬股份(002733)7月30日晚间公告,拟向特定对象发行
本文转自【央视财经微博】;受新一轮强降雨影响,长江重庆段出现明显涨
自1998年5月1日起,日本电影开始施行现行的4级制度,由映画伦理委员会
据科技日报报导,加拿大正在面临史上最严重森林火情!加拿大森林消防中
作者|闪电编辑|Duke来源|钛财经在新能源汽车已成汽车行业的主流之时
“桃子收成如何?基地里用电设备运行是否正常?”日前,国网泰顺县供电
北京:预计7月30日11时至8月1日9时本市仍有雷电活动---央视网消息。据
宝马760li多少钱宝马760li是宝马公司旗下的一款豪华轿车,以其出色的性
每经AI快讯,天风证券07月30日发布研报称,给予宏发股份(600885 SH,
资讯News
08-29
08-15
07-07
11-03
11-03
11-03
11-03
11-03
11-03
11-03
11-03
11-03
11-03
聚焦Policy
当好农民工的“护薪人” 近日,罗某等7名农民工在收到被拖欠的工资后,纷纷打电话向江西省南昌市...
“通讯录里所有人都知道我欠钱了” □ 本报记者 韩丹东 □ 本报见习记者 张守坤 ...
大连宝马车撞人案肇事司机被判死刑 本报讯 记者韩宇 10月29日,辽宁省大连市中级人民法院一审...
医院财务迷上网络赌博输光5000万元公款 □ 本报记者 马维博 □ 本报通讯员 汪宇堂 曹...
辊环车削 雕琢毫厘(工匠绝活) 【绝活看点】 23年来,雷虎始终扎根一线,改进钢材轧制工艺...
交警严查超标电动自行车挪用“白牌” 截至昨晚6时,处罚电动自行车违法行为共计6585笔;下一步将...
明起寒潮来袭 北方气温普降10℃以上 中央气象台预计,本周日北京平原地区最低气温降至-4℃左右...
多种蔬菜价格降幅达五成 包括菠菜、蒿子秆等 预计本月中旬蔬菜恢复供需平衡 本报讯(记者...
北京周日最低气温或达-4℃ 本报讯(记者 赵婷婷)北京青年报记者昨天从中央气象台获悉,新一股...
昌平一家四口确诊新冠肺炎 天通北苑第二社区升级为中风险地区 朝阳两涉疫校区及16所学校停课 ...