implemented character movement & initial selector
Co-authored-by: Ivan Yuriev <ivanyr44@gmail.com>
This commit is contained in:
parent
e08fb7255f
commit
d07d26680c
@ -6,6 +6,7 @@ local ANIMATION_SPEED = 0.1
|
||||
|
||||
local characterId = 1
|
||||
|
||||
--- @todo Композиция лучше наследования, но не до такой же степени! Надо отрефакторить и избавиться от сотни полей в таблице
|
||||
--- @class Character
|
||||
--- @field id integer
|
||||
--- @field name string
|
||||
@ -16,6 +17,8 @@ local characterId = 1
|
||||
--- @field skills table
|
||||
--- @field class "warrior"|"mage"
|
||||
--- @field position Vec3
|
||||
--- @field latestPosition Vec3 позиция, где character был один тик назад
|
||||
--- @field runTarget Vec3 точка, в которую в данный момент бежит персонаж
|
||||
--- @field size Vec3
|
||||
local character = {}
|
||||
character.__index = character
|
||||
@ -66,10 +69,34 @@ local function spawn(name, spriteDir, level)
|
||||
|
||||
char = setmetatable(char, character)
|
||||
Tree.level.characters[char.id] = char
|
||||
Tree.level.positionGrid:add(char)
|
||||
return char
|
||||
end
|
||||
|
||||
--- @param target Vec3
|
||||
function character:runTo(target)
|
||||
self.state = "run"
|
||||
self.runTarget = target
|
||||
end
|
||||
|
||||
function character:update(dt)
|
||||
if self.state == "run" and self.runTarget then
|
||||
if self.position:floor() == self.runTarget:floor() then -- мы добежали до цели и сейчас в целевой клетке
|
||||
self.state = "idle"
|
||||
self.runTarget = nil
|
||||
else -- мы не добежали до цели
|
||||
local vel = (self.runTarget:subtract(self.position):normalize() --[[@as Vec3]]
|
||||
):scale(2 * dt) -- бежим 2 условных метра в секунду
|
||||
self.position = self.position:add(vel)
|
||||
end
|
||||
end
|
||||
|
||||
if self.position ~= self.latestPosition then
|
||||
-- типа уведомление о том, что положение (на уровне клеток) изменилось
|
||||
Tree.level.positionGrid:remove(self)
|
||||
Tree.level.positionGrid:add(self)
|
||||
end
|
||||
|
||||
if love.keyboard.isDown("r") then
|
||||
self.state = "run"
|
||||
end
|
||||
|
||||
@ -14,6 +14,7 @@ local keymap = {
|
||||
cameraMoveRight = control("key", "d"),
|
||||
cameraMoveDown = control("key", "s"),
|
||||
cameraMoveScroll = control("mouse", "3"),
|
||||
select = control("mouse", "1")
|
||||
}
|
||||
|
||||
function keymap:isDown(key)
|
||||
|
||||
10
lib/grid.lua
10
lib/grid.lua
@ -7,12 +7,12 @@ grid.__index = grid
|
||||
--- Adds a character id to the grid
|
||||
--- @param character Character
|
||||
function grid:add(character)
|
||||
local centerX, centerY = character.position.x, character.position.y
|
||||
local centerX, centerY = math.floor(character.position.x), math.floor(character.position.y)
|
||||
local sizeX, sizeY = character.size.x, character.size.y
|
||||
|
||||
for y = centerY, centerY + sizeY - 1 do
|
||||
for x = centerX, centerX + sizeX - 1 do
|
||||
grid[x][y] = character.id
|
||||
self[x][y] = character.id
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -20,12 +20,12 @@ end
|
||||
--- Removes a character id from the grid
|
||||
--- @param character Character
|
||||
function grid:remove(character)
|
||||
local centerX, centerY = character.position.x, character.position.y
|
||||
local centerX, centerY = math.floor(character.position.x), math.floor(character.position.y)
|
||||
local sizeX, sizeY = character.size.x, character.size.y
|
||||
|
||||
for y = centerY, centerY + sizeY - 1 do
|
||||
for x = centerX, centerX + sizeX - 1 do
|
||||
grid[x][y] = nil
|
||||
self[x][y] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -37,7 +37,7 @@ end
|
||||
local function generateGrid(width, height)
|
||||
local g = utils.generateList(width, function(_)
|
||||
return utils.generateList(height, function(_)
|
||||
return nil
|
||||
return {}
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ local utils = require "lib/utils"
|
||||
--- @class Level
|
||||
--- @field characters Character[]
|
||||
--- @field positionGrid Grid
|
||||
--- @field selected table
|
||||
--- @field selector Selector
|
||||
--- @field camera Camera
|
||||
local level = {}
|
||||
level.__index = level
|
||||
@ -12,6 +12,7 @@ local function new()
|
||||
return setmetatable({
|
||||
characters = {},
|
||||
positionGrid = (require "lib/grid").new(30, 30), -- magic numbers for testing purposes only
|
||||
selector = (require "lib/selector").new(),
|
||||
camera = (require "lib/camera").new()
|
||||
}, level)
|
||||
end
|
||||
|
||||
35
lib/selector.lua
Normal file
35
lib/selector.lua
Normal file
@ -0,0 +1,35 @@
|
||||
--- @class Selector
|
||||
--- @field id integer
|
||||
local selector = {}
|
||||
|
||||
local function new()
|
||||
return setmetatable({}, selector)
|
||||
end
|
||||
|
||||
--- @param characterId integer
|
||||
function selector:select(characterId)
|
||||
self.id = characterId
|
||||
end
|
||||
|
||||
function selector:deselect()
|
||||
self.id = nil
|
||||
end
|
||||
|
||||
--- TODO: сделать обработчик селектора
|
||||
--- @param camera Camera
|
||||
function selector:update(camera, dt)
|
||||
if self.id then
|
||||
return
|
||||
end
|
||||
local mousePosition = camera:toWorldPosition(Vec3 { love.mouse.getX(), love.mouse.getY() }):floor()
|
||||
local characterPosition = Tree.level.positionGrid[mousePosition.x][mousePosition.y]
|
||||
if Tree.controls:isDown("select") then
|
||||
if characterPosition then
|
||||
self:select(characterPosition)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
new = new
|
||||
}
|
||||
42
lib/vec3.lua
42
lib/vec3.lua
@ -1,4 +1,4 @@
|
||||
--- @class (exact) Vec3
|
||||
--- @class Vec3
|
||||
--- @field x number
|
||||
--- @field y number
|
||||
--- @field z number
|
||||
@ -12,6 +12,8 @@ local function __tostring(self)
|
||||
return "Vec3{" .. self.x .. ", " .. self.y .. ", " .. self.z .. "}"
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param other Vec3
|
||||
--- @return Vec3
|
||||
function __Vec3:add(other)
|
||||
@ -51,31 +53,43 @@ function __Vec3:angle_to(other)
|
||||
return (other - self):direction()
|
||||
end
|
||||
|
||||
function __Vec3:floor()
|
||||
return Vec3 { math.floor(self.x), math.floor(self.y), math.floor(self.z) }
|
||||
end
|
||||
|
||||
function __Vec3:invert()
|
||||
return self:scale(-1)
|
||||
end
|
||||
|
||||
--- @param other Vec3
|
||||
function __Vec3:subtract(other)
|
||||
return self:add(other:invert())
|
||||
end
|
||||
|
||||
--- @param other Vec3
|
||||
function __Vec3:equalsTo(other)
|
||||
return
|
||||
self.x == other.x
|
||||
and self.y == other.y
|
||||
and self.z == other.z
|
||||
end
|
||||
|
||||
---Vec3 constructor
|
||||
---@param vec number[]
|
||||
---@return Vec3
|
||||
function Vec3(vec)
|
||||
return setmetatable({
|
||||
x = vec[1] or 0,
|
||||
y = vec[2] or 0,
|
||||
z = vec[3] or 0,
|
||||
|
||||
}, {
|
||||
__index = __Vec3,
|
||||
__tostring = __tostring,
|
||||
__add = __Vec3.add,
|
||||
__mul = __Vec3.scale,
|
||||
__unm = function(self)
|
||||
return __Vec3.scale(self, -1)
|
||||
end,
|
||||
__sub = function(self, other)
|
||||
return self + -other
|
||||
end,
|
||||
__eq = function(self, other)
|
||||
return
|
||||
self.x == other.x
|
||||
and self.y == other.y
|
||||
and self.z == other.z
|
||||
end,
|
||||
__unm = __Vec3.invert,
|
||||
__sub = __Vec3.subtract,
|
||||
__eq = __Vec3.equalsTo
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
5
main.lua
5
main.lua
@ -8,9 +8,8 @@ function love.conf(t)
|
||||
end
|
||||
|
||||
function love.load()
|
||||
character.spawn("Hero", Tree.assets.files.sprites.character)
|
||||
local hero2 = character.spawn("Hero2", Tree.assets.files.sprites.character)
|
||||
hero2.position = Vec3 { 1, 1 }; -- вообще-то мы вообще не хотим как-то взаимодействовать с персонажем за пределами update, но это удобно для тестов
|
||||
local char = character.spawn("Hero", Tree.assets.files.sprites.character)
|
||||
char:runTo(Vec3 { 5, 5 })
|
||||
|
||||
-- PlayerFaction.characters = { Hero1, Hero2 }
|
||||
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user