From 6d5e3252b51b096f88945cdb77f46d1128801d1f Mon Sep 17 00:00:00 2001 From: iamcheeseman Date: Fri, 13 Mar 2026 18:32:52 -0400 Subject: Fix collision resolution at low fps --- src/objs/player.lua | 2 +- src/objs/tilemap.lua | 5 ++++ src/phys.lua | 74 +++++++++++++++++++++++++++------------------------- src/room_editor.lua | 2 +- 4 files changed, 46 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/objs/player.lua b/src/objs/player.lua index ec04204..58e5f3a 100644 --- a/src/objs/player.lua +++ b/src/objs/player.lua @@ -23,7 +23,7 @@ end function new_player(x, y) local ent = new_entity() - add_comp(ent, "Body", x, y, 64, 64, { + add_comp(ent, "Body", x, y, 16, 16, { offsetx = -8, offsety = -8, layers = {}, diff --git a/src/objs/tilemap.lua b/src/objs/tilemap.lua index 834a770..90b8c8a 100644 --- a/src/objs/tilemap.lua +++ b/src/objs/tilemap.lua @@ -153,6 +153,11 @@ function to_tile_coords(x, y) return math.floor(x / TILESIZE), math.floor(y / TILESIZE) end +function get_tile_rect(x, y) + x, y = to_tile_coords(x, y) + return x*TILESIZE, y*TILESIZE, TILESIZE, TILESIZE +end + function remove_tile(map, x, y) map.tiledata[ID(map, x, y)] = 0 map.needs_rebuild = true 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 diff --git a/src/room_editor.lua b/src/room_editor.lua index 1aee150..e13bb69 100644 --- a/src/room_editor.lua +++ b/src/room_editor.lua @@ -135,7 +135,7 @@ end local function get_snapped_to_grid(room_editor, x, y) if room_editor.entity_snap then - return snap(x, TILESIZE), snap(y, TILESIZE) + return snap(x, TILESIZE/4), snap(y, TILESIZE/4) else -- Still snap to the pixel cause yes return round(x), round(y) -- cgit v1.3-2-g0d8e