add Physics_Body and basic move_body

This commit is contained in:
Tuomas Katajisto 2026-09-20 11:23:19 +03:00
parent 75b1752dba
commit 58cd083c2d
3 changed files with 119 additions and 5 deletions

View File

@ -1,4 +1,4 @@
master_volume 0.15
master_volume 0
music_volume 1
sfx_volume 1
fullscreen 0

View File

@ -1,2 +1,86 @@
#load "colliders.jai";
#load "worldphysics.jai";
Physics_Body :: struct {
half_extents : Vector3;
velocity : Vector3;
position : Vector3;
// Status, don't write to these outside of the engine physics code:
on_ground : bool;
hit_x : bool;
hit_y : bool;
hit_z : bool;
// Config:
prevent_falling : bool = true;
max_step_height : float = 0.0;
gravity : float = 20;
downward_probe_dist : float = 0.01;
}
move_body :: (body : *Physics_Body, dt: float) {
// reset status
body.on_ground = false;
body.hit_x = false;
body.hit_y = false;
body.hit_z = false;
// apply velocity XZ
body.position.x += body.velocity.x * dt;
if body_overlaps_solid(body) {
body.hit_x = true;
if body.velocity.x < 0 {
hit_cell := floor(body.position.x - body.half_extents.x);
body.position.x = hit_cell + 1.0 + body.half_extents.x;
} else {
hit_cell := floor(body.position.x + body.half_extents.x);
body.position.x = hit_cell - body.half_extents.x;
}
body.velocity.x = 0;
}
body.position.z+= body.velocity.z * dt;
if body_overlaps_solid(body) {
body.hit_z = true;
if body.velocity.z < 0 {
hit_cell := floor(body.position.z - body.half_extents.z);
body.position.z = hit_cell + 1.0 + body.half_extents.z;
} else {
hit_cell := floor(body.position.z + body.half_extents.z);
body.position.z = hit_cell - body.half_extents.z;
}
body.velocity.z = 0;
}
// gravity
probe_body := body.*;
probe_body.position.y -= body.downward_probe_dist;
if body.velocity.y <= 0 && body_overlaps_solid(*probe_body) {
// Do this so we don't stutter on the ground
body.hit_y = true;
body.on_ground = true;
body.velocity.y = 0;
hit_cell := floor(probe_body.position.y - body.half_extents.y);
body.position.y = hit_cell + 1.0 + body.half_extents.y;
} else {
body.velocity.y -= body.gravity * dt;
}
// apply velocity Y
body.position.y += body.velocity.y * dt;
if body_overlaps_solid(body) {
body.hit_y = true;
if body.velocity.y < 0 {
body.on_ground = true;
hit_cell := floor(body.position.y - body.half_extents.y);
body.position.y = hit_cell + 1.0 + body.half_extents.y;
} else {
hit_cell := floor(body.position.y + body.half_extents.y);
body.position.y = hit_cell - body.half_extents.y;
}
body.velocity.y = 0;
}
}

View File

@ -1,7 +1,4 @@
is_trile_collision :: (fx: float, fy: float, fz: float) -> bool {
x := cast(s32)floor(fx);
y := cast(s32)floor(fy);
z := cast(s32)floor(fz);
is_cell_solid :: (x : s32, y : s32, z : s32) -> bool {
world := get_current_world();
if !world.valid then return false;
@ -12,3 +9,36 @@ is_trile_collision :: (fx: float, fy: float, fz: float) -> bool {
lx, ly, lz := world_to_local(x, y, z);
return chunk_get_occupancy_mask_at(chunk, lx, ly, lz) != .FREE;
}
is_trile_collision :: (fx: float, fy: float, fz: float) -> bool {
x := cast(s32)floor(fx);
y := cast(s32)floor(fy);
z := cast(s32)floor(fz);
return is_cell_solid(x, y, z);
}
// A little bit of leeway into collisions so we aren't jittering
SKIN :: 0.001;
body_overlaps_solid :: (body : *Physics_Body) -> bool {
max := body.position + body.half_extents;
min := body.position - body.half_extents;
min_x := cast(s32)floor(min.x + SKIN);
min_y := cast(s32)floor(min.y + SKIN);
min_z := cast(s32)floor(min.z + SKIN);
max_x := cast(s32)floor(max.x - SKIN);
max_y := cast(s32)floor(max.y - SKIN);
max_z := cast(s32)floor(max.z - SKIN);
for x : min_x..max_x {
for y : min_y..max_y {
for z : min_z..max_z {
if is_cell_solid(x,y,z) {
return true;
}
}
}
}
return false;
}