refactor(game/enemies/WaveManager): 接受外部波次配置和难度倍率,支持多地图切换

This commit is contained in:
Cloud Bot
2026-03-21 09:45:22 +00:00
parent 185fa39b4e
commit 5f75895d41

View File

@@ -4,96 +4,65 @@ import { FreshGraduate } from './FreshGraduate'
import { OldEmployee } from './OldEmployee' import { OldEmployee } from './OldEmployee'
import { TroubleMaker } from './TroubleMaker' import { TroubleMaker } from './TroubleMaker'
import { BossVP } from './BossVP' import { BossVP } from './BossVP'
import type { WaveConfigEntry, DifficultyLevel } from '../data/mapConfigs'
import { DIFFICULTY_MULTIPLIER } from '../data/mapConfigs'
interface EnemyGroup { type EnemyType = 'FreshGraduate' | 'OldEmployee' | 'TroubleMaker' | 'BossVP'
type: 'FreshGraduate' | 'OldEmployee' | 'TroubleMaker' | 'BossVP'
count: number interface WaveCallbacks {
interval: number 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 { export class WaveManager {
private scene: Phaser.Scene private scene: Phaser.Scene
private activeEnemies: EnemyBase[] = [] private activeEnemies: EnemyBase[] = []
private pathPoints: PathPoint[] private pathPoints: PathPoint[]
private currentWave: number = 0 private currentWave: number = 0
private isSpawning: boolean = false private isSpawning: boolean = false
private onWave3Complete?: () => void private waveConfigs: WaveConfigEntry[]
private onAllWavesComplete?: () => void private difficulty: DifficultyLevel
private onDestroyRandomTower?: () => void private callbacks: WaveCallbacks
private wave3Completed: boolean = false private waveCompleteFired: boolean = false
private allCompleteGuard: boolean = false
constructor( constructor(
scene: Phaser.Scene, scene: Phaser.Scene,
onWave3Complete?: () => void, waveConfigs: WaveConfigEntry[],
onAllWavesComplete?: () => void, difficulty: DifficultyLevel,
onDestroyRandomTower?: () => void callbacks: WaveCallbacks,
waypoints?: readonly { x: number; y: number }[]
) { ) {
this.scene = scene this.scene = scene
this.pathPoints = buildFullPath() this.waveConfigs = waveConfigs
this.onWave3Complete = onWave3Complete this.difficulty = difficulty
this.onAllWavesComplete = onAllWavesComplete this.callbacks = callbacks
this.onDestroyRandomTower = onDestroyRandomTower this.pathPoints = buildFullPath(waypoints)
} }
get totalWaves(): number { get totalWaves(): number {
return WAVE_CONFIG.length return this.waveConfigs.length
} }
startNextWave(): void { startNextWave(): void {
if (this.isSpawning || this.currentWave >= WAVE_CONFIG.length) return if (this.isSpawning || this.currentWave >= this.waveConfigs.length) return
const config = WAVE_CONFIG[this.currentWave] const config = this.waveConfigs[this.currentWave]
this.currentWave++ this.currentWave++
this.isSpawning = true this.isSpawning = true
this.spawnWave(config) this.spawnWave(config)
} }
private spawnWave(config: WaveConfig): void { private spawnWave(config: WaveConfigEntry): void {
// 将所有怪物组展开为按时间排列的生成序列 const multiplier = DIFFICULTY_MULTIPLIER[this.difficulty]
const spawnQueue: { type: EnemyGroup['type']; delay: number }[] = [] const spawnQueue: { type: EnemyType; delay: number }[] = []
for (const group of config.enemies) { 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 }) spawnQueue.push({ type: group.type, delay: group.interval * i })
} }
} }
// 按 delay 升序排列,同时生成
spawnQueue.sort((a, b) => a.delay - b.delay) spawnQueue.sort((a, b) => a.delay - b.delay)
let completed = 0 let completed = 0
@@ -110,25 +79,28 @@ export class WaveManager {
if (spawnQueue.length === 0) this.isSpawning = false if (spawnQueue.length === 0) this.isSpawning = false
} }
private spawnEnemy(type: EnemyGroup['type']): EnemyBase { private spawnEnemy(type: EnemyType): EnemyBase {
let enemy: EnemyBase const multiplier = DIFFICULTY_MULTIPLIER[this.difficulty]
const pts = [...this.pathPoints] const pts = [...this.pathPoints]
let enemy: EnemyBase
const speedMult = multiplier.enemySpeed
const hpMult = type === 'BossVP' ? multiplier.bossHp : 1.0
switch (type) { switch (type) {
case 'OldEmployee': case 'OldEmployee':
enemy = new OldEmployee(this.scene, pts) enemy = new OldEmployee(this.scene, pts, speedMult, hpMult)
break break
case 'TroubleMaker': case 'TroubleMaker':
enemy = new TroubleMaker(this.scene, pts) enemy = new TroubleMaker(this.scene, pts, speedMult, hpMult)
break break
case 'BossVP': case 'BossVP':
enemy = new BossVP(this.scene, pts, this.onDestroyRandomTower) enemy = new BossVP(this.scene, pts, this.callbacks.onDestroyRandomTower, speedMult, hpMult)
break break
default: default:
enemy = new FreshGraduate(this.scene, pts) enemy = new FreshGraduate(this.scene, pts, speedMult, hpMult)
} }
// 随机显示语录
this.scene.time.delayedCall(1000 + Math.random() * 2000, () => { this.scene.time.delayedCall(1000 + Math.random() * 2000, () => {
if (!enemy.isDead) enemy.showQuote() if (!enemy.isDead) enemy.showQuote()
}) })
@@ -147,24 +119,26 @@ export class WaveManager {
e.update(delta) e.update(delta)
} }
// 检查第3波完成后触发周报 // 中途波次完成回调(用于触发周报等)
if ( if (
this.currentWave === 3 && this.currentWave === 3 &&
!this.isSpawning && !this.isSpawning &&
this.activeEnemies.length === 0 && this.activeEnemies.length === 0 &&
!this.wave3Completed !this.waveCompleteFired
) { ) {
this.wave3Completed = true this.waveCompleteFired = true
this.onWave3Complete?.() this.callbacks.onWaveComplete()
} }
// 检查全部波次完成 // 全部波次完成
if ( if (
this.currentWave >= WAVE_CONFIG.length && this.currentWave >= this.waveConfigs.length &&
!this.isSpawning && !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 { hasMoreWaves(): boolean {
return this.currentWave < WAVE_CONFIG.length return this.currentWave < this.waveConfigs.length
} }
getCurrentWaveNumber(): number { getCurrentWaveNumber(): number {
return this.currentWave return this.currentWave
} }
/** 清除所有活跃怪物(切图时调用) */
clearAllEnemies(): void {
for (const e of this.activeEnemies) {
if (!e.isDead) e.destroy()
}
this.activeEnemies = []
}
} }