参考:http://www.it165.net/pro/html/201403/10111.html
注:写这篇文章的时候,笔者所用的是quick-cocos2d-x 2.2.5rc版本
状态机的设计,目的就是为了避免大量状态的判断带来的复杂性,消除庞大的条件分支语句,因为大量的分支判断会使得程序难以修改和扩展。但quick状态机的设计又不同设计模式的状态模式,TA没有将各个状态单独划分成单独的状态类,相反根据js、lua语言的特点,特别设计了写法,使用起来也比较方便。
推荐大家在理解的时候结合 sample/statemachine 范例进行理解,注意player设置成竖屏模式,demo里面的按钮在横屏模式下看不见。
fsm:setupState({ initial = "green", events = { {name = "warn", from = "green", to = "yellow"}, {name = "panic", from = "green", to = "red" }, {name = "calm", from = "red", to = "yellow"}, {name = "clear", from = "yellow", to = "green" }, } })
initial:初始化状态
events:定义所有的event事件,和状态state变化
name:事件名字
from:事件表示的起始状态
to:事件表示的目的状态
args:额外的参数,用来传递用户自定义的一些变量值
之后,我们就可以通过:
fsm:doEvent("start"):从none状态转换到green状态
fsm:doEvent("warn"):从green状态转换到yellow状态
fsm:doEvent("panic"):从green状态转换到red状态
fsm:doEvent("calm"):从red状态转换到yellow状态
fsm:doEvent("clear"):从yellow状态转换到green状态
其他相关函数:
fsm:isReady():返回状态机是否就绪
fsm:getState():返回当前状态
fsm:isState(state):判断当前状态是否是参数state状态
fsm:canDoEvent(eventName):当前状态如果能完成eventName对应的event状态转换,则返回true
fsm:cannotDoEvent(eventName):当前状态如果不能能完成eventName对应的event状态转换,则返回true
fsm:isFinishedState():当前状态如果是最终状态则返回true
fsm:doEventForce(name,...):强制对当前状态进行转换
-- 状态转变后的回调
callbacks = {
onidle = function (event) self:idle() end,
onattack = function (event) self:attackEnemy() end,
onhit = function (event) self:hit() end,
ondead = function (event) self:dead() end
},
quick的状态机支持4种特定事件类型的回调:
onbeforeEVENT-在特定事件EVENT开始前被激活
onafterEVENT-在特定事件EVENT结束后被激活
onenterSTATE-在进入新状态STATE时被激活
onleaveSTATE-在离开旧状态STATE时被激活
注意:
onenterSTATE可以简写为onSTATE
onafterEVENT可以简写为onEVENT
另外,我们可以使用5种通用型的回调来捕获所有事件和状态的变化:
(注意先后顺序,正规流程)
onbeforeevent-在任何事件开始前被调用
onleavestate-在离开任何状态时被调用
onenterstate-在进入任何状态时被调用
onafterevent-在任何事件结束后被调用
onchangestate-当状态发生改变时被调用
3种影响事件响应的方式:
在onbeforeEVENT方法中返回false来取消事件
在onleaveSTATE方法中返回false来取消事件
在onleaveSTATE方法中返回‘async’来执行异步状态转换
有时候,我们需要在状态转换时执行一些异步代码来确保不会进入新状态直到代码执行完毕。
return "async" :这时状态机会被挂起,直到我们使用了event.transition()方法