One button, no throttle. You hold to tuck and release to stand, and that is the entire control scheme — every metre per second you have came out of the timing of those two moves against the shape of the ground.
The one line it all comes from
A rider on a curved track is a bead whose centre of mass sits a variable leg
length L above the contact point, along the track normal. Pushing the legs
out does work against the normal force N = m(v²κ + g cosθ); raising the centre
of mass costs m g cosθ per metre of it. Subtract, and everything that is left
over goes into speed:
ΔKE = N·ΔL − m·g·cosθ·ΔL = m·v²·κ·ΔL ⇒ Δv = v · κ · ΔL
Three consequences fall straight out of that, and they are the whole game:
- Curvature is the currency.
κ = 0means standing up buys you nothing. The loop has a stretch halfway round where the roller envelopes pinch shut and the ground goes quiet; you can pump as hard as you like through it and the trace stays flat. Every rider discovers this stretch the same way. - The sign flips.
κis signed — positive in a trough, negative over a crest. The same extension that pays you in the dip charges you on the rise. Get the phase backwards and the legs are a brake, which is exactly what the anti-pump pilot does in testing: dead in eleven seconds. - It is multiplicative. Gain scales with the speed you already have, while gravity’s bite on a climb does not. So there is a floor below which no amount of correct pumping recovers, and the demo says so plainly instead of letting you trickle to a halt wondering.
What the demo shows
- Coach lines (
C) tint the surface by the sign and strength ofκ— teal where the geometry pays you to stand, amber where it pays you to tuck. Turn them off once the shape of the ground is doing the telling. - The load meter is
Nin g. Extending is a push against it, and past the ceiling you physically cannot do it — which is why the skill is pre-loading, starting the stand before the trough loads you up rather than at the bottom of it, where your legs are already carrying four and a half g. - The trace is the speed the legs are adding or taking away, live. It is the fastest way to feel that the stroke wants to be centred on peak curvature, not started there.
- Airtime happens when
v²κ + g cosθgoes negative and the track can no longer hold you round a crest. It looks fast and it is slow: the legs earn nothing in the air, and landing costs you the whole normal component of your velocity. Absorbing hard is what keeps the wheels down — retracting pulls the centre of mass down relative to the track and buys back normal force, which is whyL̈is in the load term and not just decoration.
Reuse
src/pump-track.js is a framework-free ES module that draws nothing:
createTrack({ length, terms })→{ length, wrap, sample(x), height, slope, curvature }. The profile is a sum of amplitude-modulated harmonics, so the loop closes exactly andf,f′,f″are all analytic. That last part is not fussiness: the pump reads curvature directly, and a finite-differencef″leaks numerical noise straight into the energy budget as free speed.createRider(track, opts)→{ state, update(dt, input), options }. Input is{ crouch: bool }, or{ legTarget: 0..1 }/ a bare number for an analogue axis, so a trigger or a scripted pilot drives it the same way.stateexposesx, y, v, leg, L, airborne, load, pumpAccel, legRate, laps, distance, lastLanding— enough to render it however you like.pumpAdvice(track, x, speed)is the coach’s answer for any point: positive means extend, negative means tuck.
Tuning knobs that actually change the feel: legMin/legMax set the stroke
length and therefore the ceiling on gain per roller; legAccel sets how much
crest you can absorb before you get launched; maxLoad is what caps top speed,
because in a tight enough trough at enough pace the legs simply lock.
Gotchas
- Sub-step the update. The pump term multiplies leg rate by curvature, so
a long frame at the bottom of a tight trough integrates a visibly wrong amount
of energy.
update()fixes its own 4 ms sub-steps; don’t unpick that. - Curvature is signed and the renderer must not “fix” it. The interesting half of the mechanic is the negative half.
- The full work integral also carries an inertial part,
(L̈·L̇)/v. It is dropped on purpose: over any closed leg cycle it integrates to zero, so it can only contribute jitter and a singularity asv → 0. - Roller wavelength and leg speed are coupled. Make the rollers too short and the legs saturate at the inflection points and sit still exactly where the curvature peaks — the stroke has to be able to span a half-wavelength or the mechanic quietly stops paying. That was the first three tuning passes.
demo/bundles its own copy of the module (self-contained by contract). If you touchsrc/, re-copy it intodemo/.

