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 : Grid
--- @class CharacterGrid
--- @field __grid {string: Id|nil} --- @field __grid {string: Id|nil}
local grid = {} local grid = setmetatable({}, require "lib.level.grid.base")
grid.__index = grid grid.__index = grid
local function encode(x, y)
return tostring(x) .. ";" .. tostring(y)
end
--- Adds a character id to the grid --- Adds a character id to the grid
--- @param id Id --- @param id Id
function grid:add(id) function grid:add(id)
@ -21,22 +15,11 @@ function grid:add(id)
for y = centerY, centerY + sizeY - 1 do for y = centerY, centerY + sizeY - 1 do
for x = centerX, centerX + sizeX - 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 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 --- Generates an empty grid
--- @return CharacterGrid --- @return CharacterGrid
local function new() 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 characterGrid CharacterGrid
--- @field selector Selector --- @field selector Selector
--- @field camera Camera --- @field camera Camera
--- @field map Map --- @field tileGrid TileGrid
local level = {} local level = {}
level.__index = level level.__index = level
@ -20,10 +20,10 @@ local function new(type, template)
return setmetatable({ return setmetatable({
size = size, size = size,
characters = {}, 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(), selector = (require "lib.level.selector").new(),
camera = (require "lib.level.camera").new(), camera = (require "lib.level.camera").new(),
map = (require "lib.level.map").new(type, template, size)
}, level) }, level)
end end
@ -54,7 +54,7 @@ function level:update(dt)
end end
function level:draw() function level:draw()
self.map:draw() self.tileGrid:draw()
--- Это отрисовка пути персонажа к мышке --- Это отрисовка пути персонажа к мышке
if self.selector.id and path then 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 if template == "flower_plains" then
local tileMap = require("lib.level.tileMap").load(Tree.assets.files.tiles.grass) local tileMap = require("lib.level.tileMap").load(Tree.assets.files.tiles.grass)
map.atlas = tileMap.atlas
for y = 0, size.y - 1 do for y = 0, size.y - 1 do
map[y] = {}
for x = 0, size.x - 1 do for x = 0, size.x - 1 do
local type = tileMap.map["flower_grass"] 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 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 if mousePosition.x >= Tree.level.size.x or mousePosition.y >= Tree.level.size.y or mousePosition.y < 0 or mousePosition.x < 0 then
return return
end 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 -- временная обработка события "побежать к точке" if not characterId and self.id then -- временная обработка события "побежать к точке"
local char = Tree.level.characters[self.id] 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 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 = {} local tile = {}
tile.__index = tile tile.__index = tile
--- TODO: сделать как love.graphics.draw несколько сигнатур у функции --- TODO: сделать как love.graphics.draw несколько сигнатур у функции
--- @param x number --- @param atlasData TileAtlasData
--- @param y number local function new(atlasData)
--- @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)
return setmetatable({ return setmetatable({
isClip = isClip, atlasData = setmetatable(atlasData, tileAtlasData)
quad = quad
}, tile) }, tile)
end 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 quad love.Quad
--- @param isClip boolean --- @param isClip boolean
local function fromQuad(quad, isClip) local function fromQuad(quad, isClip)

View File

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

View File

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