import type Phaser from 'phaser' import { GAME_WIDTH, HUD_HEIGHT } from '../constants' import { GameManager } from '../GameManager' import { showVictoryModal, showDefeatModal } from './EndScreenModal' /** * 游戏 HUD 辅助工具 * 召唤下一波按钮已移至 React 右侧面板,HUD 只负责横幅提示和结算弹窗 */ export class HUD { private scene: Phaser.Scene private waveBannerTimeout: (() => void) | null = null // 按钮状态通过 window 回调同步到 React private _onWaveClick: (() => void) | null = null constructor(scene: Phaser.Scene) { this.scene = scene } /** * 注册"召唤下一波"逻辑,并把控制接口暴露给 React 层 */ createWaveButton(onClick: () => void): void { this._onWaveClick = onClick if (typeof window === 'undefined') return // React 层通过 window.__gameOnWaveClick() 触发 ;(window as any).__gameOnWaveClick = () => { this._onWaveClick?.() } // 初始状态:可用 this._notifyReact('▶ 召唤下一波', false) } private _notifyReact(text: string, disabled: boolean): void { if (typeof window !== 'undefined') { ;(window as any).__gameSetWaveBtn?.({ text, disabled }) } } setWaveButtonText(text: string): void { // 保持当前 disabled 状态,只更新文字 if (typeof window !== 'undefined') { const cur = (window as any).__gameWaveBtnState const disabled = cur?.disabled ?? false this._notifyReact(text, disabled) } } disableWaveButton(): void { this._notifyReact((typeof window !== 'undefined' ? (window as any).__gameWaveBtnState?.text ?? '波次进行中...' : '波次进行中...'), true) } enableWaveButton(): void { this._notifyReact((typeof window !== 'undefined' ? (window as any).__gameWaveBtnState?.text ?? '▶ 召唤下一波' : '▶ 召唤下一波'), false) } /** * 显示波次开始横幅 */ showWaveBanner(waveNumber: number, totalWaves: number): void { const isBoss = waveNumber === totalWaves const label = isBoss ? `!! 第${waveNumber}波:空降VP来袭 !!` : `第 ${waveNumber} 波来袭!` const color = isBoss ? '#FBBF24' : '#F43F5E' const bg = isBoss ? '#7C2D12' : '#0A1628' const banner = this.scene.add .text(GAME_WIDTH / 2, HUD_HEIGHT + 60, label, { fontFamily: "'Press Start 2P', monospace", fontSize: isBoss ? '16px' : '14px', color, backgroundColor: bg, padding: { x: 20, y: 10 }, }) .setOrigin(0.5, 0.5) .setDepth(40) .setAlpha(0) this.scene.tweens.add({ targets: banner, alpha: 1, duration: 300, yoyo: true, hold: 1800, onComplete: () => banner.destroy(), }) } /** 显示周报触发提示横幅 */ showWeeklyReportAlert(): void { const banner = this.scene.add .text(GAME_WIDTH / 2, HUD_HEIGHT + 120, '周报时间到!请选择正确黑话!', { fontFamily: "'Press Start 2P', monospace", fontSize: '11px', color: '#FCD34D', backgroundColor: '#78350F', padding: { x: 16, y: 8 }, }) .setOrigin(0.5, 0.5) .setDepth(40) .setAlpha(0) this.scene.tweens.add({ targets: banner, alpha: 1, duration: 400, yoyo: true, hold: 2500, onComplete: () => banner.destroy(), }) } /** 显示胜利画面 */ showVictory(): void { const manager = GameManager.getInstance() const kpi = manager.kpi const hc = manager.hc let grade: string let gradeColor: string let gradeDesc: string if (kpi >= 80) { grade = 'S级 "超出预期"' gradeColor = '#fbbf24' gradeDesc = '恭喜晋升为高级打工人!福报已在路上...' } else if (kpi >= 60) { grade = 'A级 "达成预期"' gradeColor = '#34d399' gradeDesc = '表现良好,明年涨薪3%(扣去通胀后-2%)' } else if (kpi >= 40) { grade = 'B级 "基本达成"' gradeColor = '#60a5fa' gradeDesc = '还需努力,下月开始996' } else { grade = 'C级 "未达预期"' gradeColor = '#f87171' gradeDesc = '已被纳入待优化名单' } showVictoryModal({ kpi, hc, grade, gradeColor, gradeDesc }) } /** 显示失败画面 */ showGameOver(): void { showDefeatModal() } destroy(): void { if (this.waveBannerTimeout) this.waveBannerTimeout() if (typeof window !== 'undefined') { delete (window as any).__gameOnWaveClick delete (window as any).__gameSetWaveBtn delete (window as any).__gameWaveBtnState } } }