diff options
author | the lemons <citrons@mondecitronne.com> | 2022-12-21 00:13:49 -0600 |
---|---|---|
committer | the lemons <citrons@mondecitronne.com> | 2022-12-21 00:13:49 -0600 |
commit | 619c46c37731df55bd2f50b7bb126c016734796e (patch) | |
tree | b785914b5b8f82ad16610382afc75603cea85483 | |
parent | 15b1b3127e636a8a63ff9cdb11dbac68f5218ffe (diff) |
chunk-based rendering
-rw-r--r-- | main.lua | 65 | ||||
-rw-r--r-- | obj.lua | 16 | ||||
-rw-r--r-- | world.lua | 36 |
3 files changed, 92 insertions, 25 deletions
@@ -4,11 +4,11 @@ local obj = require "obj" obj.load_types() line = love.graphics.line set_color = love.graphics.setColor -love.graphics.setLineWidth(0.5) +line_width = 0.4 local cam = { x = 0, y = 0, - scale = 256, + scale = 1.1, panning = false, } @@ -19,25 +19,64 @@ for i = 1, 100 do }) end -local function view_scale() +obj.new("test", {0, 0}) + +local function window_scale() local w, h = love.graphics.getDimensions() - return cam.scale / math.min(w, h) + return 256 / math.min(w, h) end -local function view_transform() +local function view_scale() + return window_scale() / cam.scale +end + +local function view_dimensions() + local w, h = love.graphics.getDimensions() local scale = view_scale() + return w * scale, h * scale +end + +local function window_transform() + local scale = window_scale() local trans = love.math.newTransform(0, 0, 0, 1/scale, 1/scale) - trans:translate(cam.x, cam.y) + return trans +end + +local function view_transform() + local w, h = view_dimensions() + local trans = window_transform() + trans:scale(cam.scale, cam.scale) + trans:translate(-cam.x + w/2, -cam.y + h/2) return trans end function love.draw() - love.graphics.clear(0,0,0) + love.graphics.clear(0, 0, 0) + local w, h = view_dimensions() + local cx1, cy1 = cam.x - w/2, cam.y - h/2 + local cx2, cy2 = cam.x + w/2, cam.y + h/2 + love.graphics.applyTransform(view_transform()) - for _, o in pairs(world.objects) do - love.graphics.setColor(1, 1, 1) + -- the line thickness will scale according to the zoom amount. counteract this. + love.graphics.setLineWidth(line_width / cam.scale) + -- draw a grid + set_color(0.1, 0.1, 0.1) + for x = cx1 - cx1%64, cx2, 64 do + for y = cy1 - cy1%64, cy2, 64 do + line(x, y, x + world.chunk_size, y) + line(x, y, x, y + world.chunk_size) + end + end + -- draw all possibly visible objects + for o in world.iterate(cx1 - 20, cy1 - 20, cx2 + 20, cy2 + 20) do + set_color(1, 1, 1) o:draw() end + love.graphics.origin() + + love.graphics.applyTransform(window_transform()) + love.graphics.setLineWidth(line_width) + set_color(1, 1, 1) end function love.update() @@ -62,7 +101,11 @@ function love.mousemoved(_, _, dx, dy) if cam.panning then local scale = view_scale() dx, dy = dx * scale, dy * scale - cam.x = cam.x + dx - cam.y = cam.y + dy + cam.x = cam.x - dx + cam.y = cam.y - dy end end + +function love.wheelmoved(_, y) + cam.scale = math.min(math.max(cam.scale + (y * 0.1), 0.25), 4) +end @@ -3,6 +3,7 @@ local pi = math.pi local obj = {} +obj.max_size = 20 local types = {} function obj.load_types() @@ -48,12 +49,6 @@ function obj:overload(m, ...) end function obj:tick(...) - local chunk = world.chunk(unpack(self.data.pos)) - if chunk ~= self.chunk then - self.chunk.objects[self.id] = nil - chunk.objects[self.id] = self - self.chunk = chunk - end if self.data.vel then local vx, vy = unpack(self.data.vel) self.data.pos[1] = self.data.pos[1] + vx @@ -62,7 +57,13 @@ function obj:tick(...) if self.data.avel then self.data.angle = (self.data.angle or 0) + self.data.avel / pi end - return self:overload("tick", ...) + self:overload("tick", ...) + local chunk = world.chunk(unpack(self.data.pos)) + if chunk ~= self.chunk then + self.chunk.objects[self.id] = nil + chunk.objects[self.id] = self + self.chunk = chunk + end end function obj:draw(...) @@ -77,6 +78,7 @@ end function obj:init(...) self.chunk = world.chunk(unpack(self.data.pos)) + self.chunk.objects[self.id] = self world.objects[self.id] = self return self:overload("init", ...) end @@ -1,7 +1,6 @@ local world = {} -local chunk_size = 1024 - +world.chunk_size = 1024 world.chunks = {} setmetatable(world.chunks, { __index = function(_, bee) @@ -15,11 +14,11 @@ world.objects = {} world.last_id = 0 function world.chunk_pos(x, y) - return math.floor(x / chunk_size), math.floor(y / chunk_size) + return math.floor(x / world.chunk_size), math.floor(y / world.chunk_size) end function world.world_pos(x, y) - return x * chunk_size, y * chunk_size + return x * world.chunk_size, y * world.chunk_size end function world.chunk(x, y) @@ -27,13 +26,36 @@ function world.chunk(x, y) if not world.chunks[cx][cy] then -- load chunk from disk if the world.chunks[cx][cy] = setmetatable( - {pos = {cx, cy}, objects = {}}, chunk) + {pos = {cx, cy}, objects = {}}, chunk_mt) end return world.chunks[cx][cy] end -function world.get_object(id) +function world.object(id) + return world.objects[id] +end + +function world.all() + return coroutine.wrap(function() + for _, o in pairs(world.objects) do + coroutine.yield(o) + end + end) +end + +function world.iterate(x1, y1, x2, y2) + return coroutine.wrap(function() + for x = x1, x2 + world.chunk_size, world.chunk_size do + for y = y1, y2 + world.chunk_size, world.chunk_size do + for _, o in pairs(world.chunk(x, y).objects) do + local x, y = unpack(o.data.pos) + if x >= x1 and x <= x2 and y >= y1 and y <= y2 then + coroutine.yield(o) + end + end + end + end + end) end -world.__index = world return world |