Lua FSM有限状态机的实现

转自https://www.cnblogs.com/SeaSwallow/p/7118676.html
最近做项目,因为要将游戏的代码基本全部改成lua的,对c#层面的东西基本只要unity的生命周期就可以了。刚开始接触lua,心痒痒,决定上网买了《Lua游戏AI开发指南》看看,决定实现一个fsm以便于在项目中使用。在这里贴出代码,其实代码都是直接抄这本书的。建议直接买书看,对于不想买书又想实现lua的状态机的可以直接拿下面的代码使用就可以了。

Action
1 Action = {}
 2 
 3 Action.Status = {
 4     RUNNING = "RUNNING",
 5     TERMINATED = "TERMINATED",
 6     UNINIIALIZED = "UNINIIALIZED"
 7 }
 8 
 9 Action.Type = "Action"
10 
11 
12 function Action.new(name,initializeFunction,updateFunction,cleanUpFunction,userData)
13 
14     local action = {}
15 
16     action.cleanUpFunction_ = cleanUpFunction
17     action.initializeFunction_ = initializeFunction
18     action.updateFunction_  = updateFunction
19     action.name_ = name or ""
20     action.status_ = Action.Status.UNINIIALIZED
21     action.type_ = Action.Type
22     action.userData_ = userData
23 
24     action.CleanUp = Action.CleanUp
25     action.Initialize = Action.Initialize
26     action.Update = Action.Update
27 
28     return action
29 end
30 
31 function Action.Initialize(self)
32     if self.status_ == Action.Status.UNINIIALIZED then
33         if self.initializeFunction_ then
34             self.initializeFunction_(self.userData_)
35         end
36     end
37 
38     self.status_ = Action.Status.RUNNING
39 end
40 
41 
42 function Action.Update(self,deltaTimeInMillis)
43     if self.status_ == Action.Status.TERMINATED then
44         return Action.Status.TERMINATED
45     elseif self.status_ == Action.Status.RUNNING then
46         if self.updateFunction_ then
47             self.status_ = self.updateFunction_(deltaTimeInMillis,self.userData_)
48 
49             assert(self.status_)
50         else
51             self.status_ = Action.Status.TERMINATED
52         end
53     end
54 
55     return self.status_
56 
57 end
58 function Action.CleanUp(self)
59     if self.status_ == Action.Status.TERMINATED then
60         if self.cleanUpFunction_ then
61             self.cleanUpFunction_(self.userData_)
62         end
63     end
64 
65     self.status_ = Action.Status.UNINIIALIZED
66 end

FiniteState

1 require "Action"
 2 --require "FiniteState"
 3 require "FiniteStateTransition"
 4 
 5 FiniteState = {}
 6 
 7 function FiniteState.new(name,action)
 8     local state = {}
 9     -- 状态的数据
10     state.name_ = name
11     state.action_ = action
12 
13     return state
14 end

FiniteStateTransition

1 FiniteStateTransition = {}
 2 
 3 function FiniteStateTransition.new(toStateName,evaluator)
 4     local transition = {}
 5 
 6     -- 状态转换条件的数据
 7     transition.evaluator_ = evaluator
 8     transition.toStateName_ = toStateName
 9 
10     return transition
11 end

FiniteStateMachine

1 require "Action"
  2 require "FiniteState"
  3 require "FiniteStateTransition"
  4 
  5 FiniteStateMachine = {}
  6 
  7 function FiniteStateMachine.new(userData)
  8     local fsm = {}
  9 
 10     -- 状态机的数据
 11     fsm.currentState_ = nil
 12     fsm.states_ = {}
 13     fsm.transition_ = {}
 14     fsm.userData_ = userData
 15 
 16     fsm.AddState = FiniteStateMachine.AddState
 17     fsm.AddTransition = FiniteStateMachine.AddTransition
 18     fsm.ContainState = FiniteStateMachine.ContainState
 19     fsm.ContainTransition = FiniteStateMachine.ContainTransition
 20     fsm.GetCurrentStateName = FiniteStateMachine.GetCurrentStateName
 21     fsm.GetCurrentStateStatus = FiniteStateMachine.GetCurrentStateStatus
 22     fsm.SetState = FiniteStateMachine.SetState
 23     fsm.Update = FiniteStateMachine.Update
 24 
 25     return fsm
 26 end
 27 
 28 
 29 function FiniteStateMachine.ContainState(self,stateName)
 30     return self.states_[stateName] ~= nil
 31 end
 32 
 33 function FiniteStateMachine.ContainTransition(self,fromStateName,toStateName)
 34     return self.transition_[fromStateName] ~= nil and
 35         self.transition_[fromStateName][toStateName] ~= nil
 36 end
 37 
 38 function FiniteStateMachine.GetCurrentStateName(self)
 39     if self.currentState_ then
 40         return self.currentState_.name_
 41     end
 42 end
 43 
 44 function FiniteStateMachine.GetCurrentStateStatus(self)
 45     if self.currentState_ then
 46         return self.currentState_.action_.status_
 47     end
 48 end
 49 
 50 
 51 function FiniteStateMachine.SetState(self,stateName)
 52     if self:ContainState(stateName) then
 53         if self.currentState_ then
 54             self.currentState_.action_:CleanUp()
 55         end
 56 
 57         self.currentState_ = self.states_[stateName]
 58         self.currentState_.action_:Initialize()
 59     end
 60 end
 61 function FiniteStateMachine.AddState(self,name,action)
 62     self.states_[name] = FiniteState.new(name,action)
 63 end
 64 
 65 function FiniteStateMachine.AddTransition(self,fromStateName,toStateName,evaluator)
 66     if self:ContainState(fromStateName) and
 67         self:ContainState(toStateName) then
 68 
 69         if self.transition_[fromStateName] == nil then
 70             self.transition_[fromStateName] = {}
 71         end
 72 
 73         table.insert(
 74             self.transition_[fromStateName],
 75             FiniteStateTransition.new(toStateName,evaluator)
 76         )
 77 
 78     end
 79 end
 80 local function EvaluateTransitions(self,transitions)
 81     for index = 1 , #transitions do
 82         if transitions[index].evaluator_(self.userData_) then
 83             return transitions[index].toStateName_;
 84         end
 85     end
 86 end
 87 function FiniteStateMachine.Update(self,deltaTimeInMillis)
 88     if self.currentState_ then
 89         local status = self:GetCurrentStateStatus()
 90 
 91         if status == Action.Status.RUNNING then
 92             self.currentState_.action_:Update(deltaTimeInMillis)
 93         elseif status == Action.Status.TERMINATED then
 94             local toStateName = EvaluateTransitions(self,self.transition_[self.currentState_.name_])
 95 
 96             if self.states_[toStateName] ~= nil then
 97                 self.currentState_.action_:CleanUp()
 98                 self.currentState_ = self.states_[toStateName]
 99                 self.currentState_.action_:Initialize()
100             end
101         end
102     end
103 end

下面是测试代码

SoldierActions

1 timer = 0
 2 
 3 function SoldierActions_IdleCleanUp(userData)
 4     print("SoldierActions_IdleCleanUp data is "..userData)
 5     timer = 0
 6 end
 7 
 8 function SoldierActions_IdleInitialize(userData)
 9     print("SoldierActions_IdleInitialize data is "..userData)
10     timer = 0
11 end
12 
13 function SoldierActions_IdleUpdate(deltaTimeInMillis,userData)
14     print("SoldierActions_IdleUpdate data is "..userData)
15     timer = (timer + 1)
16     if timer > 3 then
17         return Action.Status.TERMINATED
18     end
19 
20     return Action.Status.RUNNING
21 end
22 
23 
24 function SoldierActions_DieCleanUp(userData)
25     print("SoldierActions_DieCleanUp data is "..userData)
26     timer = 0
27 end
28 
29 function SoldierActions_DieInitialize(userData)
30     print("SoldierActions_DieInitialize data is "..userData)
31     timer = 0
32 end
33 
34 function SoldierActions_DieUpdate(deltaTimeInMillis,userData)
35     print("SoldierActions_DieUpdate data is "..userData)
36     timer = (timer + 1)
37     if timer > 3 then
38         return Action.Status.TERMINATED
39     end
40 
41     return Action.Status.RUNNING
42 end

SoldierEvaluators

1 function SoldierEvaluators_True(userData)
2     print("SoldierEvaluators_True data is "..userData)
3     return true
4 end
5 
6 function SoldierEvaluators_False(userData)
7     print("SoldierEvaluators_True data is "..userData)
8     return false
9 end

SoldierLogic

1 require "SoldierActions"
 2 require "FiniteStateMachine"
 3 require "SoldierEvaluators"
 4 
 5 local function IdleAction(userData)
 6     return Action.new(
 7         "idle",
 8         SoldierActions_IdleInitialize,
 9         SoldierActions_IdleUpdate,
10         SoldierActions_IdleCleanUp,
11         userData
12     )
13 end
14 
15 
16 local function DieAction(userData)
17     return Action.new(
18         "die",
19         SoldierActions_DieInitialize,
20         SoldierActions_DieUpdate,
21         SoldierActions_DieCleanUp,
22         userData
23     )
24 end
25 
26 function SoldierLogic_FiniteStateMachine(userData)
27     local fsm = FiniteStateMachine.new(userData)
28     fsm:AddState("idle",IdleAction(userData))
29     fsm:AddState("die",    DieAction(userData))
30 
31     fsm:AddTransition("idle","die",SoldierEvaluators_True)
32     fsm:AddTransition("die","idle",SoldierEvaluators_True)
33 
34     fsm:SetState('idle')
35 
36     return fsm
37 end
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在导出一个lua状态的所有函数时,首先需要明确导出哪些函数。在Lua中可以通过在C语言中调用该状态的函数来实现Lua中定义的函数交互,因此我们需要将需要导出的函数在C语言中进行实现。 导出函数时需要注意以下几点: 1. 需要使用luaL_Reg结构定义需要导出的函数属性,其中包含函数名和函数指针; 2. 在实现C语言函数时,需要将其与Lua中的参数和返回值进行对应; 3. 调用luaL_register函数注册需要导出的函数,传入函数表名和函数表属性,同时借助luaL_newlib函数创建新的函数表。 例如,我们需要导出以下三个函数: 1. 输出Hello World:printHello() 2. 计算两个数字的和:add(x, y) 3. 判断一个数是否为正数:isPositive(num) 那么在C语言中,可以这样实现: static int l_printHello(lua_State *L) { printf("Hello World\n"); return 0; } static int l_add(lua_State *L) { double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); lua_pushnumber(L, x + y); return 1; } static int l_isPositive(lua_State *L) { double num = luaL_checknumber(L, 1); lua_pushboolean(L, num > 0); return 1; } 然后我们需要将其存到一个luaL_Reg结构体数组里,如下: static const struct luaL_Reg myfuncs[] = { {"printHello", l_printHello}, {"add", l_add}, {"isPositive", l_isPositive}, {NULL, NULL} }; 最后,我们可以在Lua中这样使用这些函数: local mylib = require("mylib") mylib.printHello() -- 输出Hello World print(mylib.add(1, 2)) -- 输出3 print(mylib.isPositive(-1)) -- 输出false 因此,以上就是导出一个lua状态的所有函数的步骤和实现方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值