TinyGames · how it works

Sunstrip

An arcade road racer. You accelerate on your own; braking and steering are the whole game. Reach a checkpoint before the clock runs out and it hands you more time.

Open index.html. No build step, no dependencies, no images.

sunstrip/
  index.html      markup
  style.css       the frame around the canvas
  js/engine.js    copied unchanged from Overdrive - the tenth game on it
  js/road.js      the projection, the track and the hill rule
                  - no pixels, no engine, no DOM
  js/sunstrip.js  the playable layer
  test-road.js    node test-road.js

There is no 3D here, and there never was

The road is a stack of flat horizontal slices going away from you. Each one is projected with a single divide:

p.screen.scale = cameraDepth / p.camera.z;
p.screen.x     = width / 2  + scale * p.camera.x * width / 2;
p.screen.y     = height / 2 - scale * p.camera.y * height / 2;
p.screen.w     = scale * roadWidth * width / 2;

That is the entire 3D engine. Everything else — hills, bends, cresting a rise and losing sight of what is beyond it — comes from three ideas, and two of them are easy to get wrong.

$ node test-road.js
47 passed, 0 failed

Curves are fake, and they are the double integral

The road never bends. Each slice carries a curve number, and while walking away from the camera the renderer accumulates a sideways offset — adding curve into a rate, and the rate into a position:

x     += drift;
drift += seg.curve;

Integrating twice is what turns a per-slice number into a road that actually turns. Add the curve straight into x instead and the road leans over without ever going anywhere — which looks like a bug in the artwork rather than a bug in the maths.

Hills hide things, and that is one comparison

Drawing near-to-far is not enough. A dip beyond a crest projects above the crest and paints straight over it, so the road turns inside out over every hill. The fix is to remember the lowest point drawn so far and refuse to draw anything at or below it:

if (seg.p2.screen.y >= maxy) continue;
maxy = seg.p2.screen.y;

The test builds a sharp crest with a dip behind it and first proves the problem is real — it counts the slices that genuinely project below a nearer one, and asserts there are some. Then it runs the painter and asserts every slice that survives sits strictly above the last. A companion test on flat ground confirms nothing is culled except what is below the bottom of the screen, which loses nothing because the next slice begins exactly where it ended.


The two things that make it feel like driving

Centrifugal force. A bend does not turn the car, it pushes it out of the corner, harder the faster you are going. Without it a curve is scenery. With it, a curve is the reason to lift. Hands off the wheel, a car at full speed drifts three-quarters of the way to the verge in half a minute.

The checkpoint clock. A lap at full speed takes about 74 seconds and there are four checkpoints, so a quarter lap is roughly 18.5 seconds of perfect driving. Each one pays 20 — so a driver who never lifts gains a second and a half, and everybody slower is losing ground. The first numbers paid 26 and the clock never threatened anyone; measured runs now end at about 110 seconds.

Traffic shunts you rather than stopping you: you keep some speed and get pushed back behind the car you hit. On a timer, a dead stop is a run ended by one mistake.


Track building

A course is a list you can read:

["right", "medium", "hard"],
["leftUp", "medium", "medium"],
["down", "long", "medium"],

Each stretch eases in, holds, and eases out, so bends and hills begin and end smoothly rather than snapping on. The tests check a bend starts near zero, reaches exactly the lock asked for in the middle, and never overshoots it.

Because the track is a loop, the last slice has to meet the first. Any leftover height is walked off over the final stretch — the test asserts the finished course closes back to zero within a millionth, and that no step appears in the road while it does. Without that, the player crests a hill at the join and drops through the floor once a lap.


Controls

Hold and move the pointer steer — position, not motion
Hold near the bottom of the screen brake
or A D steer
/ S / Space brake
R start over

Steering is where your thumb is relative to the middle, not where it moved. A thumb resting left of centre keeps steering left, which is what a wheel does and what a drag does not.


Performance

240 slices projected and painted, 46 cars: 0.013 ms a tick, 0.56 ms a frame to draw.


Things deliberately left undone