Compare commits
No commits in common. "37eb71251801f00114122005f402ded134a1d84f" and "7ceebbb411cbae654b67dadf5542bfe5b69bf9d3" have entirely different histories.
37eb712518
...
7ceebbb411
@ -37,9 +37,9 @@ local function spawn(name, template, spriteDir, position, size, level)
|
|||||||
return char
|
return char
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param path Deque
|
--- @param target Vec3
|
||||||
function character:followPath(path)
|
function character:runTo(target)
|
||||||
self.logic:followPath(path)
|
self.logic:runTo(target)
|
||||||
end
|
end
|
||||||
|
|
||||||
function character:update(dt)
|
function character:update(dt)
|
||||||
|
|||||||
@ -20,7 +20,7 @@ end
|
|||||||
|
|
||||||
function graphics:draw()
|
function graphics:draw()
|
||||||
local ppm = Tree.level.camera.pixelsPerMeter
|
local ppm = Tree.level.camera.pixelsPerMeter
|
||||||
local position = Tree.level.characters[self.id].logic.mapLogic.displayedPosition
|
local position = Tree.level.characters[self.id].logic.mapLogic.position
|
||||||
local state = Tree.level.characters[self.id].logic.state
|
local state = Tree.level.characters[self.id].logic.state
|
||||||
|
|
||||||
if Tree.level.selector.id == self.id then love.graphics.setColor(0.5, 1, 0.5) end
|
if Tree.level.selector.id == self.id then love.graphics.setColor(0.5, 1, 0.5) end
|
||||||
|
|||||||
@ -13,42 +13,30 @@ logic.__index = logic
|
|||||||
local function new(id, position, size)
|
local function new(id, position, size)
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
id = id,
|
id = id,
|
||||||
mapLogic = (require 'lib.character.map_logic').new(id, position, size),
|
mapLogic = (require 'lib.character.map_logic').new(id, position, size)
|
||||||
state = "idle"
|
|
||||||
}, logic)
|
}, logic)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param path Deque
|
--- @param path Vec3
|
||||||
function logic:followPath(path)
|
function logic:followPath(path)
|
||||||
if path:is_empty() then return end
|
|
||||||
self.mapLogic.path = path;
|
|
||||||
self:runTo(path:peek_front())
|
|
||||||
path:pop_front()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param target Vec3
|
--- @param target Vec3
|
||||||
function logic:runTo(target)
|
function logic:runTo(target)
|
||||||
self.mapLogic.t0 = love.timer.getTime()
|
|
||||||
self.state = "run"
|
self.state = "run"
|
||||||
self.mapLogic.runTarget = target
|
self.mapLogic.runTarget = target
|
||||||
end
|
end
|
||||||
|
|
||||||
function logic:update(dt)
|
function logic:update(dt)
|
||||||
if self.state == "run" and self.mapLogic.runTarget then
|
if self.state == "run" and self.mapLogic.runTarget then
|
||||||
local vel = self.mapLogic.runTarget:subtract(self.mapLogic.position) --[[@as Vec3]]
|
if self.mapLogic.position:floor() == self.mapLogic.runTarget:floor() then -- мы добежали до цели и сейчас в целевой клетке
|
||||||
local delta = love.timer.getTime() - self.mapLogic.t0 or love.timer.getTime()
|
self.state = "idle"
|
||||||
local fraction = delta / 0.5
|
self.mapLogic.runTarget = nil
|
||||||
if fraction >= 1 then -- мы добежали до цели и сейчас в целевой клетке (возможно, промежуточной)
|
else -- мы не добежали до цели
|
||||||
self.mapLogic.position = self.mapLogic.runTarget
|
local vel = (self.mapLogic.runTarget:subtract(self.mapLogic.position):normalize() --[[@as Vec3]]
|
||||||
if not self.mapLogic.path:is_empty() then -- еще есть, куда бежать
|
):scale(1 * dt) -- бежим 2 условных метра в секунду
|
||||||
self:runTo(self.mapLogic.path:peek_front())
|
self.mapLogic.position = self.mapLogic.position:add(vel)
|
||||||
self.mapLogic.path:pop_front()
|
|
||||||
else -- мы добежали до финальной цели
|
|
||||||
self.state = "idle"
|
|
||||||
self.mapLogic.runTarget = nil
|
|
||||||
end
|
|
||||||
else -- мы не добежали до цели
|
|
||||||
self.mapLogic.displayedPosition = self.mapLogic.position:add(vel:scale(fraction))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
--- @class MapLogic
|
--- @class MapLogic
|
||||||
--- @field id Id
|
--- @field id Id
|
||||||
--- @field position Vec3
|
--- @field position Vec3
|
||||||
|
--- @field latestPosition Vec3 позиция, где character был один тик назад
|
||||||
--- @field runTarget Vec3 точка, в которую в данный момент бежит персонаж
|
--- @field runTarget Vec3 точка, в которую в данный момент бежит персонаж
|
||||||
--- @field displayedPosition Vec3 точка, в которой персонаж отображается
|
|
||||||
--- @field t0 number время начала движения для анимациии
|
|
||||||
--- @field path Deque путь, по которому сейчас бежит персонаж
|
|
||||||
--- @field size Vec3
|
--- @field size Vec3
|
||||||
local mapLogic = {}
|
local mapLogic = {}
|
||||||
|
|
||||||
@ -15,9 +13,7 @@ local function new(id, position, size)
|
|||||||
return setmetatable({
|
return setmetatable({
|
||||||
id = id,
|
id = id,
|
||||||
position = position or Vec3({}),
|
position = position or Vec3({}),
|
||||||
displayedPosition = position or Vec3({}),
|
size = size or Vec3({ 1, 1 })
|
||||||
size = size or Vec3({ 1, 1 }),
|
|
||||||
path = (require "lib.utils.deque").new()
|
|
||||||
}, mapLogic)
|
}, mapLogic)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
local deque = require "lib.utils.deque"
|
|
||||||
|
|
||||||
--- @param cur Vec3
|
--- @param cur Vec3
|
||||||
--- @param to Vec3
|
--- @param to Vec3
|
||||||
--- @param acc Deque
|
--- @param acc Vec3[]
|
||||||
local function greedy_trace_step(cur, to, acc)
|
local function greedy_trace_step(cur, to, acc)
|
||||||
local lengthTable = {}
|
local lengthTable = {}
|
||||||
for x = -1, 1 do
|
for x = -1, 1 do
|
||||||
@ -17,7 +15,7 @@ local function greedy_trace_step(cur, to, acc)
|
|||||||
end
|
end
|
||||||
local next = min[1]
|
local next = min[1]
|
||||||
|
|
||||||
acc = acc:push_back(cur)
|
table.insert(acc, cur)
|
||||||
if cur == to then
|
if cur == to then
|
||||||
return acc
|
return acc
|
||||||
end
|
end
|
||||||
@ -26,9 +24,8 @@ end
|
|||||||
|
|
||||||
--- @param from Vec3
|
--- @param from Vec3
|
||||||
--- @param to Vec3
|
--- @param to Vec3
|
||||||
--- @return Deque
|
|
||||||
local function trace(from, to)
|
local function trace(from, to)
|
||||||
return greedy_trace_step(from, to, deque.new())
|
return greedy_trace_step(from, to, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
return trace
|
return trace
|
||||||
|
|||||||
@ -27,17 +27,7 @@ function selector:update(dt)
|
|||||||
end
|
end
|
||||||
local characterId = Tree.level.characterGrid:get(mousePosition.x, mousePosition.y)
|
local characterId = Tree.level.characterGrid:get(mousePosition.x, mousePosition.y)
|
||||||
|
|
||||||
if not characterId and self.id then -- временная обработка события "побежать к точке"
|
|
||||||
local char = Tree.level.characters[self.id]
|
|
||||||
local charPos = char.logic.mapLogic.position
|
|
||||||
local path = (require "lib.pathfinder")(charPos, mousePosition)
|
|
||||||
path:pop_front()
|
|
||||||
print("Following path: ")
|
|
||||||
for p in path:values() do print(p) end
|
|
||||||
char:followPath(path)
|
|
||||||
end
|
|
||||||
self:select(characterId)
|
self:select(characterId)
|
||||||
|
|
||||||
print("[Selector]:", mousePosition, characterId and "selected " .. characterId or "deselected")
|
print("[Selector]:", mousePosition, characterId and "selected " .. characterId or "deselected")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,121 +0,0 @@
|
|||||||
---@class Deque
|
|
||||||
---@field private first integer
|
|
||||||
---@field private last integer
|
|
||||||
---@field private _data table<integer, any>
|
|
||||||
local Deque = {}
|
|
||||||
Deque.__index = Deque
|
|
||||||
|
|
||||||
---Создать пустую очередь
|
|
||||||
---@return Deque
|
|
||||||
local function new()
|
|
||||||
---@type Deque
|
|
||||||
local self = setmetatable({
|
|
||||||
first = 1,
|
|
||||||
last = 0,
|
|
||||||
_data = {},
|
|
||||||
}, Deque)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---Количество элементов
|
|
||||||
---@return integer
|
|
||||||
function Deque:size()
|
|
||||||
return self.last - self.first + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
---Пуста ли очередь
|
|
||||||
---@return boolean
|
|
||||||
function Deque:is_empty()
|
|
||||||
return self.first > self.last
|
|
||||||
end
|
|
||||||
|
|
||||||
---Добавить в начало
|
|
||||||
---@param value any
|
|
||||||
---@return Deque self
|
|
||||||
function Deque:push_front(value)
|
|
||||||
self.first = self.first - 1
|
|
||||||
self._data[self.first] = value
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---Добавить в конец
|
|
||||||
---@param value any
|
|
||||||
---@return Deque self
|
|
||||||
function Deque:push_back(value)
|
|
||||||
self.last = self.last + 1
|
|
||||||
self._data[self.last] = value
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---Забрать из начала
|
|
||||||
---@return any
|
|
||||||
function Deque:pop_front()
|
|
||||||
if self.first > self.last then return nil end
|
|
||||||
local value = self._data[self.first]
|
|
||||||
self._data[self.first] = nil
|
|
||||||
self.first = self.first + 1
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
|
|
||||||
---Забрать из конца
|
|
||||||
---@return any
|
|
||||||
function Deque:pop_back()
|
|
||||||
if self.first > self.last then return nil end
|
|
||||||
local value = self._data[self.last]
|
|
||||||
self._data[self.last] = nil
|
|
||||||
self.last = self.last - 1
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
|
|
||||||
---Подсмотреть начало
|
|
||||||
---@return any
|
|
||||||
function Deque:peek_front()
|
|
||||||
if self.first > self.last then return nil end
|
|
||||||
return self._data[self.first]
|
|
||||||
end
|
|
||||||
|
|
||||||
---Подсмотреть конец
|
|
||||||
---@generic T
|
|
||||||
---@return T|nil
|
|
||||||
function Deque:peek_back()
|
|
||||||
if self.first > self.last then return nil end
|
|
||||||
return self._data[self.last]
|
|
||||||
end
|
|
||||||
|
|
||||||
---Очистить очередь
|
|
||||||
function Deque:clear()
|
|
||||||
-- Полная очистка таблицы для GC
|
|
||||||
for i = self.first, self.last do
|
|
||||||
self._data[i] = nil
|
|
||||||
end
|
|
||||||
self.first, self.last = 1, 0
|
|
||||||
end
|
|
||||||
|
|
||||||
---Итератор по значениям слева направо
|
|
||||||
---@return fun():any
|
|
||||||
function Deque:values()
|
|
||||||
local i = self.first
|
|
||||||
return function()
|
|
||||||
if i <= self.last then
|
|
||||||
local v = self._data[i]
|
|
||||||
i = i + 1
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---Преобразовать в массив
|
|
||||||
---@return any[]
|
|
||||||
function Deque:to_array()
|
|
||||||
local n = self:size()
|
|
||||||
local arr = {}
|
|
||||||
if n <= 0 then return arr end
|
|
||||||
local j = 1
|
|
||||||
for i = self.first, self.last do
|
|
||||||
arr[j] = self._data[i]
|
|
||||||
j = j + 1
|
|
||||||
end
|
|
||||||
return arr
|
|
||||||
end
|
|
||||||
|
|
||||||
return { new = new }
|
|
||||||
7
main.lua
7
main.lua
@ -12,7 +12,8 @@ end
|
|||||||
local width = 30
|
local width = 30
|
||||||
local height = 30
|
local height = 30
|
||||||
function love.load()
|
function love.load()
|
||||||
character.spawn("Hero", "warrior", Tree.assets.files.sprites.character)
|
local char = character.spawn("Hero", "warrior", Tree.assets.files.sprites.character)
|
||||||
|
char:runTo(Vec3 { 5, 5 })
|
||||||
|
|
||||||
Grass = Tree.assets.files.tiles.grass.atlas
|
Grass = Tree.assets.files.tiles.grass.atlas
|
||||||
Gr1 = love.graphics.newQuad(0, 32, 32, 32, Grass)
|
Gr1 = love.graphics.newQuad(0, 32, 32, 32, Grass)
|
||||||
@ -75,8 +76,8 @@ function love.draw()
|
|||||||
local path = (require "lib.pathfinder")(charPos, mpos)
|
local path = (require "lib.pathfinder")(charPos, mpos)
|
||||||
|
|
||||||
love.graphics.setColor(1, 0, 0)
|
love.graphics.setColor(1, 0, 0)
|
||||||
for p in path:values() do
|
for _, p in ipairs(path) do
|
||||||
love.graphics.rectangle("fill", p.x + 0.45, p.y + 0.45, 0.1, 0.1)
|
love.graphics.rectangle("fill", p.x + 0.5, p.y + 0.5, 0.1, 0.1)
|
||||||
end
|
end
|
||||||
love.graphics.setColor(1, 1, 1)
|
love.graphics.setColor(1, 1, 1)
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user