reactive character state implementation

- @todo: refactor character submodules
This commit is contained in:
PeaAshMeter 2025-09-14 01:51:18 +03:00
parent dd1d64506d
commit 30f8b1c769
4 changed files with 27 additions and 20 deletions

View File

@ -8,35 +8,28 @@ RIGHT = 1
--- @class Animation
--- @field animationTable table<string, table>
--- @field animationGrid table
--- @field state "idle"|"run"|"hurt"|"attack"
--- @field side 1|-1
local animation = {}
animation.__index = animation
local function new(id, spriteDir)
local anim = {
animationTable = {}
animationTable = {},
animationGrid = {}
}
local animationGrid = {}
-- n: name; i: image
for n, i in pairs(spriteDir) do
local aGrid = anim8.newGrid(96, 64, i:getWidth(), i:getHeight())
local tiles = '1-' .. math.ceil(i:getWidth() / 96)
animationGrid[n] = aGrid(tiles, 1)
anim.animationGrid[n] = aGrid(tiles, 1)
end
anim.state = "idle"
anim.side = RIGHT
anim.animationTable.idle = anim8.newAnimation(animationGrid["idle"], ANIMATION_SPEED)
anim.animationTable.run = anim8.newAnimation(animationGrid["run"], ANIMATION_SPEED)
anim.animationTable.attack = anim8.newAnimation(animationGrid["attack"], ANIMATION_SPEED, function()
anim.state = "idle"
end)
anim.animationTable.hurt = anim8.newAnimation(animationGrid["hurt"], ANIMATION_SPEED, function()
anim.state = "idle"
end)
return setmetatable(anim, animation)
end
@ -44,8 +37,9 @@ function animation:getState()
return self.state
end
--- @param state State
function animation:setState(state)
--- @param state CharacterState
function animation:setState(state, onLoop)
self.animationTable[state] = anim8.newAnimation(self.animationGrid[state], ANIMATION_SPEED, onLoop)
self.state = state
end

View File

@ -1,11 +1,11 @@
local utils = require "lib.utils.utils"
--- @alias State "idle"|"run"|"attack"|"hurt"
--- @alias CharacterState "idle"|"run"|"attack"|"hurt"
--- @class Logic
--- @field id Id
--- @field mapLogic MapLogic
--- @field state State
--- @field state CharacterState
local logic = {}
logic.__index = logic
@ -20,9 +20,18 @@ local function new(id, position, size)
}, logic)
end
--- @param state CharacterState
function logic:setState(state)
self.state = state
Tree.level.characters[self.id].graphics.animation:setState(state, (state ~= "idle" and state ~= "run") and function()
self:setState("idle")
end or nil)
end
--- @param path Deque
function logic:followPath(path)
if path:is_empty() then return end
self:setState("run")
self.mapLogic.path = path;
---@type Vec3
local nextCell = path:peek_front()
@ -33,7 +42,6 @@ end
--- @param target Vec3
function logic:runTo(target)
self.mapLogic.t0 = love.timer.getTime()
self.state = "run"
self.mapLogic.runTarget = target
local charPos = self.mapLogic.position
if target.x < charPos.x then
@ -54,7 +62,7 @@ function logic:update(dt)
self:runTo(self.mapLogic.path:peek_front())
self.mapLogic.path:pop_front()
else -- мы добежали до финальной цели
self.state = "idle"
self:setState("idle")
self.mapLogic.runTarget = nil
end
else -- анимация перемещения не завершена

View File

@ -5,6 +5,12 @@
local spell = {}
spell.__index = spell
function spell:update(caster, dt) end
function spell:draw() end
function spell:cast(caster, target) end
local walk = setmetatable({
--- @type Deque
path = nil

View File

@ -17,12 +17,11 @@ function love.load()
c.logic.mapLogic.position = Vec3 { x, y }
c.logic.mapLogic.displayedPosition = Vec3 { x, y }
c.spellbook = spellbook.of { spellbook.walk }
c.logic:setState("attack")
end
end
end
-- PlayerFaction.characters = { Hero1, Hero2 }
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
end