aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.lua11
-rw-r--r--src/objs/player.lua1
-rw-r--r--src/phys.lua154
3 files changed, 82 insertions, 84 deletions
diff --git a/main.lua b/main.lua
index 21eefbe..b516216 100644
--- a/main.lua
+++ b/main.lua
@@ -13,12 +13,7 @@ function love.load()
event_bind(scn.on_draw, "Tilemap", tilemap_draw_sys)
set_scene(scn)
- new_player(100, 100)
-
- box1 = phys.Box.new(20, 20, 16, 16, {
- layers = {},
- mask = { "hard" },
- })
+ player = new_player(100, 100)
ground1 = phys.Box.new(5, 50, 64, 16, {})
ground2 = phys.Box.new(64 - 16, 50 + 16, 16, 64, {})
@@ -34,7 +29,6 @@ function love.update(dt)
assert(scn, "No scene set.")
fire_event(scn.on_update, dt)
- box1:update(0, 5, dt)
flush_scene()
end
@@ -47,6 +41,9 @@ function love.draw(dt)
assert(scn, "No scene set.")
fire_event(scn.on_draw, dt)
+ ground1:draw()
+ ground2:draw()
+ player.box:draw()
-- TODO: Take care of weird displays
lg.setCanvas()
diff --git a/src/objs/player.lua b/src/objs/player.lua
index 31df42e..bc71ea7 100644
--- a/src/objs/player.lua
+++ b/src/objs/player.lua
@@ -49,5 +49,6 @@ function new_player(x, y)
})
add_comp(ent, "Player")
add_comp(ent, "Sprite", "res/img/player.ase")
+ return ent
end
diff --git a/src/phys.lua b/src/phys.lua
index 8c4455c..3cddd4e 100644
--- a/src/phys.lua
+++ b/src/phys.lua
@@ -17,18 +17,10 @@ world.layers = {}
--
-- You can use whatever physics layer you want, but these are the standard ones
-local function aabb_x(ax, aw, bx, bw)
- return ax < bx + bw and bx < ax + aw
-end
-
-local function aabb_y(ay, ah, by, bh)
- return ay < by + bh and by < ay + ah
-end
-
local function aabb(ax, ay, aw, ah, bx, by, bw, bh)
return
- ax < bx + bw and bx < ax + aw and
- ay < by + bh and by < ay + ah
+ ax < bx + bw and bx < ax + aw and
+ ay < by + bh and by < ay + ah
end
local function add_box_to_layers(box)
@@ -44,9 +36,9 @@ phys.Box = {}
phys.Box.__index = phys.Box
function phys.Box.new(
- x, y,
- width, height,
- opts
+ x, y,
+ width, height,
+ opts
)
opts = opts or {}
@@ -61,99 +53,107 @@ function phys.Box.new(
self.width = width
self.height = height
- self.layers = opts.layers or {"hard"}
+ self.layers = opts.layers or { "hard" }
self.mask = opts.mask or {}
- self.touching_down = false
- self.touching_up = false
- self.touching_vertically = false
- self.touching_left = false
- self.touching_right = false
- self.touching_horizontally = false
+ self.touchx = 0
+ self.touchy = 0
add_box_to_layers(self)
return self
end
-function phys.Box:get_rect()
- return
- self.x + self.offsetx,
- self.y + self.offsety,
- self.width,
- self.height
+function phys.Box:touching_left()
+ return self.touchx < 0
end
-function phys.Box:update(velx, vely, dt)
- local resx = self.x + velx * dt
- local resy = self.y + vely * dt
+function phys.Box:touching_right()
+ return self.touchx > 0
+end
- local small_side = math.min(self.width, self.height)
- local steps = math.ceil(vec_len(velx * dt, vely * dt) / small_side)
+function phys.Box:touching_horizontal()
+ return self.touchx ~= 0
+end
- self.touching_down = false
- self.touching_up = false
- self.touching_vertically = false
- self.touching_left = false
- self.touching_right = false
- self.touching_horizontally = false
+function phys.Box:touching_up()
+ return self.touchy < 0
+end
- -- this block is fat. much like a certain croatian...
- for i=1, steps do
- local p = i / steps
+function phys.Box:touching_down()
+ return self.touchy > 0
+end
- local boxx = resx + self.offsetx + velx * dt * p
- local boxy = resy + self.offsety + vely * dt * p
+function phys.Box:touching_vertical()
+ return self.touchy ~= 0
+end
- for _, layer in ipairs(self.mask) do
- for _, other in ipairs(world.layers[layer] or {}) do
- if other ~= self then
- local ox = other.x + other.offsetx
- local oy = other.y + other.offsety
+function phys.Box:touching()
+ return self.touchx ~= 0 and self.touchy ~= 0
+end
- if aabb(
- boxx, boxy, self.width, self.height,
- ox, oy, other.width, other.height
+function phys.Box:get_rect()
+ return
+ self.x + self.offsetx,
+ self.y + self.offsety,
+ self.width,
+ self.height
+end
+
+function collision_check(box)
+ local box_x, box_y, box_width, box_height = box:get_rect()
+ local other_x, other_y, other_width, other_height
+
+ for _, layer in ipairs(box.mask) do
+ for _, other in ipairs(world.layers[layer] or {}) do
+ if other == box then
+ goto continue
+ end
+ other_x, other_y, other_width, other_height = other:get_rect()
+
+ if aabb(
+ box_x, box_y, box_width, box_height,
+ other_x, other_y, other_width, other_height
) then
- if aabb_x(self.x + self.offsetx, self.width, ox, other.width) then
- if vely > 0 then
- resy = oy - self.height - self.offsety
- self.touching_down = true
- else
- resy = oy + other.height - self.offsety
- self.touching_up = true
- end
- self.touching_vertically = true
- elseif aabb_y(self.y + self.offsety, self.height, oy, other.height) then
- if velx > 0 then
- resx = ox - self.width - self.offsetx
- self.touching_left = true
- else
- resx = ox + other.width - self.offsetx
- self.touching_right = true
- end
- self.touching_horizontally = true
- end
- end
- end
+ return true
end
+ ::continue::
end
+ end
+ return false
+end
- if self.touching_horizontally then
+function phys.Box:update(velx, vely, dt)
+ local small_side = math.min(self.width, self.height)
+ local steps = math.ceil(vec_len(velx * dt, vely * dt) / small_side)
+
+ -- this block is fat. much like a certain croatian...
+ -- not anymore :D
+ 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
velx = 0
+ self.x = before
end
- if self.touching_vertically then
+
+ before = self.y
+ self.y = self.y + vely * dt * p
+ if collision_check(self) then
+ self.touchy = velx > 0 and 1 or -1
vely = 0
+ self.y = before
end
- if self.touching_horizontally or self.touching_vertically then
+ if self:touching() then
break
end
end
- self.x = resx
- self.y = resy
-
return velx, vely
end