Firefox OSでゲームアプリを動かしてみる！～ PHASERを使ってゲームアプリを動かしてみた （その4）～

# Firefox OSでゲームアプリを動かしてみる！～ PHASERを使ってゲームアプリを動かしてみた （その４）～

[前回](http://qiita.com/onaona/items/a3f528bc942b6bfb3514)でゲームの操作ができるようになりました。
![invaders-fourth.gif](https://qiita-image-store.s3.amazonaws.com/0/70507/c9022936-8085-cd1c-cb9d-f50e701480fb.gif)

今回はゲームの効果音とバックグラウンドで音楽を流すことをしてみたいと思います。
[PHASER](https://phaser.io/)は"Audioサンプル":http://phaser.io/examples/v2/category/audio も多くあるので以下のサンプルを参考にします。

* ゲームの効果音：　"audio-sprite":http://phaser.io/examples/v2/audio/audio-sprite
１つのAudioファイルに複数の効果音を含めるサンプルです。ゲームの効果音をサンプルに使っているので参考にします。

* バックグラウンドの音楽： "restart-sound":http://phaser.io/examples/v2/audio/restart-sound
Audioファイルの再生、リスタートのサンプルです。サンプルの音楽が軽やかでシューティングゲームのバックグラウンドにしたらおもしろそうなので参考にします。

1回目に"ダウンロードしたサンプル":http://phaser.io/examples/v2/games/invaders#download の中に上のAudioサンプルも入っているので、Audioファイルをコピーします。

<pre>
INVADERS
│  index.html
│  invaders.js 
│  manifest.webapp　
│  phaser.2.2.2.min.js
│  
└─assets
    ├─audio
    │  │  oedipus_wizball_highscore.ogg // 追加ファイル
    │  │  
    │  └─SoundEffects
    │          fx_mixdown.ogg // 追加ファイル
    │          
     └─games
        ├─invaders　             ※3
        │      bullet.png
        │      enemy-bullet.png
        │      explode.png
        │      invader32x32x4.png
        │      player.png
        │      starfield.png
        │      
        └─starstruck
                background2.png　 ※4
</pre>


ゲームに音を付けることができました。

**invaders.jsの修正**
修正した内容は以下です
* バックグラウンドで音声を流す
* ゲームに効果音を付ける
プレイヤーの弾の発射音
弾が敵に当たったときの音
プレイヤーが弾に当たった時の音（残機のあり、なしで音を分ける）

基本的にサンプル通りに作って動きましたが、Audioファイルのデコードに時間がかかりゲームを開始してから音が鳴るまで３秒ほどかかる問題が出ました。
対応としてデコードの間は「Loading...」を表示してデコードが完了したらゲームを開始するようにしています（"参考ページ":http://www.html5gamedevs.com/topic/1453-audio-delay/）


<pre><code class="diff">
@@ -10,6 +10,8 @@ function preload() {
     game.load.spritesheet('kaboom', 'assets/games/invaders/explode.png', 128, 128);
     game.load.image('starfield', 'assets/games/invaders/starfield.png');
     game.load.image('background', 'assets/games/starstruck/background2.png');
+    // バックグラウンド用Audioファイルのロード
+    game.load.audio('bMusic', ['assets/audio/oedipus_wizball_highscore.ogg']);
+    // 効果音用Audioファイルのロード
+    game.load.audio('sfx', ['assets/audio/SoundEffects/fx_mixdown.ogg']);
 
 }
 
@@ -29,11 +31,29 @@ var enemyBullet;
 var firingTimer = 0;
 var stateText;
 var livingEnemies = [];
+var bMusic;
+var sfx;
+var isMovedAliens = false;
 
 function create() {
 
     game.physics.startSystem(Phaser.Physics.ARCADE);

+    // バックグラウンド用のAudioファイルの再生. bMusic.playの第4引数をtrueにすることでRepeat再生 
+    bMusic = game.add.audio('bMusic');
+    bMusic.play('', 0, 1, true);


+    // 効果音用Audioファイルの各エフェクトが参照できるようにマークを付ける
+    sfx = game.add.audio('sfx');
+    sfx.allowMultiple = true;
+    sfx.addMarker('alien death', 1, 1.0);
+    sfx.addMarker('boss hit', 3, 0.5);
+    sfx.addMarker('escape', 4, 3.2);
+    sfx.addMarker('meow', 8, 0.5);
+    sfx.addMarker('numkey', 9, 0.1);
+    sfx.addMarker('ping', 10, 1.0);
+    sfx.addMarker('death', 12, 4.2);
+    sfx.addMarker('shot', 17, 1.0);
+    sfx.addMarker('squit', 19, 0.3);
+
     //  The scrolling starfield background
     starfield = game.add.tileSprite(0, 0, game.world.width, game.world.height, 'starfield');
 
@@ -68,6 +88,7 @@ function create() {
     aliens.physicsBodyType = Phaser.Physics.ARCADE;
 
     createAliens();
+    // Audioファイルのデコードが終わるまではエイリアンは表示しない
+    aliens.visible = false;
 
     //  The score
     scoreString = 'Score : ';
@@ -82,6 +103,9 @@ function create() {
     stateText.anchor.setTo(0.5, 0.5);
     stateText.visible = false;
 
+    // Audioファイルのデコードが終わるまではLoading...を表示する
+    stateText.text = " Loading...";
+    stateText.visible = true;
+
     for (var i = 0; i < 3; i++) 
     {
         var ship = lives.create(game.world.width - 100 + (30 * i), 60, 'ship');
@@ -95,7 +119,20 @@ function create() {
     explosions.createMultiple(30, 'kaboom');
     explosions.forEach(setupInvader, this);
 
-    
+}
+
+// Audioファイルのデコードが終わった後にエイリアンを動かすための関数
+function moveAliens() {
+    if(!isMovedAliens)
+    {
+        //  All this does is basically start the invaders moving. Notice we're moving the Group they belong to, rather than the invaders directly.
+        var tween = game.add.tween(aliens).to( { x: 200 }, 2000, Phaser.Easing.Linear.None, true, 0, 1000, true);
+
+        //  When the tween loops it calls descend
+        tween.onLoop.add(descend, this);
+        stateText.visible = false;
+        aliens.visible = true;
+        isMovedAliens = true;
+    }
 }
 
 function createAliens () {
@@ -115,11 +152,7 @@ function createAliens () {
     aliens.x = game.world.centerX - (aliens.width / 2) - 200;
     aliens.y = 80;
 
-    //  All this does is basically start the invaders moving. Notice we're moving the Group they belong to, rather than the invaders directly.
-    var tween = game.add.tween(aliens).to( { x: 200 }, 2000, Phaser.Easing.Linear.None, true, 0, 1000, true);
 
-    //  When the tween loops it calls descend
-    tween.onLoop.add(descend, this);
 }
 
 function setupInvader (invader) {
@@ -138,6 +171,13 @@ function descend() {
 
 function update() {

+    // Audioファイルのデコードが完了するまではゲーム画面を更新しない
+    if (!game.cache.isSoundDecoded('bMusic') || !game.cache.isSoundDecoded('sfx'))
+    {
+      return;
+    }
+
+    moveAliens();
+
     //  Scroll the background
     starfield.tilePosition.y += 2;
 
@@ -189,6 +229,7 @@ function collisionHandler (bullet, alien) {
     //  When a bullet hits an alien we kill them both
     bullet.kill();
     alien.kill();
+    // エイリアンに弾があたったときに効果音を鳴らす
+    sfx.play('shot');
 
     //  Increase the score
     score += 20;
@@ -230,6 +271,15 @@ function enemyHitsPlayer (player,bullet) {
     explosion.reset(player.body.x, player.body.y);
     explosion.play('kaboom', 30, false, true);
 
+    // プレイヤーに弾があたったときに効果音を鳴らす
+    if (lives.countLiving() < 1)
+    {
+        // 残機0のときの音
+        sfx.play('death');
+    }
+    else
+    {
+        // 残機が残っているときの音
+        sfx.play('meow');
+    }
+
     // When the player dies
     if (lives.countLiving() < 1)
     {
@@ -289,6 +339,7 @@ function fireBullet () {
             bullet.reset(player.x, player.y + 8);
             bullet.body.velocity.y = -400;
             bulletTime = game.time.now + 200;
+            // プレイヤーが弾を発射したときに音を鳴らす
+            sfx.play('squit');
         }
     }
</code></pre>



[PHASERを使ってゲームアプリを動かしてみた （その１）](http://qiita.com/onaona/items/ef113de5e1efdef74c93)
[PHASERを使ってゲームアプリを動かしてみた （その２）](http://qiita.com/onaona/items/9aaeb93f17869e02725f)
[PHASERを使ってゲームアプリを動かしてみた （その３）](http://qiita.com/onaona/items/a3f528bc942b6bfb3514)



[（1）enchant.jsを使ってみる](http://qiita.com/onaona/items/6f30f5239ebd61391fe2)