2012年5月5日土曜日

[Metal Bear Solid] enchant.js でまずは動くものを

enchant.js を使っていち早くゲームらしきものを作るという目的で Metal Bear Solid なる完全に名前先行のゲームを作成しました。



すべてのソースコードは jsdo.it に記載しております。
(大変申し訳ありませんが、chrome で正常に動きません。safari、スマホ実機なら動きます。次回からはこの点注意して作成します。)











まずは本ブログにも記載しております、タップした位置に熊が移動するというプログラムを活用しました。

参照: 2. タップした方向に向かって、クマが進むようにしましょう



当たり死亡判定つきの針群


Metal Gear Solid のように隠れるだけではなく、隠れている壁にも当たり死亡判定をつけたらどうかと思いましたので、そこのところを実装しました。明らかに当たってはダメそうな針の画像を使用しました。








背景(マップ)は下記のように実装できますし、壁としての当たり判定をつける記述方法もあるようですが、当たった後に死亡させるためには、針はマップとしてではなく、Sprite として作成しました。


背景はタイル図柄で埋めました。

    var map = new Map(game.blockSize, game.blockSize);
    map.image = game.assets['./images/map0.gif'];
    map.loadData([
      [  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5],
      [  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5],

                         (中略)

      [  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5],
      [  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5]
    ]);
    game.rootScene.addChild(map);


針画像は同じものをいくつも作るのでクラス化しました。

var objs = new Array(1);

  var ObjectA = Class.create(Sprite, {
    initialize: function(x, y, n){
      Sprite.call(this, 16, 16);
      this.image = game.assets['./images/map0.gif'];
      this.frame = 16;
      this.moveTo(x, y);
      objs[n] = this;
      game.rootScene.addChild(this);
    },
  });



ObjectA という見事にダメな例の代表みたいな名前が付いておりますが、下記のように、x 座標、y 座標、objs で呼び出すための番号を引数として渡すことで、配置と for 文を利用した当たり判定をつけることができました。


var obj00 = new ObjectA(0, 50, 0);



      for(i = 0; i < objs.length; i++){
        if(this.within(objs[i], 16) == true){
            this.isDead = true;
            break;
        }
      }





敵キャラ見つかり判定 


左右に移動している敵キャラ(girl)に熊が見つかった際に死亡する記述です。





熊と敵キャラが同じ直線上に存在した場合に、爆発画像(bomb)が熊の上に乗っかることで熊の死亡を表しています。
爆発画像は死亡時以外は画面外に置いておき、熊死亡 or 敵キャラ死亡時にリサイクルできるようにしています。

ユーザから見た場合、はじめはなぜ熊が死亡しているかがいまいち直観的でないように実装してしまったため、次回から改善したいと思います。


    var girlEnterFrameFunc = function(){
      
      if(this.x <= 0){
        this.movex = 1;
      }else if(this.x >= 203){
        this.movex = -1;
      }
      if(this.x > 16 && this.x < 64){
        if(bear.x > 16 && bear.x < 64){
          bear.isDead = true;
          bomb.moveTo(bear.x + 8, bear.y + 8);
        }
      }else if(this.x > 96 && this.x < 144){
        if(bear.x > 96 && bear.x < 144){
          bear.isDead = true;
          bomb.moveTo(bear.x + 8, bear.y + 8);
        }
      }else if(this.x > 176){
        if(bear.x > 176){
          bear.isDead = true;
          bomb.moveTo(bear.x + 8, bear.y + 8);
        }
      }
      
      
      
      this.x += this.movex * this.speed;
    };
    
    girl.addEventListener("enterframe", girlEnterFrameFunc);






クリア演出


ゴールには明らかに取るといいことありそうな宝箱の画像を使用しました。






クリア後におめでたい感じを出すために、エヴァの最終回風演出をするんだ!と先に意気込んで決めていましたが、時間差でおめでとうコメントを出すのに苦戦しました。






まずは、針と同様におめでとうクラスを作成し、x 座標、y 座標、Array に入れるための番号、セリフを引数としました。

var Omedeto = Class.create(Label, {
  initialize: function(x, y, n, word){
    Label.call(this, word);
    this.moveTo(x, y);
    omes[n] = this;
  },
});



次に、1 回の実行ごとにセリフを画面に表示させる function を実装。

var omeCount = 0;
var omes = new Array(1);
function omedeto(){
  
  if(omeCount == omes.length){
    clearInterval(omeInterval); 
  }else{
    game.rootScene.addChild(omes[omeCount]);
  }
  
  omeCount++;
}




最後に、1 秒に 1 回上記を実行するように実装。

    var ending = function(){
      
      
      var clearLabel = new Label("CLEAR!");
      clearLabel.font = "50px cursive";
      clearLabel.moveTo(30, 100);
      game.rootScene.addChild(clearLabel);
      
      
      var ome00 = new Omedeto(30, 250, 0, "おめでとう");
      var ome01 = new Omedeto(60, 220, 1, "めでたいな");
      var ome02 = new Omedeto(140, 260, 2, "おめでとさーん");
      var ome03 = new Omedeto(160, 230, 3, "クエックエッ");
      
      
      function startInterval(){
        omeInterval = setInterval("omedeto()", 1000);
      }
      startInterval();
      
    };







なんとかゲームの形をしたものができました。

その他、死亡後に画面タップでゲームリセットできるようにしました。リセット時に敵キャラの位置が毎回デフォルト位置に戻っているよりも熊だけがデフォルト位置に戻っていることにより、毎回同じスタートにならないようになっております。


次回作へ向けて 

  •  説明のいらない直観的ゲーム作りを徹底
  • chrome、safari で正常動作するか確認しながら実装
  • 実は熊の左右の向きが頑健なプログラムではないため、そこを改良
  • 面白いゲーム作り 

友人にスマホでプレイしてもらったところ、画面をタップしっぱなしにすることでそこに熊が付いてくると判断したようです。

今回の実装では、タップし直すことによる熊の再移動はありますが、タップしっぱなしによる熊の再移動は実装していなかったため、直観的動きにするためには、やはりタップしっぱなし対応が必要かと思いました。


Metal Bear Solid 2 をご期待ください。