Idea to Code

アイデアをコードへ
独学でプログラミング関係にいろいろ手を出すサイト

hawk

JavaScript

ベアタッチ2015/11/28

クマをクリックするゲームをenchant.jsを使って作ってみた

ゲーム本体はこちら

- 遊び方 -
STARTをクリックするとゲームがスタート
制限時間30秒以内にクマをたくさんクリックしよう
は1pt、は3pt、は5pt もらえるぞ
時間切れになったら終了
GAMEOVERをクリックするとスタート画面に戻るぞ
(誤クリックを防ぐために1秒待ち時間あり)
main.js
enchant();                                // enchant.jsの利用を開始

// グローバル定数
var WINDOW_SIZE = 500;                    // ウィンドウサイズ
var SPRITE_SIZE = 32;                      // クマのサイズ
var GAME_TIME = 30;                        // 制限時間

// クマクラスを作成
Bear = Class.create(Sprite,               // Spriteクラスを継承
  { initialize : function(scene){         //初期化する
    Sprite.call(this,32,32);               //Spriteオブジェクトを初期化
    this.image = game.assets["chara1.png"];  // 画像を設定
    this.inScene = scene;                  // 親シーンを参照
    this.init();                          // 初期化
  },
  //enterframeイベントのリスナーを定義する
  onenterframe : function(){
    if (this.frame != 3 && this.frame != 8 && this.frame != 13) { // 泣き状態でないなら
      this.x += this.vx;                 // 横方向に移動
      this.y += this.vy;                 // 縦方向に移動
      var flag = false;                    // 枠外フラグをfalseに
      if (this.x < 0) {                   // 左端なら
        this.x = WINDOW_SIZE;             // 右端に移動
        flag = true;                      // 枠外フラグをtrueに
      }
      if (this.x > WINDOW_SIZE) {           // 右端なら
        this.x = 0;                       // 左端に移動
        flag = true;                      // 枠外フラグをtrueに
      }
      if (this.y < 0) {                   // 上端なら
        this.y = WINDOW_SIZE;             // 下端に移動
        flag = true;                      // 枠外フラグをtrueに
      }
      if (this.y > WINDOW_SIZE) {         // 下端なら
        this.y = 0;                       // 上端に移動
        flag = true;                      // 枠外フラグをtrueに
      }
      this.frame = [1, 0, 2, 0][this.age % 4] + 5 * this.type; // フレームを更新(1->0->2->0->1->...)
      if (flag && this.age > (40 + rand(11))) {  // 枠外かつageが40+(0~10)より多いなら
        this.inScene.removeChild(this);  // 一旦クマを削除
        this.init();                      // クマを初期化して追加
      }
    }
  },
  //touchendイベントのリスナーを定義する
  ontouchend : function(){
    if (!this.touch_flag && this.active) {  // タッチされていないかつアクティブなら
      this.touch_flag = true;              // タッチフラグをtrueに
      this.frame = 3 + 5 * this.type;    // フレームを泣きクマに
      game.score += 1 + 2 * this.type;    // クマに応じてスコアを加算
      this.score.x = this.x + 5;          // +スコアの表示横位置を設定
      this.score.y = this.y + SPRITE_SIZE * 1.5;// +スコアの表示縦位置を設定
      this.inScene.addChild(this.score);  // +スコアを追加
      var THIS = this;                    // this参照を作成
      setTimeout(function(){              // 一定時間後に実行
        try {                              // 削除できない場合がある
          THIS.inScene.removeChild(THIS.score); // スコアテキストを削除
          THIS.inScene.removeChild(THIS); // クマを削除
        }catch(e){}                        // なにもしない
        setTimeout(function(){            // 一定時間後に実行
          if (THIS.active){                // クマがアクティブなら
            THIS.init();                  // クマを初期化
          }
        }, 500);                          // 0.5秒後に実行
      }, 1000);                            // 1秒後に実行
    }
  },
  // 初期化関数
  init : function(){
    this.type = rand(10) > 2 ? 0 : rand(10) > 2 ? 1 : 2;  // クマの種類を決定(普通70%白21%リボン9%)
    this.x = rand(WINDOW_SIZE - SPRITE_SIZE);  // 横位置を設定
    this.y = rand(WINDOW_SIZE - SPRITE_SIZE);  // 縦位置を設定
    var num = this.type * 2 + 2;          // 速度生成用値を作成
    this.vx = Math.floor((rand(num) + num) * ((rand(2) > 0) ? 1 : -1));  // 横軸方向の速度を設定
    this.vy = Math.floor((rand(num) + num) * ((rand(2) > 0) ? 1 : -1));  // 縦軸方向の速度を設定
    this.frame = [0, 5, 9][this.type];    // フレームを設定
    this.scaleX = 1.5;                    // クマを1.5倍化
    this.scaleY = 1.5;                    // クマを1.5倍化
    if(this.vx < 0)                        // クマが左に進むなら
      this.scaleX *= -1;                  // スプライトを反転(左向きに)
    this.score = new Label("+" + (1 + 2 * this.type) + "pt");// +スコアのテキストを設定
    this.age = 0;                          // ageを0に戻す
    this.touch_flag = false;              // タッチフラグを設定
    this.active = true;                    // クマをアクティブに
    this.inScene.addChild(this);          // クマをシーンに追加
  }
});

window.onload = function(){
    game = new Game(WINDOW_SIZE, WINDOW_SIZE);  // gameオブジェクト生成

    game.fps = 15;                        // fpsを設定  

    game.preload("chara1.png", "start.png", "end.png");  // 画像の読み込み
    
    var bears = [];                        // クマたちを初期化
    var startScene = new Scene();          // スタートシーン
    var gameScene = new Scene();          // ゲームシーン
    var endScene = new Scene();            // エンドシーン
    
    game.onload = function(){            // ゲームが読み込まれたら実行
      scoreLabel = new Label("");          // ラベルを作成  
      scoreLabel.x = scoreLabel.y = 8;    // 位置を設定
      scoreLabel.addEventListener('enterframe', function(){  // エンターフレームイベントを作成
        var time = GAME_TIME - game.frame/game.fps;  // 時間を算出
        if(time < 0){                      // 0秒を超えていたら
          setTimeout(function(){          // 一定時間後に実行  
            end_flag = true;              // リスタート可に
          }, 1000);                        // 1秒後に実行
          time = 0;                        // 時間を初期化
          clearBear(bears);                // クマたちを削除
          gameScore.text = "SCORE : " + game.score + "pt";  // スコアを表示
          game.pushScene(endScene);        // シーンを切り替え
        }
        this.text = "SCORE: " + game.score + " TIME: " + time.toFixed(2);  // スコア表示を更新
      });
      gameScene.addChild(scoreLabel);      // ゲームシーンに追加
      
      game.score = 0;                      // スコアを初期化
      
      var title = new Sprite(236, 48);    // タイトルスプライトを作成
      title.image = game.assets["start.png"];  // 画像を設定
      title.x = (WINDOW_SIZE - 236) / 2;  // 横位置を設定
      title.y = (WINDOW_SIZE - 48) / 2;    // 縦位置を設定
      startScene.addChild(title);          // スタートシーンに追加
      title.addEventListener("touchstart", function(){  // タッチスタートイベントを設定
        for(var i=0; i<8; i++)            // 8回繰り返す
          bears[i] = new Bear(gameScene);// クマを1頭追加
        game.frame = 0;                    // 時間を初期化
        game.score = 0;                    // スコアを初期化
        end_flag = false;                  // リスタート可フラグをfalseに
        game.popScene();                  // スタートシーンを取り出し
      });
      
      var gameScore = new Label();        // ラベルを作成
      gameScore.x = (500 - 187) / 2;      // 横位置を設定
      gameScore.y = 140;                  // 縦位置を設定
      gameScore.font = "32px monospace bold";  // フォントを設定
      endScene.addChild(gameScore);        // エンドシーンに追加
      
      var end = new Sprite(187, 97);      // エンドスプライトを作成
      end.image = game.assets["end.png"];  // 画像を設定
      end.x = (WINDOW_SIZE - 187) / 2;    // 横位置を設定
      end.y = (WINDOW_SIZE - 97) / 2;      // 縦位置を設定
      endScene.addChild(end);              // エンドシーンに追加
      end.addEventListener("touchstart", function(){  // タッチスタートイベントを設定
        if (end_flag) {                    // リスタート可なら
          end_flag = false;                // リスタートを不可に
          game.frame = 0;                  // 時間を初期化
          scoreLabel.text = "SCORE: 0 TIME: 0.00";  // スコア表示を更新
          game.popScene();                // エンドシーンを取り出し
          game.pushScene(startScene);      // スタートシーンを追加
        }
      });
      game.pushScene(gameScene);          // ゲームシーンを追加
      game.pushScene(startScene);          // スタートシーンを追加
    };
    game.start();                          // ゲームをスタート
};

// クマたちを削除 引数はクマたち
function clearBear(bears){
  for(var i=0; i < bears.length; i++){    // クマの頭数だけ繰り返す
    bears[i].active = false;              // クマを非アクティブに
    try {
      bears[i].inScene.removeChild(bears[i].score);  // スコアを削除(setTimeoutにより削除できないタイミングがある)
      bears[i].inScene.removeChild(bears[i]);// クマを削除(setTimeoutにより削除できないタイミングがある)
    }catch(e){}
  }
}

// 0から(num-1)までの乱数を返す 引数は数
function rand(num){
    return Math.floor(Math.random() * num);  // 乱数を返す
}