81 lines
3.3 KiB
Lua
81 lines
3.3 KiB
Lua
local utils = require "lib.utils.utils"
|
||
|
||
--- Отвечает за размещение и перемещение по локации
|
||
--- @class MapBehavior : Behavior
|
||
--- @field position Vec3
|
||
--- @field runTarget Vec3 точка, в которую в данный момент бежит персонаж
|
||
--- @field displayedPosition Vec3 точка, в которой персонаж отображается
|
||
--- @field t0 number время начала движения для анимациии
|
||
--- @field path Deque путь, по которому сейчас бежит персонаж
|
||
--- @field animationNode? AnimationNode AnimationNode, с которым связана анимация перемещения
|
||
--- @field size Vec3
|
||
local mapBehavior = {}
|
||
mapBehavior.__index = mapBehavior
|
||
mapBehavior.id = "map"
|
||
|
||
|
||
--- @param position? Vec3
|
||
--- @param size? Vec3
|
||
function mapBehavior.new(position, size)
|
||
return setmetatable({
|
||
position = position or Vec3({}),
|
||
displayedPosition = position or Vec3({}),
|
||
size = size or Vec3({ 1, 1 }),
|
||
}, mapBehavior)
|
||
end
|
||
|
||
--- @param path Deque
|
||
--- @param animationNode AnimationNode
|
||
function mapBehavior:followPath(path, animationNode)
|
||
if path:is_empty() then return animationNode:finish() end
|
||
self.animationNode = animationNode
|
||
self.position = self.displayedPosition
|
||
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()
|
||
end
|
||
|
||
--- @param target Vec3
|
||
function mapBehavior:runTo(target)
|
||
self.t0 = love.timer.getTime()
|
||
self.runTarget = target
|
||
self.owner:try(Tree.behaviors.sprite,
|
||
function(sprite)
|
||
if target.x < self.position.x then
|
||
sprite.side = Tree.behaviors.sprite.LEFT
|
||
elseif target.x > self.position.x then
|
||
sprite.side = Tree.behaviors.sprite.RIGHT
|
||
end
|
||
end
|
||
)
|
||
end
|
||
|
||
function mapBehavior:update(dt)
|
||
if self.runTarget then
|
||
local delta = love.timer.getTime() - self.t0 or love.timer.getTime()
|
||
local fraction = delta /
|
||
(0.5 * self.runTarget:subtract(self.position):length()) -- бежим одну клетку за 500 мс, по диагонали больше
|
||
if fraction >= 1 then -- анимация перемещена завершена
|
||
self.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.animationNode then self.animationNode:finish() end
|
||
end
|
||
else -- анимация перемещения не завершена
|
||
self.displayedPosition = utils.lerp(self.position, self.runTarget, fraction) -- линейный интерполятор
|
||
end
|
||
end
|
||
end
|
||
|
||
return mapBehavior
|