HOW THE PALACE WAS WIRED
Every cabinet at ARCADE '84 has a service manual taped inside the coin door. This is ours: what the site is, how each trick works, and which parts you should unscrew and take home.
1 ¡ The Concept
ARCADE '84 is a fictional 1984 arcade off Route 95 in Ruby Junction, Nevada â dark since a billing dispute on New Year's Eve 1992, now reopening. The design school is synthwave / outrun: the 1980s as remembered by neon â deep purple-black voids, magenta and cyan light, chrome-lettered logos, a striped sun forever setting over a perspective grid.
Everything hangs on committing to the fiction. The palette is five values (void, magenta, cyan, sunset gold, lavender ink). The type is two faces pushed hard: Orbitron at weight 900 for chrome display work, Press Start 2P for everything that would be silkscreened on a cabinet. And the centerpiece is a real, playable house game â because an arcade site you can't play is a lobby, not an arcade.
2 ¡ The Techniques
THE ANIMATED BACKDROP (CANVAS)
One full-screen <canvas>, fixed behind everything, redrawn each frame: a gradient sky, a twinkling starfield (each star gets a random phase and speed fed into a sine wave), and the rushing grid. The horizontal grid lines are the trick â depth is faked by easing each line's position with a power curve, so lines bunch at the horizon and accelerate toward you:
var p = (i / n + off) % 1; // off scrolls with time
var y = horizon + depth * Math.pow(p, 2.7);
bx.globalAlpha = 0.12 + 0.7 * p; // fade in from the horizon
The striped sun is drawn on a small offscreen canvas: fill a gradient circle, then punch out the scanline stripes with globalCompositeOperation = 'destination-out'. The stripe positions are a function of (j + fr) / 9 where fr loops 0â1, so the pattern drifts downward forever without a visible seam.
THE CRT, ENTIRELY IN CSS
A fixed, pointer-events-none overlay carries a 3px repeating-linear-gradient for scanlines, a radial-gradient vignette on its ::after, and a 7-second keyframe animation that dips its opacity for single frames â the tube "breathing." Headings get chromatic aberration with two offset text-shadows, one per phosphor:
.aberr{ text-shadow:-2px 0 rgba(255,43,214,.55),
2px 0 rgba(0,240,255,.55); }
Chrome lettering is a hard-stop metal gradient clipped to the glyphs with background-clip:text. Because a text-shadow would show through transparent fills, the glow is applied with filter: drop-shadow() instead â that one swap is the difference between chrome and mud.
AN AIRTIGHT GAME LOOP
Grid Volley is Pong-as-endurance: every return scores, one miss ends the run. Two rules keep it bug-free. First, the ball never tunnels through a paddle, because collision is a swept plane check â it compares last frame's position against this frame's, so no frame-rate spike can jump the ball past the paddle:
if (ball.vx < 0 && prevX >= plane && ball.x <= plane) {
if (overlapsPaddleY()) { reflect(); }
}
Second, there is exactly one requestAnimationFrame loop on the page, it clamps dt to 33ms, and a visibilitychange listener cancels it when the tab hides and restarts it cleanly when the tab returns. No leaked loops, no ball teleporting after you switch tabs.
NEON SIGNS THAT FLICKER ON
Section headings start dim. An IntersectionObserver adds a .lit class the first time each one scrolls into view, which fires a keyframe animation that stutters between dark and full glow at uneven percentages (6%, 8%, 12%, 15%âĻ) â the exact rhythm of a real tube warming up. Under prefers-reduced-motion, the animation is skipped and every sign simply renders already lit: reduced, not removed.
HIGH SCORES THAT SURVIVE
The Hall of Fame merges eight seeded "recovered from battery-backed RAM" legends with the player's real runs from localStorage, sorts, and keeps the top eight. Initials are sanitized to three characters of AâZ0-9 before they ever touch the DOM, and every storage call is wrapped in try/catch so private browsing can't throw.
3 ¡ How It Was Made
Built by Claude (Fable 5) writing vanilla HTML, CSS, and JavaScript by hand â no frameworks, no build step, no libraries. Two files, one canvas, one game. It's part of a 25-site showcase exploring how far hand-written front-end can go; the full floor is at fable-25.pages.dev.
4 ¡ Steal This
- The power-curve grid. Any "infinite floor" is ~15 lines and
Math.pow(p, 2.7). Change the exponent to change how hard the ground rushes at the viewer. - Punch-out stripes.
destination-outon an offscreen canvas cuts clean holes in anything â striped suns, window blinds, glitch bars â without masking headaches. - The swept collision check. Compare previous and current positions against a plane instead of testing overlap. Ten minutes of work, and fast-moving objects stop ghosting through walls forever.
- Flicker at uneven percentages. Real neon doesn't stutter on a beat. Keyframes at 6/8/12/15/21% read as electricity; keyframes at 10/20/30% read as a metronome.
- Cancel your rAF on
visibilitychange. One listener, and your page stops burning battery in background tabs â and your game can't fast-forward when the tab wakes up.
SERVICE MANUAL v1.0 ¡ RUBY JUNCTION AMUSEMENT CO.
RETURN TO THE FLOOR ¡ THE FULL SHOWCASE