diff options
| author | iamcheeseman <[hidden email]> | 2026-02-15 13:17:36 -0500 |
|---|---|---|
| committer | iamcheeseman <[hidden email]> | 2026-02-15 13:17:36 -0500 |
| commit | cab0d6e99d96f621e6efcf1ed6b5537cf122ad96 (patch) | |
| tree | c2ec966dbced8eff07ac89fe3cdde29dafe604e7 /src/phys/body.odin | |
| parent | 93c27830060788dea1c364465d29e44d05a3064e (diff) | |
Wall sliding/jumping
Diffstat (limited to 'src/phys/body.odin')
| -rw-r--r-- | src/phys/body.odin | 53 |
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 } |
