First-Person Game Engine Template
FP Engine
A first-person movement kit with slide, mantle and bunny hop, tuned until it feels right.

Overview
FP Engine started as a question: what if the first-person gallery on this site became the seed of something reusable? The gallery proved that walking through a space is compelling on its own. It also meant hand-rolling physics, collision, character control and audio every time. So I rebuilt the parts worth keeping on Babylon.js and Havok, wrote the rest fresh, and ended up with a clean template for any first-person web game. Project Slayer is built on it.
Highlights
- Movement that feels tuned, not just functional. Asymmetric damping so stops are snappier than starts, coyote time, jump buffering, variable jump height, a landing dip, sprint FOV. The small stuff that separates “works” from “feels good.”
- Slide, slide-jump, bunny hop. Sprint plus crouch drops you into a momentum slide. Jump out of it, land with crouch held, and the next slide starts instantly at decayed speed, up to two chains before it resets. Fast in skilled hands, with no infinite-speed loop.
- Mantling. Jump toward a ledge and you vault onto it along a smooth arc, with an eye dip as you grab and an FOV squeeze as you pull over. Hold crouch as it finishes and you burst into a slide on top.
- Every input, day one. Keyboard and mouse, gamepad with analog movement, and touch with an analog joystick and auto-sprint at full deflection. Devices are interchangeable providers, so movement code never knows which one is driving.
- Sound that reacts. Footsteps are synthesized and timed to the head bob. The slide is a looping friction scrape whose pitch follows your speed.
- Mobile that actually runs. Its own post-processing preset, a pixel-ratio cap, smoothed touch look and a pointer-lock bypass.
What Was Hard
Slopes. Character controllers float above downhill surfaces because horizontal movement carries the capsule faster than gravity pulls it down, so “grounded” flickers. The fix was to cache the last valid surface normal for a quarter second, the same trick as coyote time applied to a different flickering boolean.
Bunny hop chains hid four bugs stacked on each other, and the speed only made sense once I understood how slide entry, jump boost, momentum grace and airborne velocity flooring compounded. Tuning the cap (two chains, fifteen percent decay each) was the line between expressive and broken.
Mantle detection used the capsule center as its height reference, which rises a metre during a jump and shrinks the valid window to a frame or two. Switching to feet height opened it right up.
How It’s Built
Babylon.js with Havok physics, in TypeScript. Every system implements the same tiny update-and-dispose interface, so the game loop walks a list without knowing what is in it. Input devices write into one shared snapshot. UI is HTML and CSS overlays. Audio is raw Web Audio rather than the engine’s, because I wanted control over the synthesis. Configs are frozen so tuning values can’t drift at runtime.
What This Demonstrates
Building even a small engine drags you into problems app work never surfaces: physics tick ordering, per-frame allocation budgets, platform-specific input, and systems that behave until they run together. The output is a template where anything built on it starts with movement that feels tuned, input that works on every device, and audio that reacts to the player.