The screen kit
A fighting game needs screens before and around the fight: the loading screen, choose your fighter, the versus screen, the HUD, the touch controls, the controllers, the pause screen. Until 29 October 2026 every game built them itself (Fight Lab: six files and a thousand lines). gameable/screens is the engine's: each screen is markup with named slots the kit fills and drives, and a game keeps its own words and its own look.
Two ways in
A page game writes its markup and CSS and names the slots. The kit finds a screen by data-screen and its slots by data-slot; a <template data-slot="…"> is a row the kit clones (a roster tile, a column of the tale of the tape, a line of the move list). The page's class names and CSS are its own; the kit only adds a few state classes (below). Nothing is a locked template: a slot the page leaves out is simply not drawn (screens.missing says which).
html
<div data-screen="fight" id="hud">
<div class="side l">
<div class="name" data-slot="p1-name"></div>
<div class="bar">
<div class="lag" data-slot="p1-lag"></div>
<div class="fill" data-slot="p1-health"></div>
</div>
<div class="pips" data-slot="p1-pips"></div>
</div>
<div class="clock" data-slot="clock"></div>
</div>A script game ships only src/game.ts, so it has no markup: the host draws the kit's default markup, styled by a small theme (createScreens({ theme })), and the guest drives it with data in the screens block of its HUD model (ctx.hud.set({ screens: { show: 'select', select: { pair: ['jake', 'logan'] } } })). The host hands the kit to the adapter as its HUD renderer (screensHud), and the kit's events go back to the guest as status lines on the page's conversation channel (screensEvents(tell): screens:pick:jake:0:step, screens:fight, screens:menu), the way the action template's page talks to its game.
The screens and their slots
Screen (data-screen) | Slots (data-slot) | The kit does |
|---|---|---|
loading | bar, text, modes (buttons with data-mode), title, subtitle | the bar's width from the game's progress, the words, the loading class until ready, the marked mode (on) by mouse, keys or controller, the choice |
select | stage, p1-figure, p2-figure, p1-name, p2-name, picking, tape (+ templates tape-column with tape-line, tape-bars; tape-bar with bar-name, bar-fill, bar-value), tiles (+ template tile with tile-image, tile-tag, tile-name), back, tab-1v1, tab-sep, tab-rumble, fight | the tiles from the roster, tagged and classed (p1, p2, pvp; the tag p1, p2 or cpu), the two picked as the game's pictures (a still, an idle that loops, a pick move) or its own figure, the tale of the tape, a pick by click or tap, the keys and the controllers stepping the grid |
versus | p1-figure, p2-figure, p1-name, p2-name, more, text, bar, spinner, back | the names over two lines, the rest of a rumble, the words and the bar, the way back when a fighter did not load; gone on the fade |
fight | p1-name, p1-health, p1-lag, p1-pips, p1-combo, p1-history, the same for p2, clock, banner, banner-big, banner-sub, advantage, track, help, pad-note | the bars' widths, the pips (on when won), the clock, the banner's opacity, a combo's count held a moment and faded, a callout beside a side, the training lines, a controller's note |
touch | stick, buttons (buttons with data-button, data-hold), menu, turn | the stick on gameable/input's touch layer, drawn by its overlay, read as a direction past a third of the reach; the buttons held (on), a tap the quick press and a hold the press with its modifier; shown (on) on a touch screen in a fight; the turn ask |
pause | pause-title, pause-sub, pause-list (+ templates pause-group with group-name; pause-row with row-name, row-keys, row-ends) | the move list: groups, rows, the keys as caps (<b>), notes (<i>), locked rows |
The controllers (screens.pads) and the keys (screens.keys) have no slots: a controller is read by the standard layout (south, east, west, north, the shoulders, the triggers, Options), in the order they connect, each player taking the next; on a menu each push is one step. The figure cache (createFigures) is the loading rule: a pick's figure loads at once, at most four stay in memory, the least recently picked let go, the ones a screen needs now never; a fight starts only when every figure is in (versusDone, at least 1.5 s on the versus screen).
What stays the game's
Whose pick a tap is, who is in a rumble, the modes' meaning, the damage and the clock, the words (the prompts, the tags, the banner), the look. The kit draws and steps; the game decides. A game with a turntable gives createScreens({ figure }) and draws the picked fighter in the slot itself.
See also
- Build a fighting game: the fight kit, with the screens at the end.
- The kit guide, rule 14: the screens come from the screen kit.
- Read player input: the touch layer the stick is built on.