/** * The banner: the one moment a round turns, said big, on the view itself. * * Somebody sitting down in front of the game for two minutes meets a round * ending before they meet anything else, and the view used to freeze with no * word of who took it or why — the answer was three lines below the canvas at * eighty percent opacity. So for the few seconds a round is over, the match is * over, or a round is starting, the view carries a title and one line under * it. A pure function decides the words; the drawing is a band and two texts. */ import { roundOutcome } from "./prompt.js"; /** The buy phase is fourteen seconds; the round card shows for its first three. */ const BUY_TIME = 14; const CARD_FOR = 3; const FADE = 0.5; const secs = (n) => Math.max(0, Math.ceil(n)); /** * What the banner says right now, or null for nothing. `alpha` is how solid it * is: a card that leaves by fading is not a card that blinked off. */ export function banner(snap) { if (!snap) return null; if (snap.phase === "over") return { title: snap.result ? `${snap.result}` : "Match over", sub: `match over · a new match starts in ${secs(snap.clock)}s`, alpha: 1, }; if (snap.phase === "end") { const outcome = roundOutcome(snap); const next = `next round in ${secs(snap.clock)}s`; if (!outcome) return { title: "Round over", sub: next, alpha: 1 }; return { title: outcome.title, sub: `${outcome.why} · ${next}`, alpha: 1 }; } if (snap.phase === "buy" && snap.me) { const shownFor = BUY_TIME - Number(snap.clock); if (!(shownFor < CARD_FOR)) return null; const alpha = Math.max(0, Math.min(1, (CARD_FOR - shownFor) / FADE)); const side = snap.me.side === "atk" ? "you attack — plant the spike on A or B" : "you defend — hold A and B"; return { title: `Round ${snap.round}`, sub: side, alpha }; } return null; } /** A dark band across the view with the title and the line under it. */ export function drawBanner(ctx, words, width, height) { if (!words || words.alpha <= 0.01) return; const unit = Math.min(width / 900, height / 570); const mid = width / 2; const top = height * 0.2; const band = 92 * unit; ctx.save(); ctx.globalAlpha = words.alpha; ctx.fillStyle = "rgba(8,10,14,0.78)"; ctx.fillRect(0, top, width, band); ctx.textAlign = "center"; ctx.fillStyle = "#f2f3f6"; ctx.font = `700 ${Math.round(34 * unit)}px system-ui, sans-serif`; ctx.fillText(words.title, mid, top + 44 * unit); ctx.fillStyle = "#b9c0cf"; ctx.font = `${Math.round(17 * unit)}px system-ui, sans-serif`; ctx.fillText(words.sub, mid, top + 74 * unit); ctx.restore(); }