89 lines
3.2 KiB
Lua
89 lines
3.2 KiB
Lua
local utils = require "lib.utils.utils"
|
|
|
|
--- Отвечает за перемещение по тайлам
|
|
--- @class TiledBehavior : Behavior
|
|
--- @field private runSource? Vec3 точка, из которой бежит персонаж
|
|
--- @field private runTarget? Vec3 точка, в которую в данный момент бежит персонаж
|
|
--- @field private path? Deque путь, по которому сейчас бежит персонаж
|
|
--- @field private followPathCallback? fun()
|
|
--- @field private t0 number время начала движения
|
|
--- @field size Vec3
|
|
local behavior = {}
|
|
behavior.__index = behavior
|
|
behavior.id = "tiled"
|
|
|
|
--- @param size? Vec3
|
|
function behavior.new(size)
|
|
return setmetatable({
|
|
size = size or Vec3({ 1, 1 }),
|
|
}, behavior)
|
|
end
|
|
|
|
--- @param path Deque
|
|
--- @return Task<nil>
|
|
function behavior:followPath(path)
|
|
self.owner:try(Tree.behaviors.sprite, function(sprite)
|
|
sprite:loop("run")
|
|
end)
|
|
self.path = path;
|
|
---@type Vec3
|
|
local nextCell = path:peek_front()
|
|
self:runTo(nextCell)
|
|
path:pop_front()
|
|
|
|
return function(callback)
|
|
self.followPathCallback = callback
|
|
end
|
|
end
|
|
|
|
--- @param target Vec3
|
|
function behavior:runTo(target)
|
|
local positioned = self.owner:has(Tree.behaviors.positioned)
|
|
if not positioned then return end
|
|
|
|
self.t0 = love.timer.getTime()
|
|
self.runTarget = target
|
|
|
|
self.runSource = positioned.position
|
|
|
|
self.owner:try(Tree.behaviors.sprite,
|
|
function(sprite)
|
|
if target.x < positioned.position.x then
|
|
sprite.side = Tree.behaviors.sprite.LEFT
|
|
elseif target.x > positioned.position.x then
|
|
sprite.side = Tree.behaviors.sprite.RIGHT
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
function behavior:update(dt)
|
|
if self.runTarget then
|
|
local positioned = self.owner:has(Tree.behaviors.positioned)
|
|
if not positioned then return end
|
|
|
|
local delta = love.timer.getTime() - self.t0 or love.timer.getTime()
|
|
local fraction = delta /
|
|
(0.5 * self.runTarget:subtract(self.runSource):length()) -- бежим одну клетку за 500 мс, по диагонали больше
|
|
if fraction >= 1 then -- анимация перемещена завершена
|
|
positioned.position = self.runTarget
|
|
if not self.path:is_empty() then -- еще есть, куда бежать
|
|
self:runTo(self.path:pop_front())
|
|
else -- мы добежали до финальной цели
|
|
self.owner:try(Tree.behaviors.sprite, function(sprite)
|
|
sprite:loop("idle")
|
|
end)
|
|
self.runTarget = nil
|
|
|
|
if self.followPathCallback then
|
|
self.followPathCallback()
|
|
end
|
|
end
|
|
else -- анимация перемещения не завершена
|
|
positioned.position = utils.lerp(self.runSource, self.runTarget, fraction) -- линейный интерполятор
|
|
end
|
|
end
|
|
end
|
|
|
|
return behavior
|