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 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