summaryrefslogtreecommitdiff
path: root/world.lua
diff options
context:
space:
mode:
Diffstat (limited to 'world.lua')
-rw-r--r--world.lua96
1 files changed, 70 insertions, 26 deletions
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