summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthe lemons <citrons@mondecitronne.com>2022-12-21 00:13:49 -0600
committerthe lemons <citrons@mondecitronne.com>2022-12-21 00:13:49 -0600
commit619c46c37731df55bd2f50b7bb126c016734796e (patch)
treeb785914b5b8f82ad16610382afc75603cea85483
parent15b1b3127e636a8a63ff9cdb11dbac68f5218ffe (diff)
chunk-based rendering
-rw-r--r--main.lua65
-rw-r--r--obj.lua16
-rw-r--r--world.lua36
3 files changed, 92 insertions, 25 deletions
diff --git a/main.lua b/main.lua
index 84fb787..ebef333 100644
--- a/main.lua
+++ b/main.lua
@@ -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
diff --git a/obj.lua b/obj.lua
index ae8ff59..5f35755 100644
--- a/obj.lua
+++ b/obj.lua
@@ -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
diff --git a/world.lua b/world.lua
index f4fcb70..c153a70 100644
--- a/world.lua
+++ b/world.lua
@@ -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