aboutsummaryrefslogtreecommitdiff
path: root/src/phys/body.odin
diff options
context:
space:
mode:
authoriamcheeseman <[hidden email]>2026-02-15 13:17:36 -0500
committeriamcheeseman <[hidden email]>2026-02-15 13:17:36 -0500
commitcab0d6e99d96f621e6efcf1ed6b5537cf122ad96 (patch)
treec2ec966dbced8eff07ac89fe3cdde29dafe604e7 /src/phys/body.odin
parent93c27830060788dea1c364465d29e44d05a3064e (diff)
Wall sliding/jumping
Diffstat (limited to 'src/phys/body.odin')
-rw-r--r--src/phys/body.odin53
1 files changed, 36 insertions, 17 deletions
diff --git a/src/phys/body.odin b/src/phys/body.odin
index ed8f6b5..54177e5 100644
--- a/src/phys/body.odin
+++ b/src/phys/body.odin
@@ -33,10 +33,16 @@ Collision_Type :: enum (u8) {
Raycast :: struct {
start: Vec2,
- dir: Vec2,
+ end: Vec2,
mask: Layer_Set,
}
+Raycast_Collision :: struct {
+ body: Body_Handle,
+ enter: Vec2,
+ exit: Vec2,
+}
+
Body :: struct {
handle: Body_Handle,
bin_idx: i32,
@@ -108,33 +114,46 @@ point_aabb :: proc(r: Rect, p: Vec2) -> bool {
}
@(require_results)
-raycast_to_aabb :: proc(rc: Raycast, body: Body) -> bool {
+raycast_to_aabb :: proc(
+ rc: Raycast,
+ body: Body,
+) -> (collision := Raycast_Collision{}, collided := false) {
body_min := body.pos + body.rect.start
body_max := body_min + body.rect.size
- rc_dir_to_body := linalg.normalize0((body_min + body_max) * 0.5 - rc.start)
+ rc_dir_to_body := (body_min + body_max) * 0.5 - rc.start
+ rc_dir := linalg.normalize0(rc.end - rc.start)
// Don't consider bodies behind the ray
- if linalg.dot(rc_dir_to_body, rc.dir) < 0 {
- return false;
+ if linalg.dot(rc_dir_to_body, rc_dir) < 0 {
+ return
}
- tmin := -math.INF_F32
- tmax := math.INF_F32
+ near := -math.INF_F32
+ far := math.INF_F32
- dir_inv := 1.0 / rc.dir
+ dir_inv := 1.0 / rc_dir
- tx_min := (body_min.x - rc.start.x) * dir_inv.x
- tx_max := (body_max.x - rc.start.x) * dir_inv.x
+ tx_near := (body_min.x - rc.start.x) * dir_inv.x
+ tx_far := (body_max.x - rc.start.x) * dir_inv.x
- tmin = max(tmin, min(tx_max, tx_min))
- tmax = min(tmax, max(tx_max, tx_min))
+ near = max(near, min(tx_far, tx_near))
+ far = min(far, max(tx_far, tx_near))
- ty_min := (body_min.y - rc.start.y) * dir_inv.y
- ty_max := (body_max.y - rc.start.y) * dir_inv.y
+ ty_near := (body_min.y - rc.start.y) * dir_inv.y
+ ty_far := (body_max.y - rc.start.y) * dir_inv.y
- tmin = max(tmin, min(ty_max, ty_min))
- tmax = min(tmax, max(ty_max, ty_min))
+ near = max(near, min(ty_far, ty_near))
+ far = min(far, max(ty_far, ty_near))
+
+ collision.body = body.handle
+ collision.enter = rc.start + rc_dir * near
+ collision.exit = rc.start + rc_dir * far
+
+ rc_len := linalg.length2(rc.end - rc.start)
+ rc_dist_to_body := linalg.length2(rc.start - collision.enter)
+
+ collided = far >= near && rc_dist_to_body <= rc_len
- return tmax >= tmin
+ return
}