zoukankan      html  css  js  c++  java
  • Lua FSM有限状态机的实现

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

     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
    Action
     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
    FiniteState
     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
    FiniteStateTransition
      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
    FiniteStateMachine

    下面是测试代码

     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
    SoldierActions
    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
    SoldierEvaluators
     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
    SoldierLogic

    基本就是这样,挺喜欢这个状态机的。

    这本书还有讲决策树和行为树的代码,以后有需求再实现一遍。

  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/SeaSwallow/p/7118676.html
Copyright © 2011-2022 走看看