From 1ebeadbad7f7ee757096320d9c5daf3b55373f6a Mon Sep 17 00:00:00 2001 From: iamcheeseman <[hidden email]> Date: Thu, 15 Jan 2026 12:13:41 -0500 Subject: Bullets! And buncha physics fixes! And more! --- src/phys/body.odin | 5 +-- src/phys/world.odin | 110 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 73 insertions(+), 42 deletions(-) (limited to 'src/phys') diff --git a/src/phys/body.odin b/src/phys/body.odin index 93d8623..09dc95a 100644 --- a/src/phys/body.odin +++ b/src/phys/body.odin @@ -42,10 +42,7 @@ make_body :: proc( rect: Rect, layers := bit_set[Layer;u16]{.DEFAULT}, mask := bit_set[Layer;u16]{.DEFAULT}, -) -> ( - Body_Handle, - ^Body, -) { +) -> Body_Handle { b := Body { rect = rect, layers = layers, diff --git a/src/phys/world.odin b/src/phys/world.odin index 7a56990..189f0b0 100644 --- a/src/phys/world.odin +++ b/src/phys/world.odin @@ -8,12 +8,14 @@ import rl "vendor:raylib" BIN_COUNT :: 2056 BIN_SIZE :: 64 -Body_Handle :: u32 +Body_Handle :: struct { + idx: u32, + uses: u32, +} world: struct { - handles: [dynamic]u32, - unused_handles: [dynamic]Body_Handle, bodies: [dynamic]Body, + holes: [dynamic]Body_Handle, bins: [BIN_COUNT][dynamic]Body_Handle, } @@ -21,8 +23,7 @@ destroy_world :: proc() { for bin in world.bins { delete(bin) } - delete(world.handles) - delete(world.unused_handles) + delete(world.holes) delete(world.bodies) } @@ -87,61 +88,74 @@ _remove_from_bins :: proc(b: Body) { // log.debug(last, b.handle) bin[b.bin_idx] = last - last_body := get_body(last) + last_body := _get_body(last) last_body.bin_idx = b.bin_idx } } -get_body :: proc(h: Body_Handle) -> ^Body { - return &world.bodies[world.handles[h]] +@(private = "file") +_get_body :: proc(h: Body_Handle, location := #caller_location) -> ^Body { + if h.idx >= u32(len(world.bodies)) { + log.warn("Handle is out of range", location = location) + return nil + } + if world.bodies[h.idx].handle != h { + log.warnf( + "Handle isn't yours (querying %v, got %v)", + h, + world.bodies[h.idx].handle, + location = location, + ) + } + return &world.bodies[h.idx] } -add_body :: proc(b: Body) -> (Body_Handle, ^Body) { +add_body :: proc(b: Body) -> Body_Handle { handle: Body_Handle if b.rect.size.x > BIN_SIZE || b.rect.size.y > BIN_SIZE { log.warnf("Body size is too big (%vx%v)", b.rect.size.x, b.rect.size.y) } - if len(world.unused_handles) > 0 { - handle = pop(&world.unused_handles) + if len(world.holes) > 0 { + handle = pop(&world.holes) + handle.uses += 1 } else { - handle = cast(Body_Handle)len(world.handles) - append(&world.handles, 0) + resize(&world.bodies, len(world.bodies) + 1) + handle.idx = u32(len(world.bodies) - 1) + handle.uses = 1 } + + world.bodies[handle.idx] = b + world.bodies[handle.idx].handle = handle - world.handles[handle] = u32(len(world.bodies)) - append(&world.bodies, b) - - body := &world.bodies[world.handles[handle]] - body.handle = handle - - _add_to_bins(body) + _add_to_bins(_get_body(handle)) - return handle, body + return handle } remove_body :: proc(h: Body_Handle) { - b := get_body(h) - - _remove_from_bins(b^) - - last := pop(&world.bodies) - if last.handle != h { - world.bodies[world.handles[h]] = last - world.handles[last.handle] = world.handles[h] + if h.idx >= u32(len(world.bodies)) || + world.bodies[h.idx].handle != h { + log.warn("Handle isn't yours, or is out of range") + return } - append(&world.unused_handles, h) + b := _get_body(h) + + _remove_from_bins(b^) + + append(&world.holes, b.handle) + world.bodies[h.idx] = {} } -get_collisions :: proc( +get_colliding_bodies :: proc( h: Body_Handle, allocator := context.allocator ) -> []Body_Handle { bodies := make([dynamic]Body_Handle, allocator) - b := get_body(h) + b := _get_body(h) rect := b.rect rect.start += b.pos @@ -154,7 +168,7 @@ get_collisions :: proc( continue } - c := get_body(c_h) + c := _get_body(c_h) c_rect := c.rect c_rect.start += c.pos @@ -171,7 +185,7 @@ get_collisions :: proc( update_body :: proc(h: Body_Handle) { dt := rl.GetFrameTime() - b := get_body(h) + b := _get_body(h) res_pos := b.pos + b.vel * dt @@ -191,7 +205,7 @@ update_body :: proc(h: Body_Handle) { continue } - c := get_body(c_h) + c := _get_body(c_h) if b.mask & c.layers == {} { continue @@ -231,11 +245,23 @@ update_body :: proc(h: Body_Handle) { b.vel.y = 0 } - set_body_position(h, res_pos) + set_position(h, res_pos) } -set_body_position :: proc(h: Body_Handle, new_pos: Vec2) { - b := get_body(h) +get_velocity :: proc(h: Body_Handle) -> Vec2 { + return _get_body(h).vel +} + +set_velocity :: proc(h: Body_Handle, vel: Vec2) { + _get_body(h).vel = vel +} + +get_position :: proc(h: Body_Handle) -> Vec2 { + return _get_body(h).pos +} + +set_position :: proc(h: Body_Handle, new_pos: Vec2) { + b := _get_body(h) prev_bin := _hash_bin(_world_to_bin(b.pos + b.rect.start)) res_bin := _hash_bin(_world_to_bin(new_pos + b.rect.start)) @@ -248,3 +274,11 @@ set_body_position :: proc(h: Body_Handle, new_pos: Vec2) { b.pos = new_pos } } + +get_collisions :: proc(h: Body_Handle) -> bit_set[Collision_Type;u8] { + return _get_body(h).collisions +} + +get_rect :: proc(h: Body_Handle) -> Rect { + return _get_body(h).rect +} -- cgit v1.3-2-g0d8e