feat(game): 添加全套音效系统(背景BGM+7种攻击音+波次/Boss/死亡/建塔音效),纯Web Audio API合成

This commit is contained in:
Cloud Bot
2026-03-24 08:01:27 +00:00
parent c8b8c7109f
commit 08a3612ba1
12 changed files with 351 additions and 2 deletions

View File

@@ -18,6 +18,7 @@ import { HUD } from './ui/HUD'
import { WeeklyReportModal } from './ui/WeeklyReportModal'
import { MapTransitionModal } from './ui/MapTransitionModal'
import { ALL_MAPS, type MapConfig } from './data/mapConfigs'
import { AudioEngine } from './AudioEngine'
void MAP_ROWS; void GAME_HEIGHT; void GAME_WIDTH; void BAR_X; void BAR_Y; void BAR_W; void BAR_H
@@ -81,7 +82,7 @@ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene {
this.manager = GameManager.getInstance()
this.manager.reset()
// 读取难度React 层通过 window.__gameDifficulty 传入)
// 读取难度
if (typeof window !== 'undefined') {
const diff = (window as any).__gameDifficulty
if (diff === 'easy' || diff === 'normal' || diff === 'hard') {
@@ -99,7 +100,8 @@ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene {
this.hcText = hudObjs.hcText
this.towerManager = new TowerManager(this)
this.weeklyModal = new WeeklyReportModal({ onBossInspection: () => this.freezeAllTowers(3000),
this.weeklyModal = new WeeklyReportModal({
onBossInspection: () => this.freezeAllTowers(3000),
onFullStamina: () => this.refillAllStamina(),
})
this.mapTransitionModal = new MapTransitionModal()
@@ -107,6 +109,7 @@ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene {
this.hud = new HUD(this)
this.hud.createWaveButton(() => this.onWaveButtonClick())
this.loadMap(ALL_MAPS[0])
if (typeof window !== 'undefined') {
;(window as any).__gameSelectTower = (type: TowerType | null) => {
this.selectedTowerType = type
@@ -114,11 +117,34 @@ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene {
}
}
// 初始化音效引擎(首次点击后激活 AudioContext
const audio = AudioEngine.getInstance()
this.input.once('pointerdown', () => {
audio.init()
audio.startBGM()
})
// 添加静音切换按钮(右上角)
this.createMuteButton(audio)
this.setupInteraction()
this.setupManagerCallbacks()
if (typeof window !== 'undefined') { ;(window as any).__gameReady?.() }
}
private createMuteButton(audio: AudioEngine): void {
const btn = this.add.text(GAME_WIDTH - 10, 8, '🔊', {
fontSize: '16px', backgroundColor: 'rgba(0,0,0,0.35)',
padding: { x: 6, y: 3 },
}).setOrigin(1, 0).setDepth(50).setInteractive({ useHandCursor: true })
btn.on('pointerdown', () => {
const nowMuted = !audio.isMuted()
audio.setMuted(nowMuted)
btn.setText(nowMuted ? '🔇' : '🔊')
if (!nowMuted) audio.startBGM()
else audio.stopBGM()
})
}
private setupManagerCallbacks(): void {
this.manager.onHCChange.push((hc: number) => {
this.hcText.setText(`HC: ${hc}`)
@@ -127,6 +153,10 @@ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene {
this.manager.onKPIChange.push((kpi: number) => {
updateKPIBar(this.kpiBar, kpi)
this.kpiText.setText(`${kpi}%`)
// KPI 危险时播放警告音(每次低于 30% 时触发一次)
if (kpi <= 30 && kpi > 0) {
AudioEngine.getInstance().playKPIWarning()
}
})
this.manager.onGameOver.push(() => { this.hud.showGameOver() })
this.manager.onVictory.push(() => { this.hud.showVictory() })
@@ -205,6 +235,8 @@ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene {
this.waveManager.startNextWave()
const waveNum = this.waveManager.getCurrentWaveNumber()
this.hud.showWaveBanner(waveNum, this.waveManager.totalWaves)
// 波次开始音效
AudioEngine.getInstance().playWaveStart()
}
private onWeeklyReport(): void {