lua 实现一个 StateMachine状态机

定义了一个状态机(StateMachine)类,用于管理对象在不同状态之间的转换和状态更新。状态机在游戏开发、机器人控制等领域中非常常见,用于控制对象的行为。

### 实现原理

1. **初始化**:`initialize`方法初始化状态机,设置代理(agent)、初始状态(initialState)和全局状态(globalState)。
2. **状态转换**:`changeState`方法用于将状态机从当前状态转换到新状态,并调用新旧状态的`enter`和`exit`方法。
3. **状态回退**:`revertToPreviousState`方法用于将状态机回退到前一个状态。
4. **状态更新**:`updateState`方法用于更新当前状态和全局状态。
5. **消息处理**:`handleMessage`方法用于处理传入的消息,根据当前状态和全局状态来决定如何响应。

### 用途

状态机可以用于控制对象在不同状态下的行为,例如:

- 游戏角色在不同状态下的行为(如行走、攻击、死亡等)。
- 机器人控制在不同环境下的行为(如导航、避障、充电等)。
- 用户界面元素在不同状态下的交互行为(如可点击、不可点击、选中、未选中等)。

### 注意事项

1. **状态类**:状态机依赖于状态类(如`initialState`、`globalState`、`newState`等),这些状态类需要实现`enter`、`exit`、`updateState`和`onMessage`等方法。
2. **代理**:状态机依赖于代理对象(`agent`),代理对象是状态机操作的对象,通常包含状态机需要的状态和行为。
3. **线程安全**:如果状态机在多线程环境中使用,需要确保状态转换和消息处理是线程安全的。
4. **性能**:频繁的状态转换和消息处理可能会影响性能,需要根据实际需求进行优化。


---@class StateMachine :MiddleClass
local StateMachine = class("StateMachine")

function StateMachine:initialize(agent, initialState, globalState)
    -- super.initialize(self)
    self._agent = agent

    self:setInitialState(initialState)
    self:setGlobalState(globalState)
end

function StateMachine:setAgent(agent)
    self._agent = agent
end

function StateMachine:getAgent()
    return self._agent
end

function StateMachine:setInitialState(initialState)
    self._previousState = nil
    self._currentState = initialState
end

function StateMachine:getCurrentState()
    return self._currentState
end

function StateMachine:getPreviousState()
    return self._previousState
end

function StateMachine:setGlobalState(globalState)
    self._globalState = globalState
end

function StateMachine:getGlobalState()
    return self._globalState
end

function StateMachine:updateState(...)
    if self._globalState~=nil then
        self._globalState:updateState(self._agent, ...)
    end
    if self._currentState~=nil then
        self._currentState:updateState(self._agent, ...)
    end
end

function StateMachine:changeState(newState, ...)
    self._previousState = self._currentState
    if self._currentState~=nil then
        self._currentState:exit(self._agent, ...)
    end
    self._currentState = newState
    if self._currentState~=nil then
        self._currentState:enter(self._agent, ...)
    end
end

function StateMachine:revertToPreviousState(...)
    if self._previousState==nil then
        return false
    end
    self:changeState(self._previousState, ...)
    return true
end

function StateMachine:isInState(state)
    local current = self._currentState
    return current==state or (current~=nil and current:getName()==state)
end

function StateMachine:handleMessage(message)
    if self._currentState~=nil and
        self._currentState:onMessage(self._agent, message)
    then
        return true
    end

    if self._globalState~=nil and
        self._globalState:onMessage(self._agent, message)
    then
        return true
    end

    return false
end

return StateMachine

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在导出一个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状态机的所有函数的步骤和实现方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值