テトリスを作ろう1

JavaScript

jsで定番ゲームテトリスを作ってみよう。

準備

tetris.htmlを任意の場所(desktop)に作成し、以下のように記述する。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>テトリス</title>
  <style>
      body {
        background: #ddf5ff;
      }
      #container {
        margin: 0 auto;
      }
    </style>
</head>
<body onload="init()">
    <div id="container">
      <canvas id="cvs"></canvas>
    </div>
    <script>
    //ブロック1マスの大きさ
    const blockSize = 30;
    //ボードサイズ
    const boardRow = 20;
    const boardCol = 10;
    //キャンバスの取得
    const cvs = document.getElementById("cvs");
    //2dコンテキストを取得
    const ctx=cvs.getContext("2d");
    //キャンバスサイズ
    const canvasW = blockSize * boardCol;
    const canvasH = blockSize * boardRow;
    cvs.width = canvasW;
    cvs.height = canvasH;
    //コンテナの設定
    const container = document.getElementById("container");
    container.style.width = canvasW + 'px';
    
    //描画処理
    const draw=()=>{
      //塗りに黒を設定
      ctx.fillStyle = '#000';
      //キャンバスを塗りつぶす
      ctx.fillRect(0, 0, canvasW, canvasH);
    }
    //初期化処理
    const init=()=>{
      draw();
    }
    </script> 
</body>
</html>

以下のように表示されれば成功だ。今回はキャンバスを使って描画していく。
黒い部分はゲーム背景画面となる。

四角を描画する

ブロック1マス分となる赤四角を描画してみよう。以下のハイライト部分を追記する


    //描画処理
    const draw=()=>{
      //塗りに黒を設定
      ctx.fillStyle = '#000';
      //キャンバスを塗りつぶす
      ctx.fillRect(0, 0, canvasW, canvasH);

      //塗りに赤を設定
      ctx.fillStyle="#f00";
      //x座標150,y座標150の場所に幅30,縦30の四角を描画
      ctx.fillRect(150,150,blockSize,blockSize);
    }
    

以下のように描画されれば成功だ。

テトリミノの描画

テトリスに出てくる7種類のブロックはテトリミノというらしい。

そのうちの一つをキャンバスで描画してみよう。今回テトリミノのデータは配列で扱うものとする。dwaw関数の上に2つの定数、drawの中に2重forを追記する

   //tetの1辺の大きさ
    const tetSize=4;
    //T型のtet
    let tet= [
          [0, 0, 0, 0],
          [0, 1, 0, 0],
          [1, 1, 1, 0],
          [0, 0, 0, 0],
        ];
    //描画処理
    const draw=()=>{
      //塗りに黒を設定
      ctx.fillStyle = '#000';
      //キャンバスを塗りつぶす
      ctx.fillRect(0, 0, canvasW, canvasH);

      //塗りに赤を設定
      ctx.fillStyle="#f00";
      //x座標150,y座標150の場所に幅30,縦30の四角を描画
      ctx.fillRect(150,150,blockSize,blockSize);

      //テトリミノの描画
      for (let y = 0; y < tetSize; y++) {
          for (let x = 0; x < tetSize; x++) {
            //もし、1だったら
            if (tet[y][x]) {
              //四角を描画
              ctx.fillRect(x * blockSize,y * blockSize,blockSize,blockSize);
            }
          }
        }
    }

以下のように表示されれば成功だ。

ポイント解説

テトリミノの一つ一つを以下のような2次元配列で扱う。ブロックが存在しているところを1それ以外は0で表している。

let tet= [
          [0, 0, 0, 0],
          [0, 1, 0, 0],
          [1, 1, 1, 0],
          [0, 0, 0, 0],
        ];

以下のように1のところのみが四角が描かれている

矢印キーで移動できるようにする

ではこのテトリミノが矢印キーで動くようにしてみよう。以下のように追記or変更する。

    let tet= [
          [0, 0, 0, 0],
          [0, 1, 0, 0],
          [1, 1, 1, 0],
          [0, 0, 0, 0],
        ];

    //テトリミノのオフセット量(何マス分ずれているか)
    let offsetX = 0;
    let offsetY = 0;

    //描画処理
    const draw=()=>{

      //塗りに黒を設定
      ctx.fillStyle = '#000';
      //キャンバスを塗りつぶす
      ctx.fillRect(0, 0, canvasW, canvasH);

      //塗りに赤を設定
      ctx.fillStyle="#f00";
      //x座標150,y座標150の場所に幅30,縦30の四角を描画
      ctx.fillRect(150,150,blockSize,blockSize);

      //テトリミノの描画
      for (let y = 0; y < tetSize; y++) {
          for (let x = 0; x < tetSize; x++) {
            if (tet[y][x]) {
              ctx.fillRect(
                (offsetX+x)*blockSize ,
                (offsetY+y)*blockSize ,
                blockSize,
                blockSize);
            }
          }
        }
    }
    document.onkeydown = (e) =>{
        switch (e.keyCode) {
          case 37: //左
            offsetX--;
            break;
          case 38: //上
            offsetY--;
            break;
          case 39: //右
            offsetX++;
            break;
          case 40: //下
            offsetY++;
            break;
        }
        draw();
      };

いざ、実行!

矢印キーによって上下左右に動けば成功だ。

ポイント解説

1回の移動で1ブロック分移動するようにoffsetX,Yという変数を用意した。
これが1増えると1ブロック分移動するというわけだ。
キーボードの押し下げ時にイベントを走らせられるonkeydownにイベントハンドラを登録して、ここでこのoffset量を変化させている。

drawBlock

一つのブロックを描画する部分を関数化しよう。以下のハイライト部分を追加&修正。
以下はここまでの全文

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>テトリス</title>
    <style>
      body {
        background: #ddf5ff;
      }
      #container {
        margin: 0 auto;
      }
    </style>
  </head>
  <body onload="init()">
    <div id="container">
      <canvas id="cvs"></canvas>
    </div>
    <script>
      //ブロック1マスの大きさ
      const blockSize = 30;
      //ボードサイズ
      const boardRow = 20;
      const boardCol = 10;
      //キャンバスの取得
      const cvs = document.getElementById('cvs');
      //2dコンテキストを取得
      const ctx = cvs.getContext('2d');
      //キャンバスサイズ
      const canvasW = blockSize * boardCol;
      const canvasH = blockSize * boardRow;
      cvs.width = canvasW;
      cvs.height = canvasH;
      //コンテナの設定
      const container = document.getElementById('container');
      container.style.width = canvasW + 'px';

      //tetの1辺の大きさ
      const tetSize = 4;
      //T型のtet
      let tet = [
        [0, 0, 0, 0],
        [0, 1, 0, 0],
        [1, 1, 1, 0],
        [0, 0, 0, 0],
      ];

      //テトリミノのオフセット量(何マス分ずれているか)
      let offsetX = 0;
      let offsetY = 0;

      //描画処理
      const draw = () => {
        //塗りに黒を設定
        ctx.fillStyle = '#000';
        //キャンバスを塗りつぶす
        ctx.fillRect(0, 0, canvasW, canvasH);

        //塗りに赤を設定
        //ctx.fillStyle = '#f00';
        //x座標50,y座標50の場所に幅30,縦30の四角を描画
        //ctx.fillRect(150, 150, blockSize, blockSize);

        //テトリミノの描画
        for (let y = 0; y < tetSize; y++) {
          for (let x = 0; x < tetSize; x++) {
            if (tet[y][x]) {
              drawBlock(offsetX+x,offsetY+y);
            }
          }
        }
      };
      //ブロック一つを描画する
      const drawBlock = (x, y) => {
        let px = x * blockSize;
        let py = y * blockSize;
        //塗りを設定
        ctx.fillStyle = '#f00';
        ctx.fillRect(px, py, blockSize, blockSize);
        //線を設定
        ctx.strokeStyle = 'black';
        //線を描画
        ctx.strokeRect(px, py, blockSize, blockSize);
      };

      document.onkeydown = (e) => {
        switch (e.keyCode) {
          case 37: //左
            offsetX--;
            break;
          case 38: //上
            offsetY--;
            break;
          case 39: //右
            offsetX++;
            break;
          case 40: //下
            offsetY++;
            break;
        }
        draw();
      };
      //
      //初期化処理
      const init = () => {
        draw();
      };
    </script>
  </body>
</html>

続きはこちら

コメント

タイトルとURLをコピーしました