aboutsummaryrefslogtreecommitdiff
path: root/src/phys.lua
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-03-13 18:32:52 -0400
committeriamcheeseman <[email protected]>2026-03-13 18:32:52 -0400
commit6d5e3252b51b096f88945cdb77f46d1128801d1f (patch)
tree57150e9de1c01d147b1511839304040c3cc66948 /src/phys.lua
parent88d65e65eb92c8e086bdbb7d938bbb44522caf6f (diff)
Fix collision resolution at low fps
Diffstat (limited to 'src/phys.lua')
-rw-r--r--src/phys.lua74
1 files changed, 39 insertions, 35 deletions
diff --git a/src/phys.lua b/src/phys.lua
index e55f5c7..9adb915 100644
--- a/src/phys.lua
+++ b/src/phys.lua
@@ -104,36 +104,32 @@ function phys.Box:get_rect()
self.height
end
-function box_in_tilemap(map, box)
+local function get_tilemap_collision_rect(map, box)
local x, y, width, height = box:get_rect()
if has_tile(map, to_tile_coords(x, y)) then
- return true
+ return true, get_tile_rect(x, y)
end
if has_tile(map, to_tile_coords(x + width, y)) then
- return true
+ return true, get_tile_rect(x + width, y)
end
if has_tile(map, to_tile_coords(x, y + height)) then
- return true
+ return true, get_tile_rect(x, y + height)
end
if has_tile(map, to_tile_coords(x + width, y + height)) then
- return true
+ return true, get_tile_rect(x + width, y + height)
end
local extra_x = math.floor(width / (TILESIZE - 1))
local step = width / (extra_x + 1)
for i = 1, extra_x do
- if has_tile(
- map, to_tile_coords(x + step * i, y))
- then
- return true
+ if has_tile(map, to_tile_coords(x + step * i, y)) then
+ return true, get_tile_rect(x + step * i, y)
end
- if has_tile(
- map, to_tile_coords(x + step * i, y + height))
- then
- return true
+ if has_tile(map, to_tile_coords(x + step * i, y + height)) then
+ return true, get_tile_rect(x + step * i, y + height)
end
end
@@ -141,29 +137,29 @@ function box_in_tilemap(map, box)
step = height / (extra_y + 1)
for i = 1, extra_y do
- if has_tile(
- map, to_tile_coords(x, y + step * i))
- then
- return true
+ if has_tile(map, to_tile_coords(x, y + step * i)) then
+ return true, get_tile_rect(x, y + step * i)
end
- if has_tile(
- map, to_tile_coords(x + width, y + step * i))
- then
- return true
+ if has_tile(map, to_tile_coords(x + width, y + step * i)) then
+ return true, get_tile_rect(x + width, y * step * i)
end
end
- return value
+ return false
end
-function collision_check(box)
+local function get_collision_rect(box)
local box_x, box_y, box_width, box_height = box:get_rect()
local other_x, other_y, other_width, other_height
for _, tilemap in ipairs(box.tilemap_mask) do
- if box_in_tilemap(tilemap, box) then
- return true
+ local ok, tx, ty, t_width, t_height = get_tilemap_collision_rect(
+ tilemap,
+ box
+ )
+ if ok then
+ return true, tx, ty, t_width, t_height
end
end
@@ -178,7 +174,7 @@ function collision_check(box)
box_x, box_y, box_width, box_height,
other_x, other_y, other_width, other_height
) then
- return true
+ return true, other_x, other_y, other_width, other_height
end
::collision_check_continue::
end
@@ -199,22 +195,30 @@ function phys.Box:update(velx, vely, dt)
-- welc
for i = 1, steps do
local p = i / steps
- local before
- before = self.x
self.x = self.x + velx * dt * p
- if collision_check(self) then
- self.touchx = velx > 0 and 1 or -1
+ local ok, otherx, othery, other_width, other_height = get_collision_rect(self)
+ if ok then
+ self.touchx = sign(velx)
velx = 0
- self.x = before
+ if self.touchx > 0 then
+ -- this - 0.001 is a hack to prevent some silly bug I can't figure out
+ self.x = otherx - self.width - self.offsetx - 0.001
+ elseif self.touchx < 0 then
+ self.x = otherx + other_width - self.offsetx
+ end
end
- before = self.y
self.y = self.y + vely * dt * p
- if collision_check(self) then
- self.touchy = vely > 0 and 1 or -1
+ ok, otherx, othery, other_width, other_height = get_collision_rect(self)
+ if ok then
+ self.touchy = sign(vely)
vely = 0
- self.y = before
+ if self.touchy > 0 then
+ self.y = othery - self.height - self.offsety - 0.001
+ elseif self.touchy < 0 then
+ self.y = othery + other_height - self.offsety
+ end
end
if self:touching() then