enchant.jsでブラウザゲームを作るといつもサウンドで躓きます。
GoogleChromeだと動くのにIEだと止まるやん!原因究明のために、F12キー押してデバック見てみると、大抵サウンド部分でエラーを検出していたりします。
その中でも一番面倒だったループBGM再生を、どんな環境でも再生できる形でクラス化したのでお使いください。
まずは動作原理から説明します。
実はブラウザによってループ再生方法が変わる
enchant.jsにおける音再生ですが、ブラウザによって二通りの実装方法があります。
ちなみに、話は逸れますが、iOSで音を鳴らす際は以下のコードを上の方に貼ってください。
enchant.Sound.enabledInMobileSafari = true;//iOSでがなるようにする
(1)サウンドループフラグによりループ
Sound.play(); Sound.src.loop = true;
(2)enterframeによりループ
game.onenterframe=function(){ //enterframeイベントのイベントリスナー Sound.play(); };
これのどちらかで再生ができます。ただ、
(1)が可能なブラウザが(2)を実行すると、音再生が毎フレームごとに実行されてしまいますし、
(2)が可能なブラウザが(1)を実行すると、エラーが出てしまいます。
そこで、Sound.srcが存在するか否かで(1)か(2)のどちらを使用するか分けられるようにします。
その処理を加えたクラスが以下のコードです。
コード
//サウンドクラス SoundLoop = Class.create(Sprite, { Sound, SFlg:0, game, initialize:function(_game){ //クラスの初期化(コンストラクタ) game=_game; Sprite.call(this,0,0); //スプライトの初期化 SFlg=0; game.onenterframe=function(){ //enterframeイベントのイベントリスナー if(SFlg==1){ try{ if(!Sound.src){ //もしSound.srcがないならenterframeによるループ再生 Sound.play(); } }catch(e){} } }; }, Set:function(_Sound){ Sound=_Sound; SFlg=0; try{ Sound.stop(); }catch(e){} Sound=game.assets[Sound]; try{ // もしSound.srcがあるなら、ループ再生フラグをtrueにする。 if(Sound.src){ Sound.play(); Sound.src.loop = true; } }catch(e){} SFlg=1; }, Stop:function(Sound){ try{ Sound.stop(); SFlg=0; }catch(e){} } }); //サウンドクラスここまで
使い方
//音読み込み var M_Coin="sound/Coin.wav"; game.preload([M_Coin]); var M_Sound=new SoundLoop(game); //gameクラスを引数にして宣言 M_Sound.Set(M_Coin);//ループBGMのファイルパスを引数にするとループ再生 M_Sound.Set(M_Coin);//Set二回目以降は直前のBGMを停止した後ループ再生 Sound.Stop();//ループBGMの停止
コメント
[…] ・サウンドループクラス付(http://hothukurou.firebird.jp/blog/loopsound に詳細を説明しています。) […]
はじめまして、BGMループクラス使わせていただきました。
使わせていただいたのですが
var M_Sound = new SoundLoop(core);
の部分でSoundLoop is not a constructorとエラーが出てしまいます。
(gameの部分はcoreに変えました。)
どうすればよいでしょうか。
目薬さん
ご使用の報告をくださり、ありがとうございます!
もし使いづらかったり、改善点を発見しましたら、ご報告いただけましたら改善いたします。
解決いたしました。
お騒がせしてすみません。
サウンドクラス使わせていただきます。
使おうと思ったのですが、 Sound,SFlg:0,game,のgameの所でエラーが出るのですがなぜでしょうか?
エラーメッセージを見るとヒントがわかるかもしれません。
エラーメッセージを教えていただけますか。
お世話になっております。
> 使おうと思ったのですが、 Sound,SFlg:0,game,のgameの所でエラーが出るのですがなぜでしょうか?
本クラスを使用させていただいたところ、私も同様のエラーが発生しました。
エラーメッセージは以下の通りです。
Script.js:890 Uncaught ReferenceError: game is not defined at window.onload (Script.js:890)
また、OSはWindows10、ブラウザはGoogleChromeを使用しております。
プラム様
お世話になります。
エラー内容から推測するに、 loopSoundの引数game にenchant.jsのgame オブジェクトが代入されていないことが原因かと思います。
以下のように事前にgameObjectが定義されていることをご確認いただけますか。
const game = new Game(400,400); // (w,h)=(400,400)でgameオブジェクトを定義
const loopSound=new SoundLoop(game); //gameオブジェクトを代入
(この記事執筆当初と異なり、es6以降の書き方にしています。ご了承ください。)