feat: better walls

This commit is contained in:
Dan Finch 2026-08-04 13:09:26 +02:00
parent 81474b6bca
commit 61389f091c
3 changed files with 68 additions and 21 deletions

View file

@ -14,9 +14,13 @@ export type Player = {
export const EYE_HEIGHT = 1.6
const RADIUS = 0.35
const SPEED = 4
const SPEED = 6
/** Speed multiplier while a Run key (Shift) is held. Tweak to taste; set high to
* blast across the big terrain -- move+collision is substepped, so walls stay
* solid even at big multipliers. */
const RUN_MULTIPLIER = 2
const GRAVITY = 22
const JUMP_SPEED = 8
const JUMP_SPEED = 20
const NPC_RADIUS = 0.5
export namespace Player {
@ -26,13 +30,31 @@ export namespace Player {
player.velocityY = JUMP_SPEED
player.onGround = false
}
moveHorizontal(player, keys, dt)
collide(player, level)
// Move + collide in small substeps: collision is discrete (move, then push
// out), so a single big running step could otherwise skip clean through a
// wall. Substepping keeps each advance short enough to always hit it.
const steps = moveSubsteps(keys, dt)
for (let i = 0; i < steps; i++) {
moveHorizontal(player, keys, dt / steps)
collide(player, level)
}
fall(player, dt, level)
}
/** Run-speed factor for the frame: RUN_MULTIPLIER while Shift is held, else 1. */
function runFactor(keys: Set<string>): number {
return keys.has("ShiftLeft") || keys.has("ShiftRight") ? RUN_MULTIPLIER : 1
}
/** Number of move+collide substeps so each advances at most ~RADIUS, keeping
* the player from tunneling walls however fast they run. */
function moveSubsteps(keys: Set<string>, dt: number): number {
const perFrame = SPEED * runFactor(keys) * dt * Math.SQRT2
return Math.max(1, Math.ceil(perFrame / RADIUS))
}
function moveHorizontal(player: Player, keys: Set<string>, dt: number): void {
const speed = SPEED * dt
const speed = SPEED * runFactor(keys) * dt
const fx = Math.sin(player.yaw)
const fz = -Math.cos(player.yaw)
const rx = Math.cos(player.yaw)