From a06622361d858c4d9c78c15323fc0d0e17e94110 Mon Sep 17 00:00:00 2001 From: the lemons Date: Wed, 21 Dec 2022 15:46:30 -0600 Subject: collision detection and correction --- main.lua | 4 +++- obj.lua | 40 ++++++++++++++++++++++++++++++++++------ objects/test.lua | 2 +- world.lua | 2 +- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/main.lua b/main.lua index ebef333..392fa05 100644 --- a/main.lua +++ b/main.lua @@ -68,7 +68,9 @@ function love.draw() end end -- draw all possibly visible objects - for o in world.iterate(cx1 - 20, cy1 - 20, cx2 + 20, cy2 + 20) do + for o in world.in_box( + cx1 - obj.max_size, cy1 - obj.max_size, + cx2 + obj.max_size, cy2 + obj.max_size) do set_color(1, 1, 1) o:draw() end diff --git a/obj.lua b/obj.lua index 5f35755..59a68d5 100644 --- a/obj.lua +++ b/obj.lua @@ -29,7 +29,6 @@ function obj.load(id, data) o:init() return o end - function obj.is_obj(v) return getmetatable(v) == obj end @@ -48,6 +47,13 @@ function obj:overload(m, ...) end 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 + function obj:tick(...) if self.data.vel then local vx, vy = unpack(self.data.vel) @@ -57,7 +63,32 @@ function obj:tick(...) if self.data.avel then self.data.angle = (self.data.angle or 0) + self.data.avel / pi end + + if self.hitbox then + local x, y = unpack(self.data.pos) + for o in world.in_box( + x - obj.max_size, y - obj.max_size, + x + obj.max_size, y + obj.max_size) do + if o.hitbox and o ~= self then + local dist = o.hitbox + self.hitbox + local ox, oy = unpack(o.data.pos) + local dx, dy = ox - x, oy - y + if dx*dx + dy*dy < dist*dist then + local angle = math.atan2(dy, dx) + -- reposition self outside of collided object + self.data.pos[1] = + self.data.pos[1] - math.cos(angle) * dist + dx + self.data.pos[2] = + self.data.pos[2] - math.sin(angle) * dist + dy + self:collision(o, angle) + o:collision(self, pi - angle) + end + end + end + end + self:overload("tick", ...) + local chunk = world.chunk(unpack(self.data.pos)) if chunk ~= self.chunk then self.chunk.objects[self.id] = nil @@ -76,11 +107,8 @@ function obj:draw(...) love.graphics.pop() 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", ...) +function obj:collision(collided) + return self:overload("collision", collided) end function obj:remove() diff --git a/objects/test.lua b/objects/test.lua index d8c1a65..9d72b29 100644 --- a/objects/test.lua +++ b/objects/test.lua @@ -1,4 +1,4 @@ -local test = {radius = 4} +local test = {hitbox = 4} function test:draw() line(-4, 4, 0, -4, 4, 4, -4, 4) diff --git a/world.lua b/world.lua index c153a70..0607225 100644 --- a/world.lua +++ b/world.lua @@ -43,7 +43,7 @@ function world.all() end) end -function world.iterate(x1, y1, x2, y2) +function world.in_box(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 -- cgit v1.2.3