import type Phaser from 'phaser' import { EnemyBase, buildFullPath, type PathPoint } from './EnemyBase' import { FreshGraduate } from './FreshGraduate' import { OldEmployee } from './OldEmployee' import { TroubleMaker } from './TroubleMaker' import { BossVP } from './BossVP' interface EnemyGroup { type: 'FreshGraduate' | 'OldEmployee' | 'TroubleMaker' | 'BossVP' count: number interval: number } interface WaveConfig { enemies: EnemyGroup[] } const WAVE_CONFIG: WaveConfig[] = [ { enemies: [{ type: 'FreshGraduate', count: 10, interval: 800 }] }, { enemies: [ { type: 'FreshGraduate', count: 8, interval: 800 }, { type: 'OldEmployee', count: 3, interval: 2000 }, ], }, { enemies: [ { type: 'OldEmployee', count: 5, interval: 2000 }, { type: 'TroubleMaker', count: 3, interval: 1500 }, ], }, { enemies: [ { type: 'FreshGraduate', count: 12, interval: 600 }, { type: 'TroubleMaker', count: 2, interval: 1500 }, ], }, { enemies: [ { type: 'OldEmployee', count: 6, interval: 1500 }, { type: 'TroubleMaker', count: 3, interval: 1500 }, ], }, { enemies: [ { type: 'BossVP', count: 1, interval: 0 }, { type: 'OldEmployee', count: 4, interval: 2000 }, ], }, ] export class WaveManager { private scene: Phaser.Scene private activeEnemies: EnemyBase[] = [] private pathPoints: PathPoint[] private currentWave: number = 0 private isSpawning: boolean = false private onWave3Complete?: () => void private onAllWavesComplete?: () => void private onDestroyRandomTower?: () => void private wave3Completed: boolean = false constructor( scene: Phaser.Scene, onWave3Complete?: () => void, onAllWavesComplete?: () => void, onDestroyRandomTower?: () => void ) { this.scene = scene this.pathPoints = buildFullPath() this.onWave3Complete = onWave3Complete this.onAllWavesComplete = onAllWavesComplete this.onDestroyRandomTower = onDestroyRandomTower } get totalWaves(): number { return WAVE_CONFIG.length } startNextWave(): void { if (this.isSpawning || this.currentWave >= WAVE_CONFIG.length) return const config = WAVE_CONFIG[this.currentWave] this.currentWave++ this.isSpawning = true this.spawnWave(config) } private spawnWave(config: WaveConfig): void { // 将所有怪物组展开为按时间排列的生成序列 const spawnQueue: { type: EnemyGroup['type']; delay: number }[] = [] for (const group of config.enemies) { for (let i = 0; i < group.count; i++) { spawnQueue.push({ type: group.type, delay: group.interval * i }) } } // 按 delay 升序排列,同时生成 spawnQueue.sort((a, b) => a.delay - b.delay) let completed = 0 for (const item of spawnQueue) { this.scene.time.delayedCall(item.delay, () => { this.spawnEnemy(item.type) completed++ if (completed === spawnQueue.length) { this.isSpawning = false } }) } if (spawnQueue.length === 0) this.isSpawning = false } private spawnEnemy(type: EnemyGroup['type']): EnemyBase { let enemy: EnemyBase const pts = [...this.pathPoints] switch (type) { case 'OldEmployee': enemy = new OldEmployee(this.scene, pts) break case 'TroubleMaker': enemy = new TroubleMaker(this.scene, pts) break case 'BossVP': enemy = new BossVP(this.scene, pts, this.onDestroyRandomTower) break default: enemy = new FreshGraduate(this.scene, pts) } // 随机显示语录 this.scene.time.delayedCall(1000 + Math.random() * 2000, () => { if (!enemy.isDead) enemy.showQuote() }) this.activeEnemies.push(enemy) return enemy } update(delta: number): void { for (let i = this.activeEnemies.length - 1; i >= 0; i--) { const e = this.activeEnemies[i] if (e.isDead) { this.activeEnemies.splice(i, 1) continue } e.update(delta) } // 检查第3波完成后触发周报 if ( this.currentWave === 3 && !this.isSpawning && this.activeEnemies.length === 0 && !this.wave3Completed ) { this.wave3Completed = true this.onWave3Complete?.() } // 检查全部波次完成 if ( this.currentWave >= WAVE_CONFIG.length && !this.isSpawning && this.activeEnemies.length === 0 ) { this.onAllWavesComplete?.() } } getAllActiveEnemies(): EnemyBase[] { return this.activeEnemies } hasMoreWaves(): boolean { return this.currentWave < WAVE_CONFIG.length } getCurrentWaveNumber(): number { return this.currentWave } }