Phaser3 音を鳴らす

phaser

Phaser3 音を鳴らす

前回の記事
https://mijinc0.github.io/blog/post/20200821_phaser3_depth/

基本

Phaser3で音を鳴らすには(Base|Web|Html5)SoundManagerを使うことになる。

…なるのだが、Webブラウザで音を鳴らすには一つ工夫が必要になる。Chromeなどのブラウザでは、Webサイトにアクセスした途端に音が鳴ることをデフォルトで許可していないことがある。(Webサイトにアクセスした途端に音が鳴ったりすると嫌ですよね)
そのため、各ブラウザによってWebサイトで音を鳴らすための条件をクリアしないと音が鳴らせない。最も簡単で一般的な条件は “ユーザーのアクションをトリガーにする” というものである。簡単に言うと、再生ボタンを押したら音が鳴るような処理であれば、音を鳴らしても良いよとブラウザが判断するということ。(“ブラウザの自動再生ポリシー"で検索)

Phaser3のチュートリアルを雛形にゲームを作り始めると、ページにアクセスした途端に<canvas>を描写し始める。これだと、音を鳴らすことが出来ない。回避するためには、ランチャーのようなベージをはさみ、PlayGame (音が出ます)などのボタンを押すことでゲームが立ち上がるようにスクリプトを組む必要がある。

これで、ブラウザ内で起動するゲームの中で音を鳴らすことが出来るようになる。

3つのSoundManager

https://photonstorm.github.io/phaser3-docs/Phaser.Sound.BaseSoundManager.html

Phaser3には基盤となるBaseSoundManagerを継承した3つのサウンドマネージャーがある

そしてそれらが扱うサウンドオブジェクトとして、

がある。WebAudioSoundHTML5AudioSoundBaseSoundを継承しているが、NoAudioSoundBaseSoundを継承していない。

javascriptを使っている時は余り気にならないかもしれないが、typescriptを使って書いている時はこのコンテキストの違いが少し面倒で、なぜかと言うとBaseSoundクラスにはvolumeプロパティが無く、volumeプロパティはWebAudioSoundクラスとHTML5AudioSoundクラスに直接生えているため、再生開始時の音量設定は出来ても、typescriptの型としてBaseSoundなインスタンスを操作している時は(volumeプロパティが型としてないので)再生中の音の調整ができない。これだとBGMをイベントの雰囲気作りで音量を下げたいなどの時に困る。

勿論、<any>でキャストしてしまえば済む話と言ってしまえばそうだが、それを嫌う場合はサウンドオブジェクトがWebAudioSoundまたはHTML5AudioSoundであることを検査するカスタムのtypeguard関数を用意する必要がある。

音のフェード

Phaser3では標準的に音のフェード機能はない。tweenを使って自分で作る。上記でtypescriptで書いている時にサウンドオブジェクトのvolumeプロパティにアクセスする時は自家製のtypeguardが必要と書いたが、tweenを使うだけなら型の検査はすり抜けるので普通にtweenを使えば良い。

const soundConfig = {
  // 設定
}; 
const soundObject = this.scene.sound.add('bgm', soundConfig);

// fade in
this.scene.add.tween({
  targets: soundObject,
  volume: {from: 0, to: 1},
  duration: 1000,
});

sounObject.play();

参考

https://rexrainbow.github.io/phaser3-rex-notes/docs/site/audio/