Skip to content

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
loadingbar, text, modes (buttons with data-mode), title, subtitlethe 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
selectstage, 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, fightthe 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
versusp1-figure, p2-figure, p1-name, p2-name, more, text, bar, spinner, backthe 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
fightp1-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-notethe 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
touchstick, buttons (buttons with data-button, data-hold), menu, turnthe 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
pausepause-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 ​