diff --git a/src/layouts/Full.astro b/src/layouts/Full.astro
index cf77667..fce4058 100644
--- a/src/layouts/Full.astro
+++ b/src/layouts/Full.astro
@@ -85,7 +85,7 @@ const structuredData = [
-
+
diff --git a/src/pages/index.astro b/src/pages/index.astro
index b73bd71..85a24bd 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -22,8 +22,7 @@ const indexScreen = frame(indexFrame);
const repo = 'https://github.com/aviorstudio/termcade';
const releases = 'https://github.com/aviorstudio/termcade/releases';
const docs = 'https://github.com/aviorstudio/termcade/blob/main/docs';
-const icon = (name: keyof typeof octicons, size = 16) =>
- octicons[name].toSVG({ width: size, height: size });
+const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ width: size, height: size });
// Every game in the starter pack. They are packages embedded in the binary,
// not game code compiled into the host, and run through the same wasm boundary
@@ -44,8 +43,7 @@ const games = [
{
name: 'BRICKOUGH',
from: 'Bundled',
- blurb:
- 'Breakout-style brick breaker: steer the ball with paddle english, clear the wall, survive the speed-up.',
+ blurb: 'Breakout-style brick breaker: steer the ball with paddle english, clear the wall, survive the speed-up.',
},
];
@@ -94,8 +92,14 @@ const commands = [
// What a game author is committing to. All of it is in sdk/game.go and
// sdk/input.go, which between them are also the whole dependency list.
const contract = [
- { term: 'Ticks', def: 'Update() runs exactly 60 times a second, stepped off the measured clock rather than drifting' },
- { term: 'Input', def: 'four directions, two action buttons and start — with real releases where the terminal sends them' },
+ {
+ term: 'Ticks',
+ def: 'Update() runs exactly 60 times a second, stepped off the measured clock rather than drifting',
+ },
+ {
+ term: 'Input',
+ def: 'four directions, two action buttons and start — with real releases where the terminal sends them',
+ },
{ term: 'Drawing', def: 'a canvas in square logical units; the game never sees the pixel grid it lands on' },
{ term: 'HUD', def: 'labelled fields and a hint. The shell owns every pixel of the styling' },
{ term: 'Dependencies', def: 'the sdk module, which depends on nothing outside the standard library' },
@@ -104,420 +108,1020 @@ const contract = [
---
-
- 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, Tetris and Brickough 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
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.
+ Asteroid, Tetris and Brickough, rendered in Unicode pixels. A small arcade for the terminal you already
+ have.
+
+ go run github.com/aviorstudio/termcade@latest
+ TRUECOLOR TERMINAL / 80×24 OR LARGER / PLAY OFFLINE
+
+
+
+
+
+
IN THE STARTER PACK
+
+ Pick your
+
+ next high score.
+
- {
- games.map((game) => (
-
-
- {game.name}
- {game.from}
-
-
{game.blurb}
-
- ))
- }
+ {games.map((game, index) => (
+
+ 0{index + 1}
+
+ {index === 0 ? '△' : index === 1 ? '▟' : '▦'}
+
+
{game.name}
+
{game.blurb}
+ BUNDLED / PLAY OFFLINE
+
+ ))}
-
-
TERMCADE_PIXELS
+
+ 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.
+ 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.
- {
- pixelStyles.map((style) => (
-
-
-
- {style.value}
- {style.grid} per cell
-
{style.note}
-
-
- ))
- }
+ {pixelStyles.map((style) => (
+
+
+
+
+
+ {style.value}
+ {style.grid} per cell
+
{style.note}
+
+
+ ))}
-
-
-
- 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
+
+ The front door
+
Find a game. Make it yours.
- The arcade opens on Marketplace. Use Ctrl+N to open the sidebar and switch to Library. Browse without signing in; Add saves a game to your account, while Play downloads and installs it. Your installed games stay in Library even when you are signed out.
+ The arcade opens on Marketplace. Use Ctrl+N to open the sidebar and switch to Library. Browse without
+ signing in; Add saves a game to your account, while Play downloads and installs it. Your installed games
+ stay in Library even when you are signed out.
- 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.
+ 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.
-
Library capture from an earlier release. Current releases open on Marketplace.
+
+
+
+
Library capture from an earlier release. Current releases open on Marketplace.
- {
- commands.map((row) => (
-
-
{row.cmd}
-
{row.what}
-
- ))
- }
+ {commands.map((row) => (
+
+
+ {row.cmd}
+
+
{row.what}
+
+ ))}
-
-
+
-
termcade dev
+
+ 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.
+ one interface — and because the boundary is a frozen wasm ABI rather than a Go one, Go is a convenience and
+ not a requirement.