(C)WorldWideSoftware

<!DOCTYPE html>
<html lang="ja">
 <head>
  <meta charset="utf-8">
  <title>ブロックの落下処理</title>
 </head>
 <body>
  <canvas id="bg" width="480" height="480"></canvas><br>
  <a href="http://www.wwsft.com">(C)WorldWideSoftware</a><br>
【説明】ブロックを落下させる処理のサンプルです。
緑色の支柱をタップすると壊れ、上にあるブロックが落下します。
操作はしっかり目にタップしてください。
<br>
<strong>
※このような処理は各ブロックをオブジェクトとして定義し移動する方法もありますが、このサンプルはBGデータのみで処理を行っています。
</strong>
<br>
<a href="block00src.html">ソースコードの確認</a>

  <script>
  //描画面(キャンバス)の準備
  var cvs = document.getElementById("bg");
  var ctx = cvs.getContext("2d");

  //クリックとタップの判定
  var tapX = 0, tapY = 0, tapC = 0;
  cvs.addEventListener("touchstart", touchStart);
  cvs.addEventListener("touchend", touchEnd);
  function touchStart(ev) {
   var rect = ev.target.getBoundingClientRect();
   tapX = ev.touches[0].clientX-rect.left;
   tapY = ev.touches[0].clientY-rect.top;
   tapC = 1;
  }
  function touchEnd(ev) {tapC = 0;}

  cvs.addEventListener("mousedown", mouseDown);
  cvs.addEventListener("mouseup", mouseUp);
  function mouseDown(ev) {
   var rect = ev.target.getBoundingClientRect();
   tapX = ev.clientX-rect.left;
   tapY = ev.clientY-rect.top;
   tapC = 1;
  }
  function mouseUp(ev) {tapC = 0;}

  //ブロックを配列で定義する
  //1が支柱 2がブロック 例えば2が横に3つ並んでいればそれが一まとまりのブロックとなる
  var map = [
   [ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2],
   [ 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0],
   [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
   [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
   [ 0, 0, 2, 2, 2, 2, 2, 2, 0, 1, 0, 0],
   [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
   [ 0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 0, 0],
   [ 0, 2, 2, 2, 2, 2, 0, 0, 0, 1, 0, 0],
   [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0],
   [ 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0],
   [ 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
   [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
  ];

  //画像の読み込み
  var img = [], iOK = [];
  function loadImg(n, fname) {
   iOK[n] = false;
   img[n] = new Image();
   img[n].src = fname;
   img[n].onload = function() { iOK[n] = true; }
  }

  loadImg(1, "pillar.png");
  loadImg(2, "block.png");

  //メイン処理
  function mainProc() {
   var n, x, y;

   ctx.fillStyle = "black";
   ctx.fillRect(0, 0, 480, 480);

   //タップの判定
   if(tapC == 1) {
    x = parseInt(tapX/40);
    y = parseInt(tapY/40);
    if(map[y][x] == 1) map[y][x] = 0;//柱があれば壊す
   }

   //BG描画
   for(y=0; y<12; y++)
   for(x=0; x<12; x++) {
    n = map[y][x];
    if(n > 0) {
     if(iOK[n] == true) ctx.drawImage(img[n], x*40, y*40);
    }
   }

   //ブロックを落下させる処理
   y = 10;
   x = 0;
   do {//マップデータを一番下の行から検索(操作)する

    var bn =  0;//y行にブロックや柱があるかを数える
    var bx = -1;//ブロックや柱がある場合、左端の位置
    var bp =  0;//その下に柱やブロックがあるか

    while(true) {//ブロックや柱があるか調べていく
     if(map[y][x] > 0) {//ある
      bn++;//数えて
      if(bx == -1) bx = x;//左端の位置を保持
      if(map[y+1][x] > 0) bp = 1;//下に何かあればフラグを立てる
     }
     x++;
     if(x == 12) break;//右端まで調べた
     if(map[y][x] == 0 && bn > 0) break;//ブロックor柱終わり
    }

    if(bn > 0) {//ブロックか柱がある場合
     if(bp == 0) {//下に何も無いなら落とす
      for(n=bx; n<bx+bn; n++) { map[y+1][n]=map[y][n]; map[y][n]=0; }
     }
    }//残りの部分も検索するのでx,yともに変更しない

    if(bn==0 || x==12) {//落とす必要なしor右端まで検索したら、次の行へ進む
     x=0;
     y--;
    }
   } while(y >= 0);

  }

  setInterval(mainProc, 250);
  </script>
 </body>
</html>

←動作確認に戻る