TinyGames · how it works
Ride the course. Pedal for speed, and the ramps will throw you if you are quick enough. Level out before you land, or you will not.
Open index.html. No build step, no dependencies, no images.
spokes/
index.html markup
style.css the frame around the canvas
js/engine.js copied unchanged from Overdrive - the nineteenth game on it
js/bmx.js the terrain, the launch criterion and the landing
- no pixels, no engine, no DOM
js/spokes.js the playable layer
test-bmx.js node test-bmx.js
The easy way to write riding is to set the bike's height to the terrain's height every frame. It works perfectly and the bike never jumps. It pours itself over a crest like water, at any speed, and no amount of ramp will launch it. Players read that as the ramp being broken.
There is no rule here that says "this is a ramp". Following a curve of curvature k at speed
v needs a centripetal acceleration of v²k, and gravity can supply at most g·cos(slope)
in that direction. When the first exceeds the second, contact is lost:
function staysOnGround(course, x, v) {
const k = course.curvatureAt(x);
if (k <= 0) return true; // a dip holds you in, at any speed
return v * v * k <= Physics.GRAVITY * Math.cos(course.angleAt(x));
}
That one comparison is why the same ramp launches you at speed and holds you at a crawl.
$ node test-bmx.js
51 passed, 0 failed
The tests take the same crest and ride it at a range of speeds: below the threshold the wheels stay down, above it they do not, and a sharper crest throws you sooner. Then they confirm that no speed at all — up to 4,000 units a second — can launch a bike off flat ground or out of a dip, because the curvature has the wrong sign.
The bike got airborne exactly zero times over the whole course. The criterion was right; there was simply never enough speed to satisfy it. Three separate causes, found in order:
The terrain was too steep for the power. A pedal of 240 against a gravity of 620 means any slope past about 0.4 radians decelerates you faster than you can drive. The bike arrived at every ramp doing 25 to 64, against launch thresholds of 116 to 306.
The ramps were taller than they were wide. A tall narrow ramp reads well and plays badly: it costs more speed to climb than its lip can ever give back. They are wider than they are high now.
And then the real one: nothing but a person could pedal the bike. Keys and touch are both polled, so every tick overwrote the throttle — a bot holding it flat out coasted to a standstill. The tell was unmistakable once measured: on perfectly flat ground with the pedal down, terminal speed was 25, the clamp floor, against a predicted 506.
That is the third game in this collection to hit the same fault. The control sources are separate here from the start: keys, touch, and an autopilot channel, combined once a frame.
A trick only scores if you ride away from it, and judgeLanding compares the bike's angle to
the ground's angle where it touches down.
That has a consequence that took a while to see. You launch off an up-slope and land on a down-slope, so completing exactly one turn is not enough — you arrive a radian out and go down. Three separate jumps in testing completed a full rotation and crashed every time, spinning 6.56 radians when the landing wanted more.
A rider has to over-rotate to meet the slope they can see coming. Once a test bot predicted the landing point and aimed at the ground angle there, it landed one: 1.28 seconds of air, 12.16 radians — nearly two full turns — ridden away cleanly.
Only the two biggest ramps give enough hang time for that. Everything else is a jump you level out of.
Half a rotation is worth nothing, deliberately. Three-quarters of a flip is not a trick, it is a crash in progress, and paying for it would reward starting a rotation you cannot finish.
Same course, same throttle, differing only in what happens between take-off and landing:
| crashes | time | |
|---|---|---|
| no air control at all | 6 | 27.1s |
| levels out before landing | 0 | 11.5s |
| → / D | pedal — and in the air, rotate forward |
| ← / A | brake — and in the air, rotate back |
| R | new ride |
On a touch screen the right half of the glass is one and the left half the other, tracked per pointer so you can hold both. The same pair of controls does both jobs, which is what makes a jump feel like a continuation of the run-up rather than a mode change.
The speed bar carries a red mark showing the launch threshold for the ground just ahead — so you can see whether the next ramp will throw you. Without it the criterion is invisible and the game feels arbitrary.
bmx.js.Advertisement