Sled
Sled is a downhill racer. The player pulls a slingshot back and lets go, and the sled launches down a snowy track. On the way down, the player steers and jumps past rocks, collects coins, and races to the finish gate. A rock stuns the sled or wipes it out.
The game comes from threejs-game-template, where it runs on that template’s own engine. Its code there is the specification for the behaviour and the numbers; this port rebuilds the game on this engine’s components rather than copying that code.
The first milestone is a playable slice of level 1: the launch, the slide, the rocks, the coins, the finish, and a HUD with a retry. Sled runs on the engine plans the slice and lists its layers.
The game lives in games/sled. Run it with pnpm dev:sled from the repository root. It opens on the run scene: level 1, with the rider on the sling at the start line.
Level 1
Section titled “Level 1”A level is a JSON file in src/levels, in the track level format. Its track is a list of points, each with the lane’s width and its zone, snow or ice. The game builds the engine’s Track from them, one lane plus a 3 m snow shoulder on each side wide, so the ride stops at the fence.
The drawn surface is a cross-section laid every half metre: the lane, the shoulders, a 1.5 m fence and 60 m of hillside that climbs 10 m away from the track. Loose snow lies on the lane and deepens toward the fences, and the wind carves ridges into it without ever raising it above its authored depth. An ice stretch is swept bare, paints paler and shines more. Past the hillside, the engine’s terrain carries the ground on into mountains that reach the horizon: snow lies on whatever faces up, the steep faces show stone, and the far peaks fade into the sky’s lowest colour. The trees are the level’s own, plus nine rows across the hillside around them and five more past it on the terrain, at 62, 78, 96, 116 and 136 m, the same on every device. The engine’s Lighting lights the run with the Dusk look, its sun low and warm ahead of the run. The painted dawn panorama is drawn behind it as the sky, turned so its sun stands on the look’s; Dusk’s own image is the light every surface reflects.
The launch and the ride
Section titled “The launch and the ride”The rider, a penguin, stands 6 m down the track between two sling posts, with the band strung through it. S pulls the sling back, to a full pull in 0.8 s, and W eases it off, down to the half-draw. A and D aim the rider across the lane, up to 2.5 m either side of the centre, and the posts stand half a metre outside that reach. Space or Enter fires. The first key draws the sling halfway at once, so a bare Space launches from the half-draw. Level 1 climbs for its first 24 m, and a launch from the half-draw stops short of the crest, as it did in the old game, where the run ends on a stall. The rider trails the pull and the aim, so the sling feels weighted, and the pull is drawn only: the rider’s place on the track does not move back.
The launch speed comes from the pull asked for, not the one the rider has eased to: 1.5 m/s at none, 4 m/s at the half-draw, and 6.5 m/s at a full pull. It sets the engine’s TrackMover going with launchTrackMover. From there A and D steer and Space jumps, as the mover does for any rider, under gravity at 1.6 times Earth’s, the old sled’s pace. The snow under the sled costs it speed, through the track’s surface friction: 1.14 per second for each metre of snow, so about 0.04 per second on a snow lane, 0.4 per second at a shoulder’s outer edge, and nothing on ice. Drifting off the fast line costs speed as it happens. The rider rolls into the steer, up to 0.3 radians. On a touch screen, a stick at the bottom left pulls, aims and then steers, and the button at the bottom right fires and then jumps.
The camera is the engine’s chase camera along the track, at a 52 degree lens.
Rocks, coins and the finish
Section titled “Rocks, coins and the finish”Everything the rider meets is an engine TrackTrigger, a region in track coordinates. The level lists each kind under triggers: slabs, rocks and boulders for the three tiers of rock, and pickups for the coins. Level 1 has seven coins, a slab across the middle at 39 m and a boulder on the left at 60 m. The old game’s level 1 had no rocks; this slice adds two so that it shows every hazard.
A rock’s box is its tier’s size in metres, across, up and along: a slab 4 by 0.3 by 1.4, a low rock 4 by 0.5 by 1.4, and a boulder 3 by 3 by 2.2. Each hits at 0.8 of that size, so a near miss reads as a miss. Along the track each is at least a metre deep, so a rider at 30 m/s cannot pass between two steps. Each region is padded by the sled’s half metre across and along. A jump clears a slab or a low rock once the rider rises above the rock’s hit height.
Only the entry is a hit. The first hit halves the speed and stuns the rider for 0.8 s, and the rider blinks 8 times a second while stunned. A second hit inside the stun wipes the run out, and so does any touch of a boulder. A wipeout stops the sled where it is.
A coin floats 0.6 m over the snow, spins, and reaches 0.6 m across, 0.7 m up and 0.5 m along from its middle, plus the sled’s half metre. The rider who enters it takes it into the Wallet on the rider, the coin sound plays, and the coin leaves the world. A coin lifted over a rock pays only a rider in the air.
The finish is a gate at finish.at, and its region runs from there to the track’s end across the whole width. Crossing it finishes the run and stops the sled.
The rules are sled’s own system in src/ride/course.ts, which runs after the engine’s move has marked the triggers. test/ride/course.test.ts replays the old game’s obstacle, stun and coin tests in the harness.
The run
Section titled “The run”A run is an engine Round with ready set. It waits while the rider sits on the sling, and the sling’s fire starts it. The run ends in one of three ways:
- Finished: the rider crosses the finish gate, and the round is won.
- Wiped out: two hits inside a stun, or any boulder, fail the round with the reason
wiped. - Out of steam: the rider stays under 2 m/s down the track for more than 1.5 s, and the round fails with the reason
crashed. Only the speed along the track counts, so a sled jumping in place still stalls.
Each ending stops the sled. The finish sound plays on a finish, and the crash sound on either failure.
The HUD shows the run’s coins at the top right, read from the rider’s wallet through useWallet(), and the speed in km/h under them. The round screen names the ending, the coins this run took and the total banked, and its button retries the level. Every ending banks the run’s coins into the save’s wallet, so a crash keeps them and the total survives a reload. test/ride/run.test.ts replays the old game’s run director tests.
Where the systems run
Section titled “Where the systems run”The sling and the lean are sled’s own systems in src/ride. The sling runs between the engine’s input and its move, so it takes a jump pressed at the line as its fire before the move can jump; the lean runs after the move, on the steer the move used. test/ride replays the old game’s sling and lean tests in the harness.