feat(character): 16.8 - on land a physics walker moves the body (CharacterGround.walk); the package's own gravity, ballistic air and slope-probe refusal are gone

The package keeps the rules and hands them over each step: speed and heading, whether a jump
leaves, CHAR_STEP and the boots' slope limit. The walker (Jolt CharacterVirtual) does gravity,
landing, steps, slopes and following the ground down. Too steep is ground too steep facing the way
the body wanted to go; stepping off an edge is not. ludic.physics: phys_walker_move (follow the body
if something else moved it, then step), the slope limit, the jump always honoured. The character's
tests run on a real Jolt walker over the same fake world: 15 pass, a knee-high boulder now a step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-27 00:47:14 +03:00
parent d2cd775309
commit e909ec122c
11 changed files with 169 additions and 89 deletions

View file

@ -31,10 +31,11 @@ export function phys_walker_add(physics_st: mut PhysicsState, r: float, h: float
return len(physics_st.ph_walkers) - 1
}
# how high a step it takes without a jump, and how far it follows the ground down
export function phys_walker_limits(physics_st: PhysicsState, id: int, step_up: float, stick: float) -> void {
# how high a step it takes without a jump, how far it follows the ground down, and the steepest
# slope in degrees that is still ground
export function phys_walker_limits(physics_st: PhysicsState, id: int, step_up: float, stick: float, max_slope: float) -> void {
let k = ph_walker(physics_st, id)
if k != null { jph_char_limits(k, step_up, stick) }
if k != null { jph_char_limits(k, step_up, stick, max_slope) }
}
export function phys_walker_remove(physics_st: mut PhysicsState, id: int) -> void {
@ -72,3 +73,16 @@ export function phys_walker_place(physics_st: mut PhysicsState, id: int, x: floa
let k = ph_walker(physics_st, id)
if k != null and physics_st.ph_world != null { jph_char_place(physics_st.ph_world, k, x, y, z) }
}
# a body the game keeps elsewhere, moved by its walker: put where the body is if something else
# moved it (a teleport, a ride, a swim), then one step under the given limits; the ground after it
export function phys_walker_move(physics_st: mut PhysicsState, id: int, x: float, y: float, z: float, vx: float, vz: float, jump: float, step: float, max_slope: float, dt: float) -> int {
let p = phys_walker_pose(physics_st, id)
if p == null { return PHYS_IN_AIR }
let dx = p.x - x
let dy = p.y - y
let dz = p.z - z
if dx * dx + dy * dy + dz * dz > 0.0025 { phys_walker_place(physics_st, id, x, y, z) }
phys_walker_limits(physics_st, id, step, 0.5, max_slope)
return phys_walker_step(physics_st, id, dt, vx, vz, jump)
}