import type Phaser from 'phaser' import { GAME_WIDTH, HUD_HEIGHT } from '../constants' /** * 游戏 HUD 辅助工具 * 负责管理"召唤下一波"按钮和波次提示横幅 */ export class HUD { private scene: Phaser.Scene private waveBtn: Phaser.GameObjects.Text | null = null private waveBannerTimeout: (() => void) | null = null constructor(scene: Phaser.Scene) { this.scene = scene } /** * 创建"召唤下一波"按钮 * @param onClick 点击回调 */ createWaveButton(onClick: () => void): void { if (this.waveBtn) this.waveBtn.destroy() this.waveBtn = this.scene.add .text(GAME_WIDTH - 160, HUD_HEIGHT + 20, '▶ 召唤下一波', { fontFamily: "'Press Start 2P', monospace", fontSize: '9px', color: '#A78BFA', backgroundColor: '#1e3a5f', padding: { x: 10, y: 6 }, }) .setOrigin(0, 0) .setDepth(20) .setInteractive({ useHandCursor: true }) this.waveBtn.on('pointerover', () => { if (this.waveBtn) { this.waveBtn.setStyle({ backgroundColor: '#2d5a8e' }) } }) this.waveBtn.on('pointerout', () => { if (this.waveBtn) { this.waveBtn.setStyle({ backgroundColor: '#1e3a5f' }) } }) this.waveBtn.on('pointerdown', () => { onClick() }) } /** 更新按钮文字(如禁用状态) */ setWaveButtonText(text: string): void { this.waveBtn?.setText(text) } disableWaveButton(): void { if (!this.waveBtn) return this.waveBtn.setStyle({ color: '#4B5563', backgroundColor: '#0F172A' }) this.waveBtn.removeAllListeners('pointerdown') } enableWaveButton(): void { if (!this.waveBtn) return this.waveBtn.setStyle({ color: '#A78BFA', backgroundColor: '#1e3a5f' }) } /** * 显示波次开始横幅 * @param waveNumber 当前波次(1-based) */ 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 overlay = this.scene.add.graphics() overlay.fillStyle(0x000000, 0.6) overlay.fillRect(0, 0, GAME_WIDTH, 720) overlay.setDepth(50) this.scene.add .text(GAME_WIDTH / 2, 300, '🎉 大厂保卫成功!', { fontFamily: "'Press Start 2P', monospace", fontSize: '22px', color: '#A78BFA', backgroundColor: '#0A1628', padding: { x: 24, y: 12 }, }) .setOrigin(0.5, 0.5) .setDepth(55) this.scene.add .text(GAME_WIDTH / 2, 380, 'KPI 绩效已发放!', { fontFamily: 'VT323, monospace', fontSize: '24px', color: '#A78BFA', }) .setOrigin(0.5, 0.5) .setDepth(55) } /** 显示失败画面 */ showGameOver(): void { const overlay = this.scene.add.graphics() overlay.fillStyle(0x000000, 0.7) overlay.fillRect(0, 0, GAME_WIDTH, 720) overlay.setDepth(50) this.scene.add .text(GAME_WIDTH / 2, 300, 'KPI 归零!被裁了!', { fontFamily: "'Press Start 2P', monospace", fontSize: '18px', color: '#EF4444', backgroundColor: '#0A1628', padding: { x: 24, y: 12 }, }) .setOrigin(0.5, 0.5) .setDepth(55) } destroy(): void { this.waveBtn?.destroy() if (this.waveBannerTimeout) this.waveBannerTimeout() } }