diff --git a/settings.cfg b/settings.cfg index 216dad2..71e6294 100644 --- a/settings.cfg +++ b/settings.cfg @@ -1,4 +1,4 @@ -master_volume 0.15 +master_volume 0 music_volume 1 sfx_volume 1 fullscreen 0 diff --git a/src/pseudophysics/core.jai b/src/pseudophysics/core.jai index f15b8ef..ef32e2a 100644 --- a/src/pseudophysics/core.jai +++ b/src/pseudophysics/core.jai @@ -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; + } + +} diff --git a/src/pseudophysics/worldphysics.jai b/src/pseudophysics/worldphysics.jai index f9375f4..c898136 100644 --- a/src/pseudophysics/worldphysics.jai +++ b/src/pseudophysics/worldphysics.jai @@ -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; +}