Small arcade games to play while you are blocked on something slower than you.
An agent is working. A container is building. CI is grinding through a matrix. You have somewhere between forty seconds and eleven minutes, you cannot start anything real, and you do not want to open a feed. That is what this is for.
Play: https://aamat09.github.io/blocking-io/
Every game pauses itself the instant the window loses focus. Click over to your terminal mid-wave and the screen freezes exactly where it was. Come back and press A.
That single constraint drives the rest of the design:
- No round lasts long enough to feel wasted when you abandon it
- Nothing is saved except your best score, so there is no progress to lose
- No accounts, no network calls, no telemetry, no build step
- Every game starts on the first button press, not after a menu tour
| Game | Genre | The idea | |
|---|---|---|---|
| 👾 | Phalanx | Fixed shooter | Fifty-five of them, marching. Every one you kill makes the rest move faster, so the last one is the hardest. Bunkers erode and do not come back. |
| 🐍 | Snake | Survival | It only gets longer. Every fifth pickup speeds the whole board up. |
| 🟡 | Pellet Run | Maze chase | Clear the maze while four hunters with different targeting personalities work out where you are going. |
| 🛡 | Ironworks | Tank battle | Hold the yard. Brick stops a shell exactly once, steel stops it every time, and the works behind you only has to be hit once. |
| 🏁 | Vanishing Point | Endless racer | Three lanes coming out of the horizon. Tall blocks have to be steered around, low bars have to be jumped, and every so often the whole width goes low and up is the only way through. |
All five are original implementations. Game mechanics are not copyrightable; the sprites, mazes and code here are written from scratch, and no commercial ROM is included, bundled or required.
Pellet Run and Vanishing Point both ramp: the maze speeds up the player and the ghosts on every level, and the road accelerates with distance and packs the obstacle rows tighter as it goes.
| Keyboard | Gamepad | |
|---|---|---|
| Move / change lane | Arrow keys or WASD | D-pad or left stick |
| Fire / Jump / Start | Space or Enter | A (or any face button) |
| Pause | P or Escape | Menu / View |
Built and tested with a ShanWan Q36, a keychain-sized Bluetooth pad with no analog sticks. That turned out to be the right constraint: every game here needs four directions and one button, which is exactly what the cheapest pad in the drawer can do.
shared/gamepad.js wraps the browser Gamepad API and reads generously, because budget
pads are inconsistent in ways worth knowing about:
- They can present as several different devices. The Q36 has a three-position slide
switch, and each position enumerates as its own Bluetooth device with its own pairing:
Xreports as an Xbox controller with a standard mapping,Das an Android HID device with a non-standard one,Vneeds a vendor app. Use X. Dmode has a hidden multimedia sub-mode where the face buttons emit media keys straight at the OS. Playable, but it will change your system volume while you play.- A D-pad may be an 8-way hat, and a fast roll between directions emits a transient diagonal before the direction you meant.
- Triggers can report as analog while being physically digital, reading only fully off or fully on.
- The pad sleeps after about fifteen minutes and drops its link. The first press after that is consumed by reconnection, so a "dead" pad is usually just asleep. Press twice.
Any pad the browser can see will work. The Gamepad API stays hidden until the pad sends its first input, so press a button before wondering why nothing is detected.
There is no build step, no bundler, and no dependencies. Three ways to run it, all equivalent:
# 1. open the file directly
open index.html
# 2. serve it locally
python3 -m http.server 8000 # then visit localhost:8000
# 3. GitHub Pages, straight from the repo rootClassic <script src> tags and relative paths throughout, deliberately: ES modules would
break the file:// case on CORS.
index.html the cabinet menu, navigable with the D-pad
shared/
arcade.css cabinet chrome, palette, type scale, CRT treatment
gamepad.js Gamepad API wrapper, edge-triggered input
games/
phalanx/ fixed shooter
snake/ survival
maze/ maze chase
tanks/ tank battle
road/ endless racer
- Make
games/<name>/index.html - Link
../../shared/arcade.cssand../../shared/gamepad.js - Use the
.cabinet/.hud/.screen/.overlay/.legendstructure so it matches the rest of the machine - Implement the three states every game here has:
attract,playing,paused, plusover, and pause onblurandvisibilitychange - Add an entry to the
GAMESarray in the rootindex.html
MIT. See LICENSE.