Skip to content

Third-person (interactive)

An actual playable character. Click the demo, then WASD to move (relative to the camera), drag to look around, Space to jump, Shift to run. A follow camera trails behind the capsule.

Click · WASD move · drag look · Space jump · Shift run

Loading physics…

Movement is camera-relative, exactly like the snack-dash template: the keyboard and the camera yaw are combined into a world-space move vector, which is fed to the controller as its custom “forward” axis.

// World-space move vector from WASD + camera yaw (fwd = W/S, side = A/D).
const sin = Math.sin(camYaw), cos = Math.cos(camYaw);
const mx = fwd * sin - side * cos;
const mz = fwd * cos + side * sin;
const moving = Math.hypot(mx, mz) > 1e-3;
if (moving) controller.setForwardDirection({ x: mx, y: 0, z: mz }); // normalized
controller.setMovement({ forward: moving, run: shiftHeld, jump: spaceHeld });
controller.step(dt);
world.step(dt);

The follow camera trails the capsule each frame:

const p = controller.currPos;
const target = new Vector3(p.x, p.y + 0.6, p.z);
const off = new Vector3(
-Math.sin(camYaw) * Math.cos(camPitch),
Math.sin(camPitch),
-Math.cos(camYaw) * Math.cos(camPitch),
).multiplyScalar(7);
camera.position.lerp(target.clone().add(off), 1 - Math.exp(-dt * 12));
camera.lookAt(target);