在做的一个项目,由于人物的状态较多,切换比较麻烦不便管理,所以打算引入状态机,方便管理。下面是fsm的简易版本,还有些待完善的地方。
local inspect = require "inspect"
local FSMState = {}
function FSMState:new(super)
local obj = super or {}
obj.super = self
return setmetatable(obj, {__index = self})
end
function FSMState:enter()
print(string.format("%s enter", self.name))
end
function FSMState:exit()
print(string.format("%s exit", self.name))
end
local FSMStateMachine = {}
function FSMStateMachine:new()
local obj = {
idle = FSMState:new{name="idle"},
walk = FSMState:new{name="walk"},
attack = FSMState:new{name="attack"},
event = {
idle = {},
walk = {},
attack = {},
},
_curState = "idle",
}
return setmetatable(obj, {__index = self})
end
function FSMStateMachine:addTransition(before, input, after)
if self.event[before] then
if self.event[before][input] then assert("event already be added")
else
self.event[before][input] = after
end
end
end
function FSMStateMachine:stateTransition(event)
assert(self._curState)
print(self._curState)
local out = self.event[self._curState][event]
if out then
print(string.format("reponse to event:%s", event))
-- respond to this event
self[self._curState]:exit()
self._curState = out
self[self._curState]:enter()
else
-- no related event
print(string.format("no reponse to event:%s", event))
end
end
------------------------------------------------------------------
----test
------------------------------------------------------------------
local sm = FSMStateMachine:new()
--print(inspect(sm))
sm:addTransition("idle", "seen player", "walk")
sm:addTransition("idle", "player attack", "attack")
sm:addTransition("walk", "player go away", "idle")
sm:addTransition("attack", "player die", "idle")
--print(inspect(sm))
sm:stateTransition("player attack")
sm:stateTransition("seen player")
输出的结果: