feat: add a finite state machine to actors
This commit is contained in:
parent
84e48c0320
commit
75145f1485
4 changed files with 113 additions and 0 deletions
102
sonic-radiance.love/birb/classes/states/init.lua
Normal file
102
sonic-radiance.love/birb/classes/states/init.lua
Normal file
|
@ -0,0 +1,102 @@
|
|||
-- classes/states :: a finite state machine for objects
|
||||
|
||||
--[[
|
||||
Copyright © 2022 Kazhnuz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local StateMachine = Object:extend()
|
||||
|
||||
function StateMachine.addState(self, name, state, isDefault)
|
||||
if (self.states == nil) then
|
||||
self.states = {}
|
||||
self.states.list = {}
|
||||
end
|
||||
|
||||
self.states.list[name] = state
|
||||
|
||||
if (isDefault == true) then
|
||||
self.states.default = name
|
||||
end
|
||||
end
|
||||
|
||||
function StateMachine.addStates(self, statesPath, default)
|
||||
local states = require(statesPath)
|
||||
for i, stateName in ipairs(states) do
|
||||
local state = require(statesPath .. "." .. stateName)
|
||||
self:addState(stateName, state)
|
||||
end
|
||||
self.states.default = default
|
||||
end
|
||||
|
||||
function StateMachine:initStates()
|
||||
if (self.states == nil) then
|
||||
self.states = {}
|
||||
self.states.list = {}
|
||||
end
|
||||
self.currentState = self.states.default or "none"
|
||||
end
|
||||
|
||||
function StateMachine:updateState(dt)
|
||||
self:playStateFunc("update", dt)
|
||||
end
|
||||
|
||||
function StateMachine:haveState(state)
|
||||
return (self.states.list[state] ~= nil)
|
||||
end
|
||||
|
||||
function StateMachine:setState(state)
|
||||
if (not self:haveState(state)) then
|
||||
return self.currentState
|
||||
end
|
||||
self:playStateFunc("stop", state)
|
||||
local currentState = self.currentState
|
||||
self.currentState = state
|
||||
self:playStateFunc("start", currentState)
|
||||
return state
|
||||
end
|
||||
|
||||
function StateMachine:getState()
|
||||
return self.states.list[self.currentState]
|
||||
end
|
||||
|
||||
function StateMachine:getStateVar(varName, default)
|
||||
local state = self:getState()
|
||||
if (state == nil) then
|
||||
return nil
|
||||
end
|
||||
local var = state[varName]
|
||||
if (var == nil) then
|
||||
return default
|
||||
end
|
||||
return var
|
||||
end
|
||||
|
||||
function StateMachine:playStateFunc(funcName, ...)
|
||||
local state = self:getState()
|
||||
if (state == nil) then
|
||||
return
|
||||
end
|
||||
local func = state[funcName]
|
||||
if (func ~= nil) then
|
||||
func(self, ...)
|
||||
end
|
||||
end
|
||||
|
||||
return StateMachine
|
|
@ -29,6 +29,8 @@ local TimedActor = require("birb.modules.world.actors.mixins.timers")
|
|||
local InputActor = require("birb.modules.world.actors.mixins.inputs")
|
||||
local PhysicalActor = require("birb.modules.world.actors.mixins.physics")
|
||||
|
||||
local StateMachine = require("birb.classes.states")
|
||||
|
||||
local Actor2D = Rect:extend()
|
||||
Actor2D:implement(BaseActor)
|
||||
Actor2D:implement(SpritedActor)
|
||||
|
@ -36,6 +38,8 @@ Actor2D:implement(TimedActor)
|
|||
Actor2D:implement(InputActor)
|
||||
Actor2D:implement(PhysicalActor)
|
||||
|
||||
Actor2D:implement(StateMachine)
|
||||
|
||||
local Hitbox = require "birb.modules.world.actors.utils.hitbox2D"
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
|
@ -49,6 +53,7 @@ function Actor2D:new(world, type, x, y, w, h, isSolid)
|
|||
self:initTimers()
|
||||
self:initSprite()
|
||||
self:initKeys()
|
||||
self:initStates()
|
||||
end
|
||||
|
||||
function Actor2D:destroy()
|
||||
|
|
|
@ -33,6 +33,8 @@ local InputActor = require("birb.modules.world.actors.mixins.inputs")
|
|||
local PhysicalActor = require("birb.modules.world.actors.mixins.physics")
|
||||
local Shape3DActor = require("birb.modules.world.actors.mixins.shapes")
|
||||
|
||||
local StateMachine = require("birb.classes.states")
|
||||
|
||||
local Actor3D = BasicBox:extend()
|
||||
Actor3D:implement(BaseActor)
|
||||
Actor3D:implement(SpritedActor)
|
||||
|
@ -41,6 +43,8 @@ Actor3D:implement(InputActor)
|
|||
Actor3D:implement(PhysicalActor)
|
||||
Actor3D:implement(Shape3DActor)
|
||||
|
||||
Actor3D:implement(StateMachine)
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialise the actor and its base functions
|
||||
|
||||
|
@ -52,6 +56,7 @@ function Actor3D:new(world, type, x, y, z, w, h, d, isSolid)
|
|||
self:initSprite()
|
||||
self:initKeys()
|
||||
self:initShape(Boxes, true)
|
||||
self:initStates()
|
||||
end
|
||||
|
||||
function Actor3D:destroy()
|
||||
|
|
|
@ -88,6 +88,7 @@ end
|
|||
function BaseActor:update(dt)
|
||||
self:updateStart(dt)
|
||||
self:applyUpdateFunctions(dt)
|
||||
self:updateState(dt)
|
||||
self:updateEnd(dt)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue