How it's made
A game with no image files · Marko Krulc · Slovenia
Rev Rush contains no image files at all. Its asset catalogue holds the app icon and nothing else — no sprite sheets, no textures, no atlases. Every rider, obstacle, coin and cloud in all 21 worlds is a character map in the source code, drawn pixel by pixel at runtime from a shared palette.
- 0image files in the game
- 177sprites as character maps
- 36entries in the shared palette
- 21worlds, each with its own music
What a sprite actually is
The rider is not a PNG. It is an array of strings, and a dictionary that says what each letter means:
static let palette: [Character: UIColor] = [
".": .clear,
"K": UIColor(red: 0.055, green: 0.075, blue: 0.114, alpha: 1), // outline
"R": UIColor(red: 0.937, green: 0.165, blue: 0.075, alpha: 1), // bike red
"B": UIColor(red: 0.020, green: 0.329, blue: 0.945, alpha: 1), // suit blue
...
]
static let riderFrame1: [String] = [
".....................KKKKK............",
"....................KHHHHHKKK.........",
"...................KHHHHHHHHHK........",
"...................KHHHhKKKKK.........",
...
]
A drawing routine walks the rows, looks up each character in the palette and fills one square per character. That is the whole pipeline. There is no import step, no texture packer and no build tool between the art and the screen.
Why do it this way
Size. 21 worlds of art weigh what their source code weighs. The app downloads in seconds and then plays fully offline, in 20 languages, with no network call needed for anything except syncing a score to the leaderboard.
Recolouring becomes free. Because the art is characters plus a palette, changing a colour means changing the palette, not repainting an image. That is what makes the garage possible: 51 colours across 5 zones of the vehicle, and the bike repaints while your finger is still on the swatch. Shade and highlight are derived from the one colour you pick, so no combination can come out flat.
Nothing can drift. There is no second copy of the artwork to keep in sync — the code is the artwork.
The website is the same program
The motorbike you scroll past on the front page is not a drawing of the game and not a recording of it. An exporter reads the game's own Swift source — the character maps, the palette, the ground tiles, the skies, the weather, the sky events and the level names — and writes them out as JSON. The browser then runs the same drawing algorithm on that JSON.
Matching is not a target that gets approached by careful redrawing. It is a consequence of the input being identical. When the bike changes in the game, re-running the exporter changes it here.
You can read the exported data yourself: /data/sprites.json is the 177 character maps, /data/palette.json is the palette they are read against. The claim on this page is checkable, which is the only reason it is worth making.
Three implementations, one algorithm
The same drawing routine exists three times: in Swift for the game, in JavaScript for this website, and in Python as an independent reference used to build the icon and the sharing image. A separate page in this site draws the individual parts — rider frames, ghost, battlement, barrel, ground tiles — so the browser's output can be held against the Python one.
The sharing image is not a screenshot either. It is composed from the exported JSON with the same palette and the same sprites: sky in bands, wave silhouettes, ground, rider and the title in the game's 5×7 pixel font. A screenshot would depend on a window size and a moment; this does not.
The favicon is not drawn again either — it is the app icon, scaled down with nearest-neighbour sampling, because bilinear scaling blurs a pixel icon at exactly the 32-pixel size where it matters. The tab and the App Store have to show the same picture, or they are two products with one name.
The rest of the site
The page is static HTML with no framework, no bundler and no
node_modules. Audio is 1.4 MB of WAV that is not
downloaded at all until you switch sound on, and then only one track
at a time, as you enter each world. The leaderboard on the front page
reads the same database the game writes, and fetches nothing until
you press the button.
Even the machine-readable files are generated rather than written: /facts.json takes its numbers from the game's source, and the build fails if a number cannot be found there any more. A hand-copied fact would eventually disagree with the game — and it would disagree exactly where somebody quotes it.
Written by Marko Krulc, who makes Rev Rush alone in Slovenia — design, code, pixel art, music and this website. More at Info, or on X.
You are welcome to quote this page with attribution to revrush.net. Numbers for press use are on the press page.
The text of this site may be quoted with attribution to revrush.net.