aboutsummaryrefslogtreecommitdiff
path: root/src/phys
diff options
context:
space:
mode:
authoriamcheeseman <[hidden email]>2026-01-15 12:13:41 -0500
committeriamcheeseman <[hidden email]>2026-01-15 12:13:41 -0500
commit1ebeadbad7f7ee757096320d9c5daf3b55373f6a (patch)
treeffa9ce9d9df6f93970c488441f0a74c8bfcc9022 /src/phys
parentd6f276be6bc1214c88cfc5346ceb7a5bea610638 (diff)
Bullets! And buncha physics fixes! And more!
Diffstat (limited to 'src/phys')
-rw-r--r--src/phys/body.odin5
-rw-r--r--src/phys/world.odin110
2 files changed, 73 insertions, 42 deletions
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
+}