Cheatsheet
Every key, flag, script and figure on one page, for someone who has already read the documentation. The full text lives on the site.
Controls
| Input | Action |
|---|---|
W A S D or arrows | Steer |
F or Shift (browser) | Boost |
Space | Fire pulse cannon |
Q / E | Barrel roll |
P | Pause / resume |
M | Mute toggle |
C (browser) | CRT scanline overlay |
V (browser, title screen) | Open a two-pilot split-screen round |
Enter | Launch / relaunch |
Esc | Menu / quit |
Ctrl+C | Quit immediately (terminal) |
Thumbstick / FIRE / BOOST | Touch: steer / fire or confirm / boost |
Left stick / A / B | Gamepad: steer / fire or confirm / boost |
| Triggers | Gamepad: barrel roll, left and right |
On the name entry screen the same keys spell a name instead of steering: up and down walk the character under the cursor through A-Z, 0-9 and a space, left and right move between the three slots, and Enter files the score. Esc files it too, under whatever name is showing, because the score was earned before the screen came up.
Press-not-hold keys are P, M, Esc, Q and E. They fire once per press and take a short deadzone after a hold.
A gamepad has to report the standard layout before it drives anything, and its stick takes the same dead zone and eight sectors the on-screen thumbstick does. Any pad plugged in can fly the run, and a second one alongside does no harm. In a split-screen round the whole pad flies pilot 1, stick and trigger both.
CLI
space-rider Start in normal mode
space-rider --debug Open the debug scenario menu
space-rider --mode <mode> Start a specific debug mode directly
space-rider --help Show help
Browser URL parameters
index.html?debug Open the debug scenario menu
index.html?mode=chaos Start a specific debug mode directly
index.html?mode=mines Mine Field
index.html?mode=orbs Orb Harvest
index.html?mode=obstacleCollision Collision Course
index.html?mode=mineCollision Mine Sweeper
index.html?versus Open a split-screen round
Split screen (browser)
Two pilots at one keyboard, each flying their own run in half the grid. V on
the title screen opens a round, or index.html?versus goes straight into one.
| Control | Pilot 1 | Pilot 2 |
|---|---|---|
| Steer | W A S D | I J K L |
| Fire | Space | Enter |
| Boost | F | ; |
| Barrel roll | Q / E | U / O |
P pauses the round and M mutes it from either hand, and the mute carries
into a round when one opens and into its rematch. Esc leaves, and Enter
starts a rematch once both pilots are down, on a window still wide enough to
open one. The arrow keys and Shift steer
nobody in a round, because two players cannot agree whose they are.
Both pilots launch into the same tunnel, from one seed drawn when the round opens, so the opening field is the same in both halves. The fields drift apart from there, because each pilot reaches a given depth at their own speed. Scores are separate and the higher one takes the round; a round never reaches the leaderboard, since the table has one name to a row.
A round needs 45 columns a half, so 91 columns of grid. The key is only offered on a window wide enough for one. A round dragged narrower than that keeps flying, with each half shortening its score, distance and shield readings to whatever fits, and the rematch waits for the window to come back.
Debug modes
| # | Mode | Flag / param | What it isolates |
|---|---|---|---|
| 1 | Mine Field | mines | Pure evasion |
| 2 | Orb Harvest | orbs | Collection |
| 3 | Collision Course | obstacleCollision | Obstacle impacts |
| 4 | Mine Sweeper | mineCollision | Mine collisions |
| 5 | Chaos Protocol | chaos | Everything, permanent boost, auto-fire |
Debug runs never record a best score.
Numbers
| Thing | Value |
|---|---|
| Obstacle collision | 25 shield |
| Mine collision | 35 shield |
| Mine hit points | 5 pulse hits |
| Orb pickup | 10 shield, 500 points |
| Obstacle destroyed | 200 points |
| Mine destroyed | 500 points |
| Powerup drop chance | about 1 in 3 mines shot down |
Shield Regen + | 25 shield |
Rapid Fire ! | 10 seconds, 3x cadence |
Slow Motion ~ | 5 seconds, half world speed |
| Combo window | 2 seconds, caps at COMBO x8 |
| Barrel roll | 0.5 seconds invulnerable, then a cooldown |
| Warp step | every 60 seconds, banner for 2 seconds |
| Asteroid field | every 150 seconds of tunnel, open for 15, 70 rocks |
| Boss encounter | every 180 seconds of flying, 3 second warning |
| Boss hit points | 20 pulse hits |
| Boss approach | 200 units in, 14 units a second |
| Boss return fire | a shot every 1.5 seconds, 12 shield each |
| Boss collision | 50 shield, and it pays nothing |
| Boss destroyed | 5000 points, 3 pickups, one of each kind |
| Grid floor | 60 columns by 20 rows |
| Split-screen floor | 45 columns a half, 91 of grid |
| Leaderboard | top 10, three characters a name |
| Replay ghost | 10 path samples a second, 10 minutes of run |
| Detail ladder | 40 / 24 / 12 stars, full / 60% / 30% of a burst |
| Detail window | 30 frames; down under 24 fps, back up at 27.3 fps |
Scripts
npm run build # Compile TypeScript to out/
npm run start # Run the compiled game
npm run dev # Build and run in one step
npm run debug # Build and run in debug mode
npm run watch # Watch mode for development
npm test # Build, then run the test suite
npm run probe # Build, then run a measurement probe
Probes
npm run probe with no arguments lists what there is to measure, and which flags each probe takes. The probes that fly a shot take a grid and a build:
npm run probe -- seen-versus-kill
npm run probe -- column --grid 205x50 --build browser
npm run probe -- free-flight --passes 2
npm run probe -- versus-half --count 300 # seconds of game time to fly out to
npm run probe -- overlay-anchor # no grid, no build: it walks viewports
npm run probe -- glyph-tuning # no flags: it walks the font size range
A flag the named probe does not read is refused rather than discarded, so
npm run probe -- overlay-anchor --grid 80x24 exits non-zero instead of reporting a figure from a walk that never used the grid.
The table the rig checks against lives in test/probes/probes.mjs, and
test/probes.test.mjs reads it against the probes themselves: every probe takes exactly the flags listed for it, so a probe that stops reading an argument fails the suite rather than going on accepting the flag in silence. Every probe that calls the shared engagement is run there too, on one grid, one build and the smallest --count and --passes the rig takes, because reading a probe's argument list never reaches the calls the probe makes. What --count 1 narrows to depends on the probe: one placement for column, frame-rate and seen-versus-kill, a single frame for free-flight and drop-clip, which read the flag as frames, and a one-second flight for versus-half, which reads it as the seconds of game time to fly out to.
A probe reports; it never asserts. Every walk is seeded, so the same command gives the same numbers every time.
versus-half is the one probe that reports a width. The split screen gives each
pilot half the grid and the half carries the whole HUD, so the probe flies a seeded run out to twenty minutes, reads the score and the distance off it at six marks, and sweeps half widths for the narrowest at which SCORE, DIST and SHIELD stop overlapping. 45 columns is what holds every mark, which is the floor a round opens on.
glyph-tuning is the one probe that measures nothing: it rebuilds the figures the browser build's glyph centring quotes about itself, out of Courier New's 1229/2048 em advance and the page's own glyphInset. It also lists, at the foot of its output, the four figures in that tuning that needed a rasterizer and so are not rebuilt - each with the instrument that read it and what it concluded, which is the method published beside the number.
Test grids
The pulse cannon checks run at three sizes, because the hit test is not size-neutral:
| Grid | Why |
|---|---|
| 80x24 | What a terminal opens at |
| 60x20 | The floor a small browser window is clamped to |
| 205x50 | A full-screen window at the default font |
Terminal requirements
- 60 columns by 20 rows minimum
- 256-colour ANSI
- Unicode box-drawing and block elements
- Windows Terminal, iTerm2, GNOME Terminal, Alacritty, Kitty
Browser-only features
High score and leaderboard persistence, sound, the CRT overlay (C), light mode, touch controls, the two-pilot split screen (V), and a canvas-offset screen shake. The terminal build jolts the play area by a whole character column instead, and keeps a best score and a table for the session only.
The replay ghost and the detail ladder are in both builds and neither is stored: a ghost lasts as long as the session, and the ladder survives the run that measured it and is re-measured a second into every session.