このページの本文へ

PROGRAMMING 古籏一浩のJavaScriptラボ第91回

DeviceOrientation Eventでブロック崩し作ってみた

2012年07月26日 13時00分更新

古籏一浩

  • この記事をはてなブックマークに追加
本文印刷

ボールとブロックの当たり判定

 ブロックが表示できたら、ゲームに必要な当たり判定の処理を追加します。スカッシュではパドルとボールの衝突を判定するだけでしたが、ブロック崩しの場合はボールとすべてのブロックとの衝突も判定する必要があります。

 判定にはパドルとボールの処理と同様にintersect()メソッドを使い、for文を使ってブロックの数だけ当たり繰り返します。ブロックとボールが当たっている場合はブロックのY座標を-9999に設定してブロックを非表示にします。-9999は画面に表示されない座標値であれば何でも構いません。この方法なら、ブロックを削除したり、ブロックの有無を示すフラグを用意したりせずに済みます。

 ブロックとボールが当たったらスコアに5点を加算し、すべての当たり判定が終わった後にラベルのtextプロパティにスコアを設定します。

 最後に、ブロックの総数を示す変数totalから1を引き、totalが0になったら再度ブロックを描画してゲームを継続させます。


function hitCheck_block_ball(){
  for(var i=0; i<count; i++){
    if (ball.intersect(block[i])){
      ball.dy = -ball.dy;  // 接触した場合はボールのY方向の移動量を逆にする
      block[i].y = -9999// 見えない場所に移動
      game.score = game.score + 5;  // スコアを加算(5点)
      total = total - 1// 総ブロック数から1を引く
      if (total < 1){  // 全部消したか調べる
        drawBlock();  // ブロックを再描画
      }
    }
  }
  scoreLabel.text = "SCORE : "+game.score;
}

 以上でブロック崩しの基本的なプログラムができあがりました。実際のプログラムがサンプル3です。なお、今回はフレームレートを60に設定していますので、前回のスカッシュと比べてボールやパドルがスムーズに移動します。

■サンプル3


enchant(); // ライブラリーの初期化
window.onload = function(){
  var game = new Game(240, 320); // 240×320画面(Canvas)を作成
  game.fps = 60// フレームレートの設定。60fpsに設定
  // 画像データをあらかじめ読み込ませる
  game.preload("images/pad.png","images/ball.png", "images/block.png");
  game.rootScene.backgroundColor = "blue";  // ゲームの背景色を青色に設定
  game.score = 0// スコアを入れる変数を用意する
  // スコアを表示するラベルを作成
  var scoreLabel = new Label("SCORE : 0");
  scoreLabel.font = "16px Tahoma";
  scoreLabel.color = "white";
  scoreLabel.x = 10// X座標
  scoreLabel.y = 5; // Y座標
  game.rootScene.addChild(scoreLabel);
  // ブロックの総数を入れるカウンタ変数
  var count = 0;
  // ブロックを格納する配列
  var block = new Array();
  // 消したブロックの総数を入れる変数
  var total = 0;
  // データの読み込みが完了したら処理
  game.onload = function(){
    // ボールの設定
    var ball = new Sprite(16, 16);
    ball.image = game.assets["images/ball.png"];
    ball.x = 0// X座標
    ball.y = 130; // Y座標
    ball.dx = 1.5// X方向の移動量
    ball.dy = 2.5// Y方向の移動量
    game.rootScene.addChild(ball);
    // パドルの設定
    var pad = new Sprite(32, 16);
    pad.image = game.assets["images/pad.png"];
    pad.x = game.width/2; // X座標
    pad.y = game.height - 40; // Y座標
    game.rootScene.addChild(pad);
    // ブロックを描く
    drawBlock();
    // フレームイベントが発生したら処理
    game.rootScene.addEventListener(Event.ENTER_FRAME, function(){
      moveBall();   // ボールを移動させる
      movePaddle(); // パドルを移動させる(キーボード対応)
      hitCheck_paddle_ball();  // パドルとボールの接触判定
      hitCheck_block_ball(); // ボールとブロックの接触判定
      // =============== 各種処理 ==================
      // ------------ ■ボールを移動させる -----------------
      function moveBall(){
        ball.x = ball.x + ball.dx; // X方向の移動量を加算
        ball.y = ball.y + ball.dy; // Y方向の移動量を加算
        // 画面外かどうか調べる
        if ((ball.x < 0) || (ball.x > (game.width-ball.width))){ ball.dx = -ball.dx; }
        if (ball.y < 0){ ball.dy = -ball.dy; }
        // ボールが下まで行ったらゲームオーバー
        if(ball.y > game.height){
          game.stop();
          alert("スコアは"+game.score+"点でした");
        }
      }
      // ------------ ■パドルを移動させる -----------------
      function movePaddle(){
        var n = game.input.analogX / 4;
        pad.x = pad.x + n; // パドルを移動
        if (pad.x < 0){ pad.x = 0; }  // 左端かどうか調べる
        if (pad.x > (game.width-pad.width)){ pad.x = game.width-pad.width; }  // 右端かどうか調べる
      }
      // ------------ ■パドルとボールの接触判定を行う -----------------
      function hitCheck_paddle_ball(){
        if (pad.intersect(ball)){
          ball.dy = -ball.dy;  // 接触した場合はボールのY方向の移動量を逆にする
          ball.y = pad.y - ball.height - 1; // うまく跳ね返るように調整
          game.score = game.score + 10; // スコアを加算(10点)
          scoreLabel.text = "SCORE : "+game.score;
        }
      }
      // ------------ ■ブロックとボールの接触判定を行う -----------------
      function hitCheck_block_ball(){
        for(var i=0; i<count; i++){
          if (ball.intersect(block[i])){
            ball.dy = -ball.dy;  // 接触した場合はボールのY方向の移動量を逆にする
            block[i].y = -9999// 見えない場所に移動
            game.score = game.score + 5;  // スコアを加算(5点)
            total = total - 1// 総ブロック数から1を引く
            if (total < 1){  // 全部消したか調べる
              drawBlock();  // ブロックを再描画
            }
          }
        }
        scoreLabel.text = "SCORE : "+game.score;
      }
    });
  }
  // 傾きセンサーを設定(Android/iOS共通)
  window.addEventListener("deviceorientation", function(evt){
    game.input.analogX = evt.gamma;  // 横方向の傾斜角度
  }, false);
  // ゲーム処理開始
  game.start();
  // ------------ ブロックを描く -----------------
  function drawBlock(){
    count = 0// ブロックの総数を示すカウンタを0にする
    // ボールの設定を縦横の数だけ繰り返し生成
    for(var y=0; y<5; y++){
      for(var x=0; x<7; x++){
        block[count] = new Sprite(24, 12);
        block[count].image = game.assets["images/block.png"];
        block[count].x = x * 32+12// X座標
        block[count].y = y * 18 + 30; // Y座標
        game.rootScene.addChild(block[count]);
        count = count + 1// ブロックの総数を示すカウンタを増やす
      }
    }
    total = count; // 消すブロックの総数を変数に入れる
  }
}
Web Professionalトップページバナー

この記事の編集者は以下の記事をオススメしています

ASCII.jp会員サービス 週刊Web Professional登録

Webディレクター江口明日香が行く