Redline Rider — ride the line, feed the eye.
"Neon downhill survival, watched by an AI that learns how you ride." · "One line. One eye. No brakes."
Inspiration
We wanted an endless runner that didn't just get faster — one that got personal. Most infinite games escalate on a fixed curve; the mountain never cares who's riding it. We asked a different question: what if the game watched you, learned your habits, and set traps for the rider you actually are? That became the Overseer an adaptive presence rendered as a giant eye in the sky that studies your style and answers it. The downhill-biking skin came from wanting speed you earn through clean riding rather than speed you're handed.
How we built it
The whole game is a single index.html Three.js0.160` over an importmap, no build step, no framework. That constraint was a feature: anyone can open the file and read the entire game top to bottom.
-Rendering & feel:** procedural chunked terrain from seeded noise, a posable rider rig built from primitives, day→night mood lerp, bloom on desktop, and a 3-tier adaptive-quality governor that degrades under sustained $>21\text{ms}$ frames so mobile stays first-class.
Physics:** a Rapier (WASM) character-controller layer owns "you cannot pass through things," while an arcade layer owns forward momentum. Speed ramps toward a ceiling of $v_{\max} = 88\ \text{m/s}$, earned in the last third only through perfect landings and clean streaks.
The Overseer:** a separate
overseer-core.mjsmodule scores your run — greed, clean technical play, quick deaths — and biases toward Trickster bait, Judge traps, or mercy, all deterministic per seed so behavior is testable.Backend:** Vercel serverless functions + Upstash Redis. A global leaderboard, server-backed accounts (coins, owned/equipped skins) that survive cache clears and device changes, and a coin economy. Coins are earned as $$\text{coins} = \lfloor \text{dist} \rfloor \cdot 1 + \text{topCombo} \cdot 3$$ and the leaderboard ranks by $$\text{rankScore} = t_{\text{run}} + 0.25\,t_{\text{hang}}$$ so hang time rewards style without breaking older entries.
Content:** a 21-rider / 15-bike skin catalog, each recoloring a shared in-game rig, bought and equipped through a 3D marketplace.
What we learned
Deployed" is not "works."** Our hardest bugs — skins equipping in Redis but not rendering, a leaderboard that looked frozen — passed every unit test. Nothing replaced driving the real production site through a headless browser and reading the actual rig.
The moment coins have value, every quirk becomes an exploit.** A stuck-bike soft-lock that was merely annoying started minting fake 9-minute leaderboard runs. We learned to gate the server against anything the game can't physically produce:
$$\text{reject if}\quad t_{\text{hang}} > t \;\lor\; \text{dist} > 90t \;\lor\; (t > 90 \land \text{dist} < 8t)$$
- Identity is subtle. A case-sensitive name split one player into two ranks (#9 vs. #43); a failed sign-in fetch could blank a real account. Small assumptions, real data loss.
Challenges we faced
One 3000-line file, four contributors. Merge conflicts were constant; small PRs and fast rebases were survival, not style.
Making equipped skins actually appear in-game** turned out to be three bugs deep — stale caches, back-navigation restores, and a rig built once at boot. The fix was rebuilding the rig from the equipped loadout on every meaningful event, plus an auto-updater so stale tabs self-heal.
A copyright rename mid-flight** ("Downhill Rush" → Redline Rider) while live players had sessions bound to the old URL — solved by keeping both domains attached so nobody got signed out.
Keeping mobile first-class** against a physics engine, bloom, and a live AI all fighting for a sub-21ms frame budget.
What shipped is a game that reads your line, remembers your mistakes, and races back.piration
What's next for Redline Rider
Real economy, real ownership. We're moving coins from "a number the browser reports" to server-authoritative, then opening a top-up rail. The plan we're most excited about is crypto-native purchases: the player's wallet signature does double duty as both payment and identity — sign in with your wallet, buy a coin pack in USDC with a single signed transfer, and a server verifies it on-chain before crediting (with replay protection so a tx can never be redeemed twice). No card fields, no chargebacks, and the wallet address becomes stronger auth than any email link. Coins stay off-chain for instant, gasless spending in the shop; only the top-up crosses the chain.
Harden identity. Wallet sign-in (SIWE-style) replaces email-as-weak-key and closes the account-takeover gap we found during our own deep check. Runs get signed so the leaderboard trusts submissions cryptographically — the plausibility gate $$\text{reject if}\quad t_{\text{hang}} > t \;\lor\; \text{dist} > 90t \;\lor\; (t>90 \land \text{dist} < 8t)$$ stops what the game physically can't produce; signatures stop everything else.
Seasons as a first-class loop. We just ran our first reset (Season 01) and archived the old board. Next: recurring seasons with their own leaderboards, a permanent Hall of Fame for past champions, and season-exclusive skins so the mountain always has something new to chase.
Let the Overseer truly evolve. The adaptive AI already reads greed, clean play, and quick deaths per run. We're wiring its evolution loop to an LLM auditor that tunes trap frequency and mercy between seasons the eye doesn't just watch one run, it learns the whole playerbase over time.
More mountain. Coin pickups scattered on the descent, a daily deterministic seed for head-to-head runs on identical terrain, and ghost replays of the top times so you're always racing someone — even the eye.
And underneath all of it: keeping the whole thing a single readable file that stays first-class on a phone, no matter how much we add.
Built With
- css3
- git
- glsl
- google-fonts
- html5
- javascript
- localstorage
- node.js
- rapier
- three.js
- upstash-redis
- vercel
- vercel-analytics
- web-audio-api
- webassembly
- webgl
Log in or sign up for Devpost to join the conversation.