summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--camera.lua1
-rw-r--r--main.lua9
-rw-r--r--world.lua96
3 files changed, 76 insertions, 30 deletions
diff --git a/camera.lua b/camera.lua
index 752b32e..6439a9f 100644
--- a/camera.lua
+++ b/camera.lua
@@ -97,6 +97,7 @@ function Camera:set(padding)
local scaleY = canvasH / viewH
local scale = math.floor(math.min(scaleX, scaleY))
+ self._lastScale = scale
love.graphics.scale(scale)
diff --git a/main.lua b/main.lua
index 9a18611..d014b96 100644
--- a/main.lua
+++ b/main.lua
@@ -1,7 +1,8 @@
local VIRTUAL_WIDTH, VIRTUAL_HEIGHT = 16*10*3, 9*10*3
local CANVAS_PADDING = 6
-DEBUG = true
+DEBUG = false
+
local CANVAS_WIDTH = VIRTUAL_WIDTH + CANVAS_PADDING
local CANVAS_HEIGHT = VIRTUAL_HEIGHT + CANVAS_PADDING
local WORLD_TO_CANVAS = 3
@@ -50,7 +51,6 @@ function states.game.load()
end
function states.game.update(dt)
- if camera then camera:update(dt) end
if world then world:update(dt) end
end
@@ -147,8 +147,9 @@ function love.draw()
subDx, subDy = world.camera:getSubPixelOffset()
end
- local uvOffsetX = subDx * WORLD_TO_CANVAS / CANVAS_WIDTH
- local uvOffsetY = subDy * WORLD_TO_CANVAS / CANVAS_HEIGHT
+ local camScale = (world and world.camera and world.camera._lastScale) or 2
+ local uvOffsetX = subDx * camScale / CANVAS_WIDTH
+ local uvOffsetY = subDy * camScale / CANVAS_HEIGHT
if shaderEnabled and smoothCameraShader and (subDx ~= 0 or subDy ~= 0) then
smoothCameraShader:send("offset", { uvOffsetX, uvOffsetY })
diff --git a/world.lua b/world.lua
index 1c49fd4..c7f2fe4 100644
--- a/world.lua
+++ b/world.lua
@@ -206,30 +206,62 @@ function World:getMapData()
return self.mapData
end
-local function drawTileLayer(layer, mapTileW, mapTileH, tileGidInfo)
+local function drawTileLayer(layer, mapTileW, mapTileH, tileGidInfo, viewMinX, viewMinY, viewMaxX, viewMaxY)
if not layer or not layer.visible or not layer.data then return end
local w = layer.width or 0
+ local h = layer.height or 0
+ if w == 0 or h == 0 then return end
+
+ local minCol, maxCol, minRow, maxRow
+ if viewMinX and viewMaxX and viewMinY and viewMaxY then
+ minCol = math.max(0, math.floor(viewMinX / mapTileW))
+ maxCol = math.min(w - 1, math.floor(viewMaxX / mapTileW))
+ minRow = math.max(0, math.floor(viewMinY / mapTileH))
+ maxRow = math.min(h - 1, math.floor(viewMaxY / mapTileH))
+ else
+ minCol, maxCol = 0, w - 1
+ minRow, maxRow = 0, h - 1
+ end
+
+ -- Collect tiles by image for SpriteBatch (reduces 770 draw calls to 1-2 batch draws)
+ local batches = {}
+ local fallbacks = {}
local data = layer.data
- for i, gid in ipairs(data) do
- if gid and gid ~= 0 then
- local idx = i - 1
- local tx = idx % w
- local ty = math.floor(idx / w)
- 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, mapTileW, mapTileH)
- love.graphics.setColor(1, 1, 1, 1)
+ for ty = minRow, maxRow do
+ for tx = minCol, maxCol do
+ local idx = ty * w + tx + 1
+ local gid = data[idx]
+ if gid and gid ~= 0 then
+ local x = tx * mapTileW
+ local y = ty * mapTileH
+ local info = tileGidInfo and tileGidInfo[gid]
+ if info then
+ local img = info.image
+ batches[img] = batches[img] or {}
+ table.insert(batches[img], { quad = info.quad, x = x, y = y })
+ else
+ table.insert(fallbacks, { x = x, y = y, gid = gid })
+ end
end
end
end
+
+ for img, tiles in pairs(batches) do
+ local batch = love.graphics.newSpriteBatch(img, #tiles, "static")
+ for _, t in ipairs(tiles) do
+ batch:add(t.quad, t.x, t.y)
+ end
+ love.graphics.draw(batch)
+ end
+
+ for _, t in ipairs(fallbacks) do
+ local r = ((t.gid * 17) % 256) / 255
+ local g = ((t.gid * 31 + 50) % 256) / 255
+ local b = ((t.gid * 47 + 100) % 256) / 255
+ love.graphics.setColor(r, g, b, 1)
+ love.graphics.rectangle("fill", t.x, t.y, mapTileW, mapTileH)
+ love.graphics.setColor(1, 1, 1, 1)
+ end
end
function World:draw()
@@ -237,8 +269,20 @@ function World:draw()
local mapTileH = self.tilemap:getTileHeight()
local tileGidInfo = self.tilemap:getTileGidInfo()
- drawTileLayer(self.tilemap:getBackgroundLayer(), mapTileW, mapTileH, tileGidInfo)
- drawTileLayer(self.tilemap:getGroundLayer(), mapTileW, mapTileH, tileGidInfo)
+ local viewMinX, viewMinY, viewMaxX, viewMaxY
+ if self.camera then
+ local cx, cy = self.camera.x, self.camera.y
+ local cw = self.camera.width or 0
+ local ch = self.camera.height or 0
+ local pad = math.max(mapTileW, mapTileH) * 2
+ viewMinX = cx - pad
+ viewMinY = cy - pad
+ viewMaxX = cx + cw + pad
+ viewMaxY = cy + ch + pad
+ end
+
+ drawTileLayer(self.tilemap:getBackgroundLayer(), mapTileW, mapTileH, tileGidInfo, viewMinX, viewMinY, viewMaxX, viewMaxY)
+ drawTileLayer(self.tilemap:getGroundLayer(), mapTileW, mapTileH, tileGidInfo, viewMinX, viewMinY, viewMaxX, viewMaxY)
for _, e in ipairs(self.entities) do
if e.draw then e:draw() else World.drawEntityDefault(e) end
@@ -249,7 +293,7 @@ function World:draw()
World.drawPhysicsBodyOutlines(self.groundEntities)
end
- drawTileLayer(self.tilemap:getForegroundLayer(), mapTileW, mapTileH, tileGidInfo)
+ drawTileLayer(self.tilemap:getForegroundLayer(), mapTileW, mapTileH, tileGidInfo, viewMinX, viewMinY, viewMaxX, viewMaxY)
end
function World.drawPhysicsBodyOutlines(entityList)
@@ -280,17 +324,17 @@ function World:update(dt)
if not self.physicsWorld then return end
self.physicsWorld:update(PHYSICS_DT)
- if self.camera then
- self.camera:setTarget(self.player)
- self.camera:update(dt)
- end
-
for _, e in ipairs(self.entities) do
if e.body then
e:syncFromPhysicsBody()
end
if e.update then e:update(dt) end
end
+
+ if self.camera then
+ self.camera:setTarget(self.player)
+ self.camera:update(dt)
+ end
end
return World