SOURCE / PINNED RELEASE
Made of little things.
Soybert 3D
- Release
- 4bf80e758af1…
- Author-recorded commit
- 298fa2d0e8b1…
- License
- LICENSE
- Author’s source reference
- nostr://npub1n8ga89w8h6tvwamxusfyzexw8gjy84yxu9rxgnmk955cxtml4ujswzxydd/wss%3A%2F%2Fgit.napplet.soy%2F/n-9021e1b6a96
Archive hash verified: 7083223a53bbd320…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
export const STAGE_RADIUS = 5.6;
export const DEFAULT_MOVE_SPEED = 6.2;
export type ActorState = { x: number; z: number; y: number; vy: number; vx: number; vz: number; heading: number; celebration: number; recoil: number };
export function initialState(): ActorState { return { x: 0, z: 0, y: 0, vy: 0, vx: 0, vz: 0, heading: 0, celebration: 0, recoil: 10 }; }
export function jump(state: ActorState): boolean {
if (state.y > .001 || state.vy !== 0 || state.celebration > 0) return false;
state.vy = 7.8; return true;
}
export function shoot(state: ActorState): boolean {
if (state.recoil < .65 || state.celebration > 0) return false;
state.recoil = 0; return true;
}
export function celebrate(state: ActorState): boolean {
if (state.y > .001 || state.celebration > 0) return false;
state.celebration = 2.8; return true;
}
export function step(state: ActorState, dx: number, dz: number, dt: number, speed: number): boolean {
dt = Math.min(.05, Math.max(0, dt));
state.recoil += dt; state.celebration = Math.max(0, state.celebration - dt);
const length = Math.hypot(dx, dz);
if (length > 1) { dx /= length; dz /= length; }
if (state.celebration > 0) { dx = 0; dz = 0; }
const ease = 1 - Math.exp(-(length > .01 ? 22 : 28) * dt);
state.vx += (dx * speed - state.vx) * ease; state.vz += (dz * speed - state.vz) * ease;
state.x += state.vx * dt; state.z += state.vz * dt;
const distance = Math.hypot(state.x, state.z);
if (distance > STAGE_RADIUS) { state.x *= STAGE_RADIUS / distance; state.z *= STAGE_RADIUS / distance; }
if (Math.hypot(dx, dz) > .05) {
const target = Math.atan2(dx, dz);
const delta = Math.atan2(Math.sin(target - state.heading), Math.cos(target - state.heading));
state.heading += delta * (1 - Math.exp(-20 * dt));
}
const wasAirborne = state.y > 0;
state.vy -= 22 * dt; state.y += state.vy * dt;
if (state.y <= 0) { state.y = 0; state.vy = 0; }
return wasAirborne && state.y === 0;
}
