← Work

Hotfix

The arcade cabinet on this site. A maze game rendered live onto a curved CRT.

Date
2026
Kind
This site
Stack
TypeScript, three.js, Canvas 2D, Astro

The problem

A portfolio should be readable in thirty seconds, but a list of links says nothing about how someone builds things. Hotfix is a small maze game inside a 3D cabinet: clear the bits, fix the bugs, and finish a run in a minute. It never blocks the page around it.

How to play

Steer a disc through three mazes. Eat every bit. A patch lets you fix bugs for points; otherwise they cost a life. Arrow keys, WASD, a swipe, or the mouse.

The name, mazes, and sprites are original. The genre is a maze chase, not a copy of any one machine.

Architecture

GameHost (fixed 120 Hz step)
  ├─ Game         pure TypeScript: modes, maze, bugs, score
  ├─ renderGame   draws a 320×240 Canvas 2D frame
  └─ view
       ├─ ThreeView  canvas → CanvasTexture → CRT ShaderMaterial on a curved mesh
       └─ FlatView   the same canvas inside a CSS cabinet (Lite mode)

The game knows nothing about how it is shown. Each animation frame, the active view asks the host to step the simulation and redraw the 320×240 canvas, then displays it.

Three decisions

A fixed timestep, separate from rendering. The game advances in steps of 1/120 s however fast the screen refreshes, so movement stays the same at 60 Hz and 144 Hz, and the engine can be unit tested without a browser. The cost is an accumulator loop and a cap on catch-up steps after a stall.

The CRT is a shader, not a post-process. The screen is its own mesh with a gentle bulge. Its material does the barrel distortion, scanlines, aperture grille, and power-on sweep. Scanlines fade out with fwidth once they are too fine to resolve.

Everything is procedural. The cabinet is built in code from a measured side profile. There are no model files to download, at the cost of the extra detail a hand-modelled cabinet would have.

Coins

The cabinet takes coins. Every visit comes with one, and three more are hidden around the site. Finding all of them turns on free play.

Respecting the page

What’s unfinished