Phaser 音频系统 #

音频概述 #

Phaser 使用 Web Audio API 和 HTML5 Audio 提供强大的音频支持。

text
┌─────────────────────────────────────────────────────────────┐
│                    音频系统架构                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Sound Manager                                              │
│  ├── Web Audio API                                         │
│  │   ├── 低延迟                                            │
│  │   ├── 音频节点                                          │
│  │   └── 音效处理                                          │
│  ├── HTML5 Audio                                           │
│  │   ├── 兼容性好                                          │
│  │   └── 功能有限                                          │
│  └── 音频类型                                              │
│      ├── 音效(SFX)                                       │
│      └── 背景音乐(BGM)                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

加载音频 #

基本加载 #

javascript
preload() {
  this.load.audio('bgm', 'assets/audio/background.mp3');
  
  this.load.audio('jump', 'assets/audio/jump.mp3');
  this.load.audio('coin', 'assets/audio/coin.mp3');
  this.load.audio('explosion', 'assets/audio/explosion.mp3');
}

多格式支持 #

javascript
preload() {
  this.load.audio('bgm', [
    'assets/audio/background.mp3',
    'assets/audio/background.ogg',
    'assets/audio/background.m4a'
  ]);
}

音频精灵 #

javascript
preload() {
  this.load.audioSprite('sfx', 'assets/audio/sfx.json', [
    'assets/audio/sfx.mp3',
    'assets/audio/sfx.ogg'
  ]);
}

播放音频 #

基本播放 #

javascript
create() {
  this.sound.play('jump');
  
  this.bgm = this.sound.add('bgm');
  this.bgm.play();
  
  this.coinSound = this.sound.add('coin');
  this.coinSound.play();
}

播放配置 #

javascript
this.sound.play('jump', {
  volume: 0.5,
  rate: 1,
  detune: 0,
  seek: 0,
  loop: false,
  delay: 0
});

const sound = this.sound.add('bgm', {
  volume: 0.3,
  loop: true
});
sound.play();

音频精灵播放 #

javascript
create() {
  this.sound.playAudioSprite('sfx', 'jump');
  
  this.sfx = this.sound.addAudioSprite('sfx');
  this.sfx.play('coin');
  this.sfx.play('explosion');
}

音频控制 #

音量控制 #

javascript
const sound = this.sound.add('bgm');

sound.setVolume(0.5);

sound.volume = 0.5;

this.sound.setVolume(0.5);

this.sound.volume = 0.5;

暂停与恢复 #

javascript
const sound = this.sound.add('bgm');
sound.play();

sound.pause();

sound.resume();

sound.stop();

sound.destroy();

循环播放 #

javascript
const sound = this.sound.add('bgm', { loop: true });
sound.play();

sound.setLoop(true);

const isLooping = sound.loop;

播放速率 #

javascript
const sound = this.sound.add('bgm');

sound.setRate(1.5);

sound.rate = 1.5;

sound.setDetune(100);

sound.detune = 100;

播放位置 #

javascript
const sound = this.sound.add('bgm');

sound.setSeek(30);

sound.seek = 30;

const currentTime = sound.seek;

const duration = sound.duration;

const progress = sound.seek / sound.duration;

静音 #

javascript
const sound = this.sound.add('bgm');

sound.setMute(true);

sound.mute = true;

this.sound.setMute(true);

this.sound.mute = true;

音频事件 #

声音事件 #

javascript
const sound = this.sound.add('bgm');

sound.on('play', (sound) => {
  console.log('Sound started playing');
});

sound.on('end', (sound) => {
  console.log('Sound ended');
});

sound.on('stop', (sound) => {
  console.log('Sound stopped');
});

sound.on('pause', (sound) => {
  console.log('Sound paused');
});

sound.on('resume', (sound) => {
  console.log('Sound resumed');
});

sound.on('loop', (sound) => {
  console.log('Sound looped');
});

sound.on('mute', (sound, mute) => {
  console.log('Mute changed:', mute);
});

sound.on('volume', (sound, volume) => {
  console.log('Volume changed:', volume);
});

sound.on('rate', (sound, rate) => {
  console.log('Rate changed:', rate);
});

sound.on('seek', (sound, seek) => {
  console.log('Seek changed:', seek);
});

全局事件 #

javascript
this.sound.on('mute', (soundManager, mute) => {
  console.log('Global mute:', mute);
});

this.sound.on('volume', (soundManager, volume) => {
  console.log('Global volume:', volume);
});

this.sound.on('unlocked', () => {
  console.log('Audio unlocked');
});

音频管理 #

获取音频 #

javascript
const allSounds = this.sound.getAll();

const sound = this.sound.get('bgm');

const isPlaying = this.sound.isPlaying('bgm');

const isPaused = this.sound.isPaused('bgm');

停止所有音频 #

javascript
this.sound.stopAll();

this.sound.stopByKey('bgm');

音频解锁 #

javascript
if (this.sound.locked) {
  this.sound.once('unlocked', () => {
    this.sound.play('bgm');
  });
}

this.input.once('pointerdown', () => {
  this.sound.unlock();
});

音频效果 #

淡入淡出 #

javascript
const sound = this.sound.add('bgm', { volume: 0 });
sound.play();

this.tweens.add({
  targets: sound,
  volume: 1,
  duration: 2000,
  ease: 'Linear'
});

this.tweens.add({
  targets: sound,
  volume: 0,
  duration: 2000,
  ease: 'Linear',
  onComplete: () => sound.stop()
});

音量渐变 #

javascript
fadeIn(sound, duration = 1000) {
  sound.setVolume(0);
  sound.play();
  
  this.tweens.add({
    targets: sound,
    volume: 1,
    duration: duration,
    ease: 'Linear'
  });
}

fadeOut(sound, duration = 1000) {
  this.tweens.add({
    targets: sound,
    volume: 0,
    duration: duration,
    ease: 'Linear',
    onComplete: () => sound.stop()
  });
}

crossFade(fromSound, toSound, duration = 1000) {
  this.tweens.add({
    targets: fromSound,
    volume: 0,
    duration: duration,
    ease: 'Linear',
    onComplete: () => fromSound.stop()
  });
  
  toSound.setVolume(0);
  toSound.play();
  
  this.tweens.add({
    targets: toSound,
    volume: 1,
    duration: duration,
    ease: 'Linear'
  });
}

随机音高 #

javascript
playWithRandomPitch(key) {
  const sound = this.sound.add(key);
  sound.setDetune(Phaser.Math.Between(-200, 200));
  sound.play();
}

3D 音频 #

javascript
playPositionalSound(key, sourceX, sourceY, listenerX, listenerY, maxDistance) {
  const distance = Phaser.Math.Distance.Between(sourceX, sourceY, listenerX, listenerY);
  const volume = Math.max(0, 1 - distance / maxDistance);
  
  const sound = this.sound.add(key, { volume: volume });
  sound.play();
  
  const angle = Phaser.Math.Angle.Between(listenerX, listenerY, sourceX, sourceY);
  const pan = Math.cos(angle);
  
  return sound;
}

音频配置 #

全局配置 #

javascript
const config = {
  audio: {
    disableWebAudio: false,
    noAudio: false
  }
};

音频上下文 #

javascript
const context = this.sound.context;

const masterGain = this.sound.masterGain;

音频池 #

音效池 #

javascript
class SoundPool {
  constructor(scene, key, poolSize = 5) {
    this.scene = scene;
    this.key = key;
    this.pool = [];
    
    for (let i = 0; i < poolSize; i++) {
      this.pool.push(scene.sound.add(key));
    }
  }
  
  play(config = {}) {
    const sound = this.pool.find(s => !s.isPlaying);
    if (sound) {
      sound.play(config);
      return sound;
    }
    return null;
  }
}

create() {
  this.jumpSoundPool = new SoundPool(this, 'jump', 10);
}

update() {
  if (playerJumped) {
    this.jumpSoundPool.play();
  }
}

完整示例 #

音频管理器 #

javascript
class AudioManager {
  constructor(scene) {
    this.scene = scene;
    this.bgm = null;
    this.sfxVolume = 1;
    this.bgmVolume = 0.5;
    this.muted = false;
  }
  
  playBGM(key, config = {}) {
    if (this.bgm) {
      this.stopBGM();
    }
    
    this.bgm = this.scene.sound.add(key, {
      volume: this.bgmVolume,
      loop: true,
      ...config
    });
    
    this.bgm.play();
  }
  
  stopBGM(fadeOut = 0) {
    if (!this.bgm) return;
    
    if (fadeOut > 0) {
      this.scene.tweens.add({
        targets: this.bgm,
        volume: 0,
        duration: fadeOut,
        onComplete: () => {
          this.bgm.stop();
          this.bgm = null;
        }
      });
    } else {
      this.bgm.stop();
      this.bgm = null;
    }
  }
  
  pauseBGM() {
    if (this.bgm) {
      this.bgm.pause();
    }
  }
  
  resumeBGM() {
    if (this.bgm) {
      this.bgm.resume();
    }
  }
  
  playSFX(key, config = {}) {
    if (this.muted) return;
    
    return this.scene.sound.play(key, {
      volume: this.sfxVolume,
      ...config
    });
  }
  
  setSFXVolume(volume) {
    this.sfxVolume = volume;
  }
  
  setBGMVolume(volume) {
    this.bgmVolume = volume;
    if (this.bgm) {
      this.bgm.setVolume(volume);
    }
  }
  
  mute() {
    this.muted = true;
    this.scene.sound.setMute(true);
  }
  
  unmute() {
    this.muted = false;
    this.scene.sound.setMute(false);
  }
  
  toggleMute() {
    if (this.muted) {
      this.unmute();
    } else {
      this.mute();
    }
    return this.muted;
  }
}

class GameScene extends Phaser.Scene {
  create() {
    this.audioManager = new AudioManager(this);
    
    this.audioManager.playBGM('background');
    
    this.input.keyboard.on('keydown-M', () => {
      this.audioManager.toggleMute();
    });
  }
  
  playerJump() {
    this.audioManager.playSFX('jump');
  }
  
  collectCoin() {
    this.audioManager.playSFX('coin');
  }
}

下一步 #

现在你已经掌握了音频系统,接下来学习 补间动画,了解如何创建更复杂的动画效果!

最后更新:2026-03-29