termcade draws its playfield out of Unicode block elements, so one terminal cell
becomes a 2×2 or 2×3 grid of pixels and the games come out sharper than the font
should allow. Asteroid and Tetris are in the binary, and play offline the moment it
starts.
go run github.com/aviorstudio/termcade@latest
One static binary · a truecolor terminal at 80×24 or larger
termcade / ASTEROID
ASTEROIDHIGH 1380╭────────────────────────────────────────────────────────────────────────╮│▗▚││▌▌││▟▀▀▟▖││││││││▗▄▄▄││▄▞▘▀▀▌││▄▀▐▗▄▖││▐▌▄▀▀▘▝▖││▚▞▗▄▄▖▞▗▘││▀▄▐▗▞▀▘▝▀▀▄▝▚▄▖▄▀▄▄▄▄││▀▄▄▄▀▀▘▞▘▐▝▀▗▀▀▌││▌▌▝▖▄▘││▀▚▄▖▄▘▀▄▄▄▞││▄▖▝▀▚▖▄▀││▄▞▀▝▚▖▝▀││▄▀▝▀▄▖││▞▐▘││▝▚▗▞▗▖│╰────────────────────────────────────────────────────────────────────────╯SCORE 000020WAVE 1▲ ▲ ▲←/→ turn · ↑ thrust · space fire
quad 2×2 pixels per cellwasm sandboxed guest60 TPS fixed step
In the arcade
Three games in the box, and the way in for the rest.
The starter pack is committed as packages and embedded in the binary, then unpacked
into your games directory the first time it runs. The games that come with the arcade
are installed exactly the way an added one is — and can be removed exactly the same
way.
ASTEROIDBundled
Asteroids-style rock shooter. An inertial ship on a wrapping field, and big rocks that split into faster small ones.
TETRISBundled
Falling-block stacker with Super Rotation System kicks, a 7-bag randomizer, ghost piece, lock delay, and gravity that tightens by level.
BRICKOUGHBundled
Breakout-style brick breaker: steer the ball with paddle english, clear the wall, survive the speed-up.
TERMCADE_PIXELS
One ship. Four ways to cut up a cell.
Every setting draws the same game into the same terminal cells; only the sharpness,
and what the font has to know how to draw, change. Below is Asteroid's ship at the
start of a wave, captured four times over and blown up — the same five columns of
cells every time, a different number of pixels inside them. In the arcade p cycles the
style and keeps it, and TERMCADE_PIXELS overrides the saved choice for a
single run.
▗▗▘▚▟▄▞▖▝▘▝▀
quad2×2 per cell
Unicode 1.0 block elements. Renders anywhere, and the default.
🬦🬞🬄🬣🬔🬭🬁🬓🬉🬂🬂🬍
sextant2×3 per cell
Sharpest, near-square pixels. Needs Unicode 13, or you get tofu.
▄▄▀▄▄▄▀▄▀▀▀
half1×2 per cell
The original look, for fonts that struggle with the rest.
-:::.:_:,-""-
ascii3×3 per cell
A density ramp and line characters. No block glyphs at all.
01
Nothing is compiled in
Every game is a WebAssembly package, and it runs under
wazero with no filesystem, no network, and a
watchdog on every call into it. One that panics gets a crash screen instead of
taking the arcade with it, and one that fails to install is listed dimmed, with the
reason, rather than quietly missing.
02
Held keys, without the half-second stall
Terminals send no key-release events, so a held key is normally guessed from
auto-repeat — which stalls for the OS repeat delay after the first press and makes
a paddle feel like it is ignoring you. termcade asks for the Kitty keyboard
protocol's event-type reporting, and on terminals that answer — kitty, Ghostty,
foot, WezTerm, recent xterm — held keys are exact. Everywhere else it falls back
without saying anything.
03
The renderer owns the look
Games draw in square logical units and never see the pixel grid, so the block
style, the cell shape and the ANSI batching are the arcade's business rather than
theirs. A game written before a pixel style existed renders in it anyway.
The front door
Opens on what you played last.
The library is one keystroke away and the marketplace one more. Browsing is
open; signing in adds a game to the account library and installs it on this machine.
The library follows you to the web app and every terminal where you sign in, and the
arcade has its own account screens.
The live registry is api.termca.de. Package bytes pass through it and are
checked against the sha256 recorded when the release was published before either the
terminal or web app runs them. TERMCADE_REGISTRY selects a local registry
for development.
▄▄▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄ ▄▄ ▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄██ ██▄▄ ██▄▄▄▀ ██▀▄▀██ ██ ▀▀ ██▄▄██ ██ ██ ██▄▄██ ██▄▄▄ ██ ██ ██ ██ ▀███▀ ██ ██ ██▄▄█▀ ██▄▄▄recently played▸ BRICKOUGH··· high 580ASTEROID··· high 1380→ LIBRARY→ MARKETPLACE↑/↓ select · enter open · l library · m marketplace · p pixels · q quit
termcade
play — the marketplace is in here too, on m
termcade add author/slug
add a marketplace game to your account and this machine
termcade list
what is in your arcade
termcade remove author/slug
take one off, and off your synced library
termcade signup
create an account — or termcade login, termcade logout
termcade dev new you/mygame
scaffold a game that is already playable
termcade dev build
package a game directory into a .tcade
termcade dev install build/game.tcade
install a local package while developing
termcade dev
The arcade you play with is the dev kit.
termcade dev new you/mygame scaffolds a game that already runs,
termcade dev build turns the directory into a .tcade, and
termcade dev install puts the local build on your own menu. A game is a Go package implementing
one interface — and because the boundary is a frozen wasm ABI rather than a Go one, Go
is a convenience and not a requirement.