在前面一篇《状态机4,关于战斗中负责兵种状态切换的状态机》中实现了一个简单的状态机
在最后抛出了为什么说简单的问题,因为在一个复杂的战斗中,一个角色很少说只有一个状态,
或者说根本不可能,多状态是合理的需求,在之前实现的状态机中,角色同时只能有一个状态,
要么行走状态,要么冰冻状态,从代码逻辑上看,一个新的状态进来当前的状态会被顶替掉,
来看需求:一个角色的攻击的过程中中了一个中毒buff,在一段时间内会持续掉血,这种情况下
角色会同时有两个状态,攻击状态和中毒状态,中毒状态不会顶替攻击状态,在中毒状态下角色
也可以切换到行走状态,冰冻状态等等,那么从以上的需求来看,
我们可以把状态分为两种类型:主状态和子状态,
主状态:如待机状态,行走状态,攻击状态,冰冻状态等等,它们的特点是相互这间互斥,
角色在同一时刻只能处于其中一种状态,新的主状态进来会顶替当前的主状态
子状态:如中毒状态,变羊状态,隐身状态等等,它们的特点是相互之间独立,且不会顶替
掉主状态,如角色可以同时处于行走状态,中毒状态,隐身状态
经过上面的总结,我们把上一篇文章里提到的状态做下分类,并加入一些新的状态
主状态:待机状态,行走状态,攻击状态,冰冻状态,眩晕状态
子状态:中毒状态,网捕状态,变羊状态
总结完之后,大概说下新的状态机的原理,大部分跟之前的简单状态机一样,不同的地方在于切换
状态的时候,需要做一些额外的逻辑处理,
1.如果新进来的状态是子状态,那么直接新增一个子状态,并直接返回不做其他处理,
子状态可以独立添加和移除
2.如果新进来的状态是主状态,那么先检查一下角色身上的子状态,为什么要做检查,
下面说一下一些情况就能明白,
假如角色现在处于攻击状态,在此状态下中了一个网捕buff,网捕buff的作用是让角色
不能行走,带有网捕状态的角色只能呆在原地做攻击,待机等等行为,
再假如角色现在处于行走状态,在此状态下中了一个变羊的buff,变羊buff的作用是让角色
变成羊的模型,带有变羊状态的角色不能使用技能,不能攻击,其他如行走,冰冻是可以的
通过上面的例子可以总结出来,子状态的存在会影响到主状态的切换,那么我们的状态切换
规则就分三步:
1.如果新进来的状态是子状态,那么直接添加
2.如果新进来的状态是主状态,那么分下面几步:
如果是相同的状态,则直接返回
如果不是相同的状态,那么检查自身的子状态,是否有影响到主状态的切换的子状态
如果没有影响到主状态切换的子状态,那么检查是否有可切换的主状态
下面来看代码:
StateId.lua:状态id,没什么大的区别,只是新加了几个新的状态id,子状态从500开始,做区分
local StateId = {}
StateId.unKnown = -1
StateId.idle = 1 --待机
StateId.walk = 2 --行走
StateId.attack = 3 --攻击
StateId.frozen = 4 --冰冻
StateId.vertigo = 5 --眩晕
StateId.subStateStartId = 500 --子状态开始id
StateId.poisoning = 501 --中毒
StateId.netCatch = 502 --网捕
StateId.sheep = 503 --羊
StateId.name = {}
StateId.name[StateId.idle] = "待机状态"
StateId.name[StateId.walk] = "行走状态"
StateId.name[StateId.attack] = "攻击状态"
StateId.name[StateId.frozen] = "冰冻状态"
StateId.name[StateId.vertigo] = "眩晕状态"
StateId.name[StateId.poisoning] = "中毒状态"
StateId.name[StateId.netCatch] = "网捕状态"
StateId.name[StateId.sheep] = "羊状态"
return StateId
StateRuleConfig.lua:这个跟之前的有些区别,分为可切换的主状态和互斥的子状态
拿一个出来说一下,假设当前角色处于攻击状态(3)和网捕状态(502),要切换掉行走状态(2),
那么新进来的状态是主状态,要先判断是否有影响主状态切换的子状态,行走状态的id是2,那么取出
来的配置是:StateRuleConfig[2] = {majorStateCanToggle = {1, 3, 4, 5}, mutexSubState = {502}}
此时角色身上有网捕状态(502),在互斥配置中的相同的id,那么无法切换到行走状态
StateRuleConfig = {}
--状态id:待机状态(1),行走状态(2),攻击状态(3),冰冻状态(4),眩晕状态(5),中毒(501),网捕(502),羊(503)
--majorStateCanToggle:可切换的主状态
--mutexSubState:互斥子状态,
StateRuleConfig[1] = {majorStateCanToggle = {2, 3, 4, 5}, mutexSubState = {}}
StateRuleConfig[2] = {majorStateCanToggle = {1, 3, 4, 5}, mutexSubState = {502}}
StateRuleConfig[3] = {majorStateCanToggle = {1, 2, 4, 5}, mutexSubState = {503}}
StateRuleConfig[4] = {majorStateCanToggle = {1}, mutexSubState = {}}
StateRuleConfig[5] = {majorStateCanToggle = {1}, mutexSubState = {}}
retur