import Phaser from 'phaser'; import { POUR_SWEEP_MS, POUR_CLEAN_FROM, POUR_OVER_FROM } from '../barShift'; import { POUR_UI } from '../../../data/strings/floor'; const W = 640; const H = 360; const GLASS_H = 120; const GLASS_W = 44; /** * The pour (docs/SCENARIOS.md, bartender shift): a marker sweeps 0→1→0 and * SPACE stops it — the fill IS your pour. The clean band sits near the top * because a good pour is nearly a mistake. Same shell discipline as the other * overlays: the scene routes keys in and calls update(dt). */ export class PourOverlay { private root: Phaser.GameObjects.Container | null = null; private fillRect: Phaser.GameObjects.Rectangle | null = null; private t = 0; private rising = true; private done: ((fill: number | null) => void) | null = null; constructor(private readonly scene: Phaser.Scene) {} get isOpen(): boolean { return this.root !== null; } open(done: (fill: number | null) => void): void { if (this.root) return; this.done = done; this.t = 0; this.rising = true; const root = this.scene.add.container(0, 0).setDepth(900).setScrollFactor(0); this.root = root; root.add(this.scene.add.rectangle(W / 2, H / 2, W, H, 0x03030a, 0.72)); root.add(this.scene.add.rectangle(W / 2, H / 2, 280, 200, 0x10121c).setStrokeStyle(1, 0x3a4054)); root.add( this.scene.add .text(W / 2, H / 2 - 82, POUR_UI.title, { fontFamily: 'monospace', fontSize: '13px', color: '#e8e4da' }) .setOrigin(0.5), ); // The glass, and the bands painted on its side like an honest jug. const gx = W / 2; const gBottom = H / 2 + 58; root.add(this.scene.add.rectangle(gx, gBottom - GLASS_H / 2, GLASS_W + 8, GLASS_H + 6, 0x232838)); const band = (from: number, to: number, colour: number): void => { const y0 = gBottom - GLASS_H * from; const y1 = gBottom - GLASS_H * to; root.add( this.scene.add .rectangle(gx + GLASS_W / 2 + 10, (y0 + y1) / 2, 4, y0 - y1, colour) .setOrigin(0.5), ); }; band(0, POUR_CLEAN_FROM, 0x5a4a48); // short: the region of regret band(POUR_CLEAN_FROM, POUR_OVER_FROM, 0x74a06a); // clean band(POUR_OVER_FROM, 1, 0xd8a020); // overflow: beloved, expensive this.fillRect = this.scene.add .rectangle(gx, gBottom, GLASS_W, 1, 0xc8a24a) .setOrigin(0.5, 1); root.add(this.fillRect); root.add( this.scene.add .text(W / 2, H / 2 + 78, POUR_UI.help, { fontFamily: 'monospace', fontSize: '9px', color: '#8890a8' }) .setOrigin(0.5), ); } handleKey(key: string): void { if (!this.root) return; if (key === 'ESCAPE' || key === 'ESC') return this.finish(null); if (key === 'SPACE') return this.finish(this.t); } update(dtMs: number): void { if (!this.root) return; const step = dtMs / POUR_SWEEP_MS; this.t += this.rising ? step : -step; if (this.t >= 1) { this.t = 1; this.rising = false; } else if (this.t <= 0) { this.t = 0; this.rising = true; } this.fillRect?.setDisplaySize(GLASS_W, Math.max(1, GLASS_H * this.t)); } private finish(fill: number | null): void { const cb = this.done; this.root?.destroy(); this.root = null; this.fillRect = null; this.done = null; cb?.(fill); } }