tile grid implementation

This commit is contained in:
PeaAshMeter 2025-08-30 21:06:03 +03:00
parent bc0537a649
commit 7000f0fb4d
10 changed files with 105 additions and 72 deletions

32
lib/level/grid/base.lua Normal file
View File

@ -0,0 +1,32 @@
local utils = require "lib.utils.utils"
--- @class Grid
--- @field __grid {string: any}
local grid = {}
grid.__index = grid
--- adds a value to the grid
--- @param value any
function grid:add(value)
grid[tostring(value.position)] = value
end
--- @param position Vec3
function grid:get(position)
return self.__grid[tostring(position)]
end
--- clears the grid
function grid:reset()
self.__grid = {}
end
--- Generates an empty grid
--- @return Grid
function grid.new()
return setmetatable({
__grid = {}
}, grid)
end
return grid

View File

@ -1,14 +1,8 @@
local utils = require "lib.utils.utils"
--- @class CharacterGrid
--- @class CharacterGrid : Grid
--- @field __grid {string: Id|nil}
local grid = {}
local grid = setmetatable({}, require "lib.level.grid.base")
grid.__index = grid
local function encode(x, y)
return tostring(x) .. ";" .. tostring(y)
end
--- Adds a character id to the grid
--- @param id Id
function grid:add(id)
@ -21,22 +15,11 @@ function grid:add(id)
for y = centerY, centerY + sizeY - 1 do
for x = centerX, centerX + sizeX - 1 do
self.__grid[encode(x, y)] = character.id
self.__grid[tostring(Vec3 { x, y })] = character.id
end
end
end
--- @param x integer
--- @param y integer
function grid:get(x, y)
return self.__grid[encode(x, y)]
end
--- clears the grid
function grid:reset()
self.__grid = {}
end
--- Generates an empty grid
--- @return CharacterGrid
local function new()

View File

@ -0,0 +1,21 @@
local utils = require "lib.utils.utils"
--- @class TileGrid : Grid
local map = setmetatable({}, require "lib.level.grid.base")
map.__index = map
--- create new map
--- @param type "procedural"|"handmaded"
--- @param template Procedural|Handmaded
--- @param size? Vec3
local function new(type, template, size)
local tMap = require('lib.level.' .. type).new(template, size)
return setmetatable({ __grid = tMap }, map)
end
function map:draw()
utils.each(self.__grid, function(el)
el:draw()
end)
end
return { new = new }

View File

@ -6,7 +6,7 @@ local utils = require "lib.utils.utils"
--- @field characterGrid CharacterGrid
--- @field selector Selector
--- @field camera Camera
--- @field map Map
--- @field tileGrid TileGrid
local level = {}
level.__index = level
@ -20,10 +20,10 @@ local function new(type, template)
return setmetatable({
size = size,
characters = {},
characterGrid = (require "lib.level.grid").new(),
characterGrid = (require "lib.level.grid.character_grid").new(),
tileGrid = (require "lib.level.grid.tile_grid").new(type, template, size),
selector = (require "lib.level.selector").new(),
camera = (require "lib.level.camera").new(),
map = (require "lib.level.map").new(type, template, size)
}, level)
end
@ -54,7 +54,7 @@ function level:update(dt)
end
function level:draw()
self.map:draw()
self.tileGrid:draw()
--- Это отрисовка пути персонажа к мышке
if self.selector.id and path then

View File

@ -1,30 +0,0 @@
--- @class Map
--- @field atlas love.Image
--- @field size Vec3|nil
local map = {}
map.__index = map
--- create new map
--- @param type "procedural"|"handmaded"
--- @param template Procedural|Handmaded
--- @param size? Vec3
local function new(type, template, size)
map.size = size
local tMap = require('lib.level.' .. type).new(template, size)
return setmetatable(tMap, map)
end
function map:draw()
for y = 0, self.size.y - 1 do
for x = 0, self.size.x - 1 do
love.graphics.draw(self.atlas, self[x][y].quad, x, y,
nil, 1 / 32, 1 / 32)
end
end
end
function map:get(x, y)
return self[x][y]
end
return { new = new }

View File

@ -6,12 +6,12 @@ local function new(template, size)
-- паттерн-матчинг для самых маленьких
if template == "flower_plains" then
local tileMap = require("lib.level.tileMap").load(Tree.assets.files.tiles.grass)
map.atlas = tileMap.atlas
for y = 0, size.y - 1 do
map[y] = {}
for x = 0, size.x - 1 do
local type = tileMap.map["flower_grass"]
map[y][x] = type[math.random(1, #type)]
--- @type Tile
local tile = type[math.random(1, #type)]:copyWith({ position = Vec3 { x, y } })
map[tostring(tile.position)] = tile
end
end
end

View File

@ -25,7 +25,7 @@ function selector:update(dt)
if mousePosition.x >= Tree.level.size.x or mousePosition.y >= Tree.level.size.y or mousePosition.y < 0 or mousePosition.x < 0 then
return
end
local characterId = Tree.level.characterGrid:get(mousePosition.x, mousePosition.y)
local characterId = Tree.level.characterGrid:get(Vec3 { mousePosition.x, mousePosition.y })
if not characterId and self.id then -- временная обработка события "побежать к точке"
local char = Tree.level.characters[self.id]

View File

@ -1,23 +1,50 @@
--- @class Tile
--- @class TileAtlasData
--- @field x number
--- @field y number
--- @field tileSize number
--- @field atlas love.Image
--- @field isClip boolean
--- @field quad love.Quad
--- @field quad love.Quad | nil
local tileAtlasData = {}
tileAtlasData.__index = tileAtlasData
function tileAtlasData:getQuad()
if self.quad then return self.quad end
self.quad = love.graphics.newQuad(self.x, self.y, self.tileSize, self.tileSize, self.atlas)
return self.quad
end
-----------------------------------------------------------------
--- @class Tile
--- @field atlasData TileAtlasData
--- @field position Vec3
local tile = {}
tile.__index = tile
--- TODO: сделать как love.graphics.draw несколько сигнатур у функции
--- @param x number
--- @param y number
--- @param tileSize number
--- @param atlas love.Image
--- @param isClip boolean
local function new(x, y, tileSize, atlas, isClip)
local quad = love.graphics.newQuad(x, y, tileSize, tileSize, atlas)
--- @param atlasData TileAtlasData
local function new(atlasData)
return setmetatable({
isClip = isClip,
quad = quad
atlasData = setmetatable(atlasData, tileAtlasData)
}, tile)
end
function tile:draw()
love.graphics.draw(self.atlasData.atlas, self.atlasData:getQuad(), self.position.x,
self.position.y,
nil, 1 / 32, 1 / 32)
end
--- @param values table
--- @return Tile
function tile:copyWith(values)
for k, v in pairs(self) do
values[k] = v
end
return setmetatable(values, tile)
end
--- @param quad love.Quad
--- @param isClip boolean
local function fromQuad(quad, isClip)

View File

@ -29,14 +29,14 @@ local function load(path)
end
end
end
-- Как пропатчить KDE2 под любое устройство, используя любые технологии, например, через модульные тесты или инструменты автоматизации?
local cnt = 0
for y = 0, atlas:getHeight() - 1, tiles.tileSize do
for x = 0, atlas:getWidth() - 1, tiles.tileSize do
if layout[cnt] then
for _, group in ipairs(layout[cnt]) do
print(x, y, tiles.tileSize, atlas, false)
local tile = require('lib.level.tile').new(x, y, tiles.tileSize, atlas, false)
local tile = require('lib.level.tile').new { x = x, y = y, tileSize = tiles.tileSize, atlas = atlas, isClip = false }
if tiles.map[group] then
table.insert(tiles.map[group], tile)
else

View File

@ -28,7 +28,7 @@ end
--- @param table {[any] : T}
--- @param fn fun(el: T): nil
function P.each(table, fn)
for _, value in ipairs(table) do
for _, value in pairs(table) do
fn(value)
end
end