A puzzle platformer where the platforms are your function. Type f(x), and the
curve becomes a road; a rider follows it, building the momentum needed to clear the
gaps and reach the finish line.
Play it live: https://function-platformer-xdvj.vercel.app/
Or open index.html in a browser — no build step and no dependencies, so the file
works straight from disk.
- The curve is the road. Polynomials, trig, roots, exponentials — anything the
built-in parser accepts (
+ - * / ^, implicit products like2xor3sin(x),sin cos tan sqrt abs exp ln log10 floor ceil min max, constantspi e tau). - The level is a grid of fixed-pixel cells (16×9 cells of 60 px), of three kinds:
- Path cells — where the function should be traced; the curve is rideable here.
- Gap cells — places on the grid that are not on the optimal path: the curve is cut inside them (it cannot be used as road), but the kart may fly through. Jumps happen here, carried by momentum.
- Filler cells — fill all remaining space; they cut the curve and crash the kart on contact.
- Momentum jumps. Launching off a rising lip throws the kart upward; it detaches from crests on its own when fast enough (curvature vs. gravity).
- Runner levels. Level 1's rider is a person under full player control: nothing
moves without input. Run with ← / → (or A / D), jump with Space / ↑ / click, with
a little mid-air steering. The intended solution is
floor(x) + 1: the floor function draws discrete platforms that climb to a finish line on higher ground than the start, and the runner must jump up each successive platform. Walls and ceilings bonk the runner instead of crashing them. - Fillers constrain the solution to one or a few shapes: level 1 wants a step
function aligned to its staircase (wrong offsets and zooms fail, and no climbing
straight line wins — verified by search); level 2 falls to a plain downhill line;
level 3 needs a launch ramp (no line works); level 4 needs a tilted wave (no
line, pure sine, or parabola works); level 5 is an open sandbox. Maps were
generated from verified winning runs (
gen.js, historical) and re-verified. - Zoom via canvas limits. The plot window is
0 ≤ x ≤ x max,0 ≤ y ≤ y max(y = 0 at the bottom). Changing the limits rescales the curve only — the cell grid and the kart keep their pixel size, so the same formula gets steeper (and faster) as you shrinky max.
index.html— UI, rendering, game loop.engine.js— expression parser, terrain sampling, kart physics, level definitions. Shared between the browser and Node.test.js— headless checks: parser behavior, every level's hinted solution wins, and the filler constraints actually exclude the trivial function families. Run withnode test.js;node test.js searchgrid-searches solution families (used to tune the levels).