hud
The readouts of the front row, and the composition that arranges them: Nerve, the act, the pause glyph, the tent's Laughter meter and the house's heat, the clown's plate, the rail of piles and Breath and Block and End Turn, the fan of cards, and the contents of a pile when a play…
hud
The readouts of the front row, and the composition that arranges them: Nerve, the act, the pause glyph, the tent's Laughter meter and the house's heat, the clown's plate, the rail of piles and Breath and Block and End Turn, the fan of cards, and the contents of a pile when a player asks to see one.
Pure builders — a view model and a metrics table in, a widget tree out. Nothing
here reads Core.state() or registers a screen; game.ui.Table does both and
hands the result over.
local hud = require("game.ui.hud")
local m = hud.metrics() -- every size in the table, live
local tree, geom = hud.table(vm, m, fx) -- the whole table as one tree
hud.metrics({ width = 1600, height = 900 }) -- the same table, for a screen this one is not
hud.metrics reads the live frame through Core.frame(), so the same layout
holds on a phone held either way, a laptop and a television; hand it a
{ width, height } and it lays out for that shape instead.
The bands
Every band is a fraction of the frame's height, and each belongs to one thing:
| band | what |
|---|---|
| 0.00 – 0.19 | Nerve, the act, the pause glyph, the Laughter rail |
| 0.19 – 0.28 | the clown's plate |
| 0.28 – 0.57 | the ring. Nothing here draws into it. |
| 0.57 – 0.67 | the rail: DECK · Breath · END TURN · SPENT · BURNT |
| 0.71 – 0.98 | the fan |
Outside battle the table draws nothing at all, except the pause glyph while
vm.phase == "intro" — a card is up in front of it in every other phase.
The pieces
nervePlate, actBadge, pauseGlyph, laughterMeter, breath,
blockPlate, endTurn, pile, pileList, intentPlate, stamp, flood
and flakes are each callable on their own.
fanGeometry(n, m, focus) answers where each card in a hand of n sits — and
also how big it is, because how many cards are in the hand is what decides
whether they can stand side by side. It carries cardW, cardH and step
beside the per-card boxes. Up to six cards the fan is laid out so no card
covers its neighbour at all; past that the cards splay harder and overlap
rather than shrinking below the width the woodcut stops reading at.
endTurn drops its id and its callback while vm.canEndTurn is false, so the
dim stamp is not merely faint — it cannot be clicked, tapped or hit-tested.
The fx table is the transient motion — the flood, the paint flakes, the
stamp, the card arcing into the ring, the deal, a heat lamp lighting —
expressed as countdowns the build reads as progress, so a frame draws the
effect rather than a keyframe that would restart every time the tree is handed
over. Pass nil for a still frame.
A wrapping line needs a box with a width
A label given both props.wrap and a style.width lays out one glyph per
line, and a wrapping label inside a box that hugs its content gets no measure
at all. Every wrapping line in here therefore sits inside a box carrying an
explicit pixel width. Read topics/ui/styling before adding another.
Scoped to this part · feeds back into the world's score.