summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcursed22bc <admin@pixeldawn.org>2026-03-01 12:58:57 +0200
committercursed22bc <admin@pixeldawn.org>2026-03-01 12:58:57 +0200
commit937de6cf0402535def99bdd8056ac706afee2c82 (patch)
tree9e7694bdd3a90cc1c9862abd609f9dad612704e5
parentde94226e1b302cee2a006f78f0153aa5fa081f47 (diff)
flexible multisized tiles in tilemap loading
-rw-r--r--entity.lua2
-rw-r--r--main.lua33
-rw-r--r--tilemap.lua72
-rw-r--r--world.lua36
4 files changed, 94 insertions, 49 deletions
diff --git a/entity.lua b/entity.lua
index 3619993..d291717 100644
--- a/entity.lua
+++ b/entity.lua
@@ -34,7 +34,7 @@ end
function Entity:syncFromPhysicsBody()
if not self.body then return end
- self.x = self.body:getX() - self.physicsWidth / 2
+ self.x = self.body:getX() - self.physicsWidth
self.y = self.body:getY() - self.height + self.physicsHeight / 2
end
diff --git a/main.lua b/main.lua
index 5a4e2f0..9a18611 100644
--- a/main.lua
+++ b/main.lua
@@ -12,6 +12,7 @@ local offsetX, offsetY = 0, 0
local dpiScale = 1
local canvas = nil
local smoothCameraShader = nil
+local shaderEnabled = true
local cameraModule = require("camera")
local camera = nil
@@ -19,7 +20,10 @@ local fonts = require("fonts")
local currentState = "game"
local currentMapPath = "assets/maps/tilemap.lua"
-local currentTilesetPath = "assets/maps/tileset.png"
+local currentTilesets = {
+ tileset = { path = "assets/maps/tileset.png", tilewidth = 16, tileheight = 16 },
+ ground = { path = "assets/maps/ground.png", tilewidth = 8, tileheight = 8 },
+}
local world = nil
local states = {
@@ -39,7 +43,7 @@ end
function states.game.load()
local World = require("world")
world = World:new()
- world:load(currentMapPath, currentTilesetPath)
+ world:load(currentMapPath, currentTilesets)
local target = world:getPlayer() or { x = 0, y = 0, width = 16, height = 16 }
camera = cameraModule:new(target, VIRTUAL_WIDTH/2, VIRTUAL_HEIGHT/2, true, WORLD_TO_CANVAS)
world:setCamera(camera)
@@ -116,6 +120,9 @@ function love.keypressed(key, scancode, isrepeat)
if key == "f11" then
love.window.setFullscreen(not love.window.getFullscreen(), "desktop")
end
+ if key == "f1" and DEBUG then
+ shaderEnabled = not shaderEnabled
+ end
if (key == "space" or key == "up" or key == "w") and not isrepeat then
local player = world and world:getPlayer()
if player then player:jump() end
@@ -143,16 +150,34 @@ function love.draw()
local uvOffsetX = subDx * WORLD_TO_CANVAS / CANVAS_WIDTH
local uvOffsetY = subDy * WORLD_TO_CANVAS / CANVAS_HEIGHT
- if smoothCameraShader and (subDx ~= 0 or subDy ~= 0) then
+ if shaderEnabled and smoothCameraShader and (subDx ~= 0 or subDy ~= 0) then
smoothCameraShader:send("offset", { uvOffsetX, uvOffsetY })
love.graphics.setShader(smoothCameraShader)
end
love.graphics.draw(canvas, math.floor(drawX), math.floor(drawY), 0, finalScale, finalScale)
- if smoothCameraShader then
+ if shaderEnabled and smoothCameraShader then
love.graphics.setShader()
end
+
+ if DEBUG then
+ local fps = love.timer.getFPS()
+ local shaderLoaded = smoothCameraShader ~= nil
+ local shaderApplied = shaderEnabled and shaderLoaded and (subDx ~= 0 or subDy ~= 0)
+ local shaderName = shaderLoaded and "smooth_camera.glsl" or "none (fallback)"
+ local shaderState = not shaderLoaded and "unavailable"
+ or not shaderEnabled and "disabled [F1]"
+ or shaderApplied and "active"
+ or "idle"
+ local shaderLine = "shader: " .. shaderName .. " (" .. shaderState .. ")"
+ love.graphics.setColor(0, 0, 0, 0.5)
+ love.graphics.rectangle("fill", 4, 4, 280, 36)
+ love.graphics.setColor(1, 1, 0, 1)
+ love.graphics.print("FPS: " .. fps, 8, 8)
+ love.graphics.print(shaderLine, 8, 22)
+ love.graphics.setColor(1, 1, 1, 1)
+ end
end
return nil
diff --git a/tilemap.lua b/tilemap.lua
index 4780cfe..ab2a52c 100644
--- a/tilemap.lua
+++ b/tilemap.lua
@@ -39,7 +39,7 @@ local function objectToEntity(obj)
return entity
end
-function Tilemap:new(mapPath, tilesetPath)
+function Tilemap:new(mapPath, tilesets)
local self = setmetatable({}, Tilemap)
self.entitiesTiles = {}
@@ -48,34 +48,40 @@ function Tilemap:new(mapPath, tilesetPath)
self.layerBackground = nil
self.layerGround = nil
self.layerForeground = nil
- self.tileWidth = 16
- self.tileHeight = 16
+ self.tileWidth = 8
+ self.tileHeight = 8
self.mapWidth = 0
self.mapHeight = 0
- self.tilesetImage = nil
- self.tileQuads = {}
+ self.tileGidInfo = {}
+ self.layerTileDimensions = {}
local mapData = loadMapData(mapPath)
self.mapData = mapData
- self.tileWidth = mapData and (mapData.tilewidth or 16) or 16
- self.tileHeight = mapData and (mapData.tileheight or 16) or 16
+ self.tileWidth = mapData and (mapData.tilewidth or 8) or 8
+ self.tileHeight = mapData and (mapData.tileheight or 8) or 8
self.mapWidth = (mapData and mapData.width or 0) * self.tileWidth
self.mapHeight = (mapData and mapData.height or 0) * self.tileHeight
- if type(tilesetPath) == "string" and tilesetPath ~= "" then
- local ok, img = pcall(love.graphics.newImage, tilesetPath)
- if ok and img then
- self.tilesetImage = img
- local firstGid = (mapData.tilesets and mapData.tilesets[1] and mapData.tilesets[1].firstgid) or 1
- local imgW, imgH = img:getDimensions()
- local tw, th = self.tileWidth, self.tileHeight
- local cols = math.floor(imgW / tw)
- local rows = math.floor(imgH / th)
- for index = 0, (cols * rows) - 1 do
- local qx = (index % cols) * tw
- local qy = math.floor(index / cols) * th
- self.tileQuads[firstGid + index] = love.graphics.newQuad(qx, qy, tw, th, imgW, imgH)
+ if mapData and mapData.tilesets then
+ for _, ts in ipairs(mapData.tilesets) do
+ local info = tilesets[ts.name]
+ if info then
+ local ok, img = pcall(love.graphics.newImage, info.path)
+ if ok and img then
+ local tw = info.tilewidth or self.tileWidth
+ local th = info.tileheight or self.tileHeight
+ local imgW, imgH = img:getDimensions()
+ local cols = math.floor(imgW / tw)
+ local rows = math.floor(imgH / th)
+ for index = 0, (cols * rows) - 1 do
+ local qx = (index % cols) * tw
+ local qy = math.floor(index / cols) * th
+ local gid = ts.firstgid + index
+ local quad = love.graphics.newQuad(qx, qy, tw, th, imgW, imgH)
+ self.tileGidInfo[gid] = { image = img, quad = quad, tilewidth = tw, tileheight = th }
+ end
+ end
end
end
end
@@ -88,6 +94,19 @@ function Tilemap:new(mapPath, tilesetPath)
elseif n == "ground" then self.layerGround = layer
elseif n == "foreground" then self.layerForeground = layer
end
+ local dims = nil
+ if layer.data then
+ for _, gid in ipairs(layer.data) do
+ if gid and gid ~= 0 then
+ local gi = self.tileGidInfo[gid]
+ if gi then
+ dims = { tilewidth = gi.tilewidth, tileheight = gi.tileheight }
+ break
+ end
+ end
+ end
+ end
+ self.layerTileDimensions[n] = dims or { tilewidth = self.tileWidth, tileheight = self.tileHeight }
elseif layer.type == "objectgroup" and layer.objects then
local name = (layer.name or ""):gsub("%s+", "_"):lower()
for _, obj in ipairs(layer.objects) do
@@ -169,6 +188,11 @@ function Tilemap:getTileHeight()
return self.tileHeight
end
+function Tilemap:getLayerTileDimensions(layerName)
+ return self.layerTileDimensions[layerName:lower()]
+ or { tilewidth = self.tileWidth, tileheight = self.tileHeight }
+end
+
function Tilemap:getMapWidth()
return self.mapWidth
end
@@ -177,12 +201,8 @@ function Tilemap:getMapHeight()
return self.mapHeight
end
-function Tilemap:getTilesetImage()
- return self.tilesetImage
-end
-
-function Tilemap:getTileQuads()
- return self.tileQuads
+function Tilemap:getTileGidInfo()
+ return self.tileGidInfo
end
return Tilemap
diff --git a/world.lua b/world.lua
index b9ba01f..1c49fd4 100644
--- a/world.lua
+++ b/world.lua
@@ -26,7 +26,7 @@ function World:new()
return self
end
-function World:load(mapPath, tilesetPath)
+function World:load(mapPath, tilesets)
if self.physicsWorld then
self.groundEntities = {}
end
@@ -43,14 +43,15 @@ function World:load(mapPath, tilesetPath)
end
)
- self.tilemap = Tilemap:new(mapPath, tilesetPath)
+ self.tilemap = Tilemap:new(mapPath, tilesets)
self.mapData = self.tilemap:getMapData()
if not self.mapData then
error("World:load - no map data from " .. tostring(mapPath))
end
- local tileWidth = self.tilemap:getTileWidth()
- local tileHeight = self.tilemap:getTileHeight()
+ local groundDims = self.tilemap:getLayerTileDimensions("ground")
+ local tileWidth = groundDims.tilewidth
+ local tileHeight = groundDims.tileheight
local groundLayer = self.tilemap:getGroundLayer()
if groundLayer and groundLayer.data then
@@ -205,7 +206,7 @@ function World:getMapData()
return self.mapData
end
-local function drawTileLayer(layer, tileWidth, tileHeight, tilesetImage, tileQuads)
+local function drawTileLayer(layer, mapTileW, mapTileH, tileGidInfo)
if not layer or not layer.visible or not layer.data then return end
local w = layer.width or 0
local data = layer.data
@@ -214,16 +215,17 @@ local function drawTileLayer(layer, tileWidth, tileHeight, tilesetImage, tileQua
local idx = i - 1
local tx = idx % w
local ty = math.floor(idx / w)
- local x = tx * tileWidth
- local y = ty * tileHeight
- if tilesetImage and tileQuads and tileQuads[gid] then
- love.graphics.draw(tilesetImage, tileQuads[gid], x, y)
+ local x = tx * mapTileW
+ local y = ty * mapTileH
+ local info = tileGidInfo and tileGidInfo[gid]
+ if info then
+ love.graphics.draw(info.image, info.quad, x, y)
else
local r = ((gid * 17) % 256) / 255
local g = ((gid * 31 + 50) % 256) / 255
local b = ((gid * 47 + 100) % 256) / 255
love.graphics.setColor(r, g, b, 1)
- love.graphics.rectangle("fill", x, y, tileWidth, tileHeight)
+ love.graphics.rectangle("fill", x, y, mapTileW, mapTileH)
love.graphics.setColor(1, 1, 1, 1)
end
end
@@ -231,14 +233,12 @@ local function drawTileLayer(layer, tileWidth, tileHeight, tilesetImage, tileQua
end
function World:draw()
- local tw = self.tilemap:getTileWidth()
- local th = self.tilemap:getTileHeight()
- local tilesetImage = self.tilemap:getTilesetImage()
- local tileQuads = self.tilemap:getTileQuads()
-
- drawTileLayer(self.tilemap:getBackgroundLayer(), tw, th, tilesetImage, tileQuads)
+ local mapTileW = self.tilemap:getTileWidth()
+ local mapTileH = self.tilemap:getTileHeight()
+ local tileGidInfo = self.tilemap:getTileGidInfo()
- drawTileLayer(self.tilemap:getGroundLayer(), tw, th, tilesetImage, tileQuads)
+ drawTileLayer(self.tilemap:getBackgroundLayer(), mapTileW, mapTileH, tileGidInfo)
+ drawTileLayer(self.tilemap:getGroundLayer(), mapTileW, mapTileH, tileGidInfo)
for _, e in ipairs(self.entities) do
if e.draw then e:draw() else World.drawEntityDefault(e) end
@@ -249,7 +249,7 @@ function World:draw()
World.drawPhysicsBodyOutlines(self.groundEntities)
end
- drawTileLayer(self.tilemap:getForegroundLayer(), tw, th, tilesetImage, tileQuads)
+ drawTileLayer(self.tilemap:getForegroundLayer(), mapTileW, mapTileH, tileGidInfo)
end
function World.drawPhysicsBodyOutlines(entityList)