feat(enemies): 实现怪物基类与4种怪物及波次管理器
This commit is contained in:
182
game/enemies/WaveManager.ts
Normal file
182
game/enemies/WaveManager.ts
Normal file
@@ -0,0 +1,182 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user