Files
test1/game/GameManager.ts

107 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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())
}
}
}