From 5f75895d4170f6a3471b34b7c23848189934c4fd Mon Sep 17 00:00:00 2001 From: Cloud Bot Date: Sat, 21 Mar 2026 09:45:22 +0000 Subject: [PATCH] =?UTF-8?q?refactor(game/enemies/WaveManager):=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=97=E5=A4=96=E9=83=A8=E6=B3=A2=E6=AC=A1=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=92=8C=E9=9A=BE=E5=BA=A6=E5=80=8D=E7=8E=87=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E5=9C=B0=E5=9B=BE=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/enemies/WaveManager.ts | 136 ++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 77 deletions(-) diff --git a/game/enemies/WaveManager.ts b/game/enemies/WaveManager.ts index 73fb814..4f6fd2f 100644 --- a/game/enemies/WaveManager.ts +++ b/game/enemies/WaveManager.ts @@ -4,96 +4,65 @@ import { FreshGraduate } from './FreshGraduate' import { OldEmployee } from './OldEmployee' import { TroubleMaker } from './TroubleMaker' import { BossVP } from './BossVP' +import type { WaveConfigEntry, DifficultyLevel } from '../data/mapConfigs' +import { DIFFICULTY_MULTIPLIER } from '../data/mapConfigs' -interface EnemyGroup { - type: 'FreshGraduate' | 'OldEmployee' | 'TroubleMaker' | 'BossVP' - count: number - interval: number +type EnemyType = 'FreshGraduate' | 'OldEmployee' | 'TroubleMaker' | 'BossVP' + +interface WaveCallbacks { + onWaveComplete: () => void + onAllWavesComplete: () => void + onDestroyRandomTower: () => void } -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 + private waveConfigs: WaveConfigEntry[] + private difficulty: DifficultyLevel + private callbacks: WaveCallbacks + private waveCompleteFired: boolean = false + private allCompleteGuard: boolean = false constructor( scene: Phaser.Scene, - onWave3Complete?: () => void, - onAllWavesComplete?: () => void, - onDestroyRandomTower?: () => void + waveConfigs: WaveConfigEntry[], + difficulty: DifficultyLevel, + callbacks: WaveCallbacks, + waypoints?: readonly { x: number; y: number }[] ) { this.scene = scene - this.pathPoints = buildFullPath() - this.onWave3Complete = onWave3Complete - this.onAllWavesComplete = onAllWavesComplete - this.onDestroyRandomTower = onDestroyRandomTower + this.waveConfigs = waveConfigs + this.difficulty = difficulty + this.callbacks = callbacks + this.pathPoints = buildFullPath(waypoints) } get totalWaves(): number { - return WAVE_CONFIG.length + return this.waveConfigs.length } startNextWave(): void { - if (this.isSpawning || this.currentWave >= WAVE_CONFIG.length) return - const config = WAVE_CONFIG[this.currentWave] + if (this.isSpawning || this.currentWave >= this.waveConfigs.length) return + const config = this.waveConfigs[this.currentWave] this.currentWave++ this.isSpawning = true this.spawnWave(config) } - private spawnWave(config: WaveConfig): void { - // 将所有怪物组展开为按时间排列的生成序列 - const spawnQueue: { type: EnemyGroup['type']; delay: number }[] = [] + private spawnWave(config: WaveConfigEntry): void { + const multiplier = DIFFICULTY_MULTIPLIER[this.difficulty] + const spawnQueue: { type: EnemyType; delay: number }[] = [] + for (const group of config.enemies) { - for (let i = 0; i < group.count; i++) { + const count = Math.ceil(group.count * multiplier.enemyCount) + for (let i = 0; i < count; i++) { spawnQueue.push({ type: group.type, delay: group.interval * i }) } } - // 按 delay 升序排列,同时生成 spawnQueue.sort((a, b) => a.delay - b.delay) let completed = 0 @@ -110,25 +79,28 @@ export class WaveManager { if (spawnQueue.length === 0) this.isSpawning = false } - private spawnEnemy(type: EnemyGroup['type']): EnemyBase { - let enemy: EnemyBase + private spawnEnemy(type: EnemyType): EnemyBase { + const multiplier = DIFFICULTY_MULTIPLIER[this.difficulty] const pts = [...this.pathPoints] + let enemy: EnemyBase + + const speedMult = multiplier.enemySpeed + const hpMult = type === 'BossVP' ? multiplier.bossHp : 1.0 switch (type) { case 'OldEmployee': - enemy = new OldEmployee(this.scene, pts) + enemy = new OldEmployee(this.scene, pts, speedMult, hpMult) break case 'TroubleMaker': - enemy = new TroubleMaker(this.scene, pts) + enemy = new TroubleMaker(this.scene, pts, speedMult, hpMult) break case 'BossVP': - enemy = new BossVP(this.scene, pts, this.onDestroyRandomTower) + enemy = new BossVP(this.scene, pts, this.callbacks.onDestroyRandomTower, speedMult, hpMult) break default: - enemy = new FreshGraduate(this.scene, pts) + enemy = new FreshGraduate(this.scene, pts, speedMult, hpMult) } - // 随机显示语录 this.scene.time.delayedCall(1000 + Math.random() * 2000, () => { if (!enemy.isDead) enemy.showQuote() }) @@ -147,24 +119,26 @@ export class WaveManager { e.update(delta) } - // 检查第3波完成后触发周报 + // 中途波次完成回调(用于触发周报等) if ( this.currentWave === 3 && !this.isSpawning && this.activeEnemies.length === 0 && - !this.wave3Completed + !this.waveCompleteFired ) { - this.wave3Completed = true - this.onWave3Complete?.() + this.waveCompleteFired = true + this.callbacks.onWaveComplete() } - // 检查全部波次完成 + // 全部波次完成 if ( - this.currentWave >= WAVE_CONFIG.length && + this.currentWave >= this.waveConfigs.length && !this.isSpawning && - this.activeEnemies.length === 0 + this.activeEnemies.length === 0 && + !this.allCompleteGuard ) { - this.onAllWavesComplete?.() + this.allCompleteGuard = true + this.callbacks.onAllWavesComplete() } } @@ -173,10 +147,18 @@ export class WaveManager { } hasMoreWaves(): boolean { - return this.currentWave < WAVE_CONFIG.length + return this.currentWave < this.waveConfigs.length } getCurrentWaveNumber(): number { return this.currentWave } + + /** 清除所有活跃怪物(切图时调用) */ + clearAllEnemies(): void { + for (const e of this.activeEnemies) { + if (!e.isDead) e.destroy() + } + this.activeEnemies = [] + } }