import { INITIAL_HC, INITIAL_KPI, } from './constants' import type { DifficultyLevel } from './data/mapConfigs' type GameState = 'idle' | 'playing' | 'paused' | 'victory' | 'defeat' /** * 游戏状态管理器(单例) * 负责管理 HC(人才储备)、KPI、波次状态,并通过回调事件通知 Scene */ export class GameManager { private static instance: GameManager public hc: number = INITIAL_HC public kpi: number = INITIAL_KPI public currentWave: number = 0 public gameState: GameState = 'idle' // 难度与地图状态 public difficulty: DifficultyLevel = 'normal' public currentMapIndex: number = 0 // 0=地图1, 1=地图2, 2=地图3 public totalWaveCleared: number = 0 // 总计已清理波次 // 事件回调(Scene 通过这些 hook 更新 HUD) public onHCChange: ((hc: number) => void)[] = [] public onKPIChange: ((kpi: number) => void)[] = [] public onGameOver: (() => void)[] = [] public onVictory: (() => void)[] = [] private constructor() {} static getInstance(): GameManager { if (!GameManager.instance) { GameManager.instance = new GameManager() } return GameManager.instance } /** 设置难度 */ setDifficulty(d: DifficultyLevel): void { this.difficulty = d } /** 重置游戏状态(保留难度,重置其他字段) */ reset(): void { this.hc = INITIAL_HC this.kpi = INITIAL_KPI this.currentWave = 0 this.gameState = 'idle' this.currentMapIndex = 0 this.totalWaveCleared = 0 this.onHCChange = [] this.onKPIChange = [] this.onGameOver = [] this.onVictory = [] // difficulty 保留,不重置 } /** * 扣除 HC,余额不足时返回 false */ spendHC(amount: number): boolean { if (this.hc < amount) return false this.hc -= amount this.onHCChange.forEach(cb => cb(this.hc)) return true } /** * 增加 HC */ addHC(amount: number): void { this.hc += amount this.onHCChange.forEach(cb => cb(this.hc)) } /** * 减少 KPI,归零时触发 GameOver */ reduceKPI(amount: number): void { this.kpi = Math.max(0, this.kpi - amount) this.onKPIChange.forEach(cb => cb(this.kpi)) if (this.kpi <= 0 && this.gameState === 'playing') { this.gameState = 'defeat' this.onGameOver.forEach(cb => cb()) } } /** * 增加 KPI(不超过 100) */ addKPI(amount: number): void { this.kpi = Math.min(100, this.kpi + amount) this.onKPIChange.forEach(cb => cb(this.kpi)) } /** 触发胜利 */ triggerVictory(): void { if (this.gameState === 'playing') { this.gameState = 'victory' this.onVictory.forEach(cb => cb()) } } }