JavaScriptでテトリス!初心者向け解説とサンプルコード10選

JavaScriptでテトリスを作る方法を解説する記事のイメージ JS
この記事は約13分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事を読めば、JavaScriptを使ってテトリスを作る方法が身に付きます。

JavaScriptに触れたことがない初心者の方でも、下記の解説とサンプルコードに沿って進めれば、テトリスを作成し、さらにカスタマイズする方法が理解できるでしょう。

●テトリスの仕組み

○基本ルール

テトリスは、さまざまな形のブロック(テトリミノ)が上から下へ落ちてくるゲームです。

プレイヤーはテトリミノを移動させたり回転させて、画面下部に積み上げます。

テトリミノが横一列に並ぶと、その行は消えてスコアが加算されます。

テトリミノが画面上部に積み上がるとゲームオーバーになります。

●JavaScriptでテトリスを作るための環境構築

○ブラウザとエディタの選択

JavaScriptでテトリスを作成するには、最新のウェブブラウザ(Google ChromeやFirefoxなど)と、コードを記述するためのエディタ(Visual Studio CodeやSublime Textなど)が必要です。

●JavaScriptの基本知識

○変数と関数

JavaScriptでは、変数を使ってデータを保持し、関数を使って処理をまとめることができます。

変数はletconstで宣言し、関数はfunctionで定義します。

○ループと条件分岐

ループは繰り返し処理を行うために使用され、for文やwhile文があります。

条件分岐は、条件によって処理を分けるために使用され、if文が代表的です。

●テトリスの基本構成

○HTMLとCSS

HTMLはウェブページの構造を表現し、CSSはその見た目を装飾します。

テトリスでは、HTMLでゲーム画面やスコア表示の領域を作り、CSSでそれらをデザインします。

○JavaScriptの役割

JavaScriptはウェブページに動的な機能を追加するために使われます。

テトリスでは、JavaScriptでテトリミノの動きや衝突判定、行のクリアなどのゲームロジックを実装します。

○サンプルコード1:テトリスのボードを作成

HTMLとCSSを使って、テトリスのボードを作成しましょう。

下記のコードでは、20行×10列のボードが作成されます。

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>JavaScriptでテトリス</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div id="board"></div>
  <script src="script.js"></script>
</body>
</html>

CSS (styles.css)

body {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  background-color: #f0f0f0;
}

#board {
  display: grid;
  grid-template-rows: repeat(20, 30px);
  grid-template-columns: repeat(10, 30px);
  grid-gap: 1px;
}

.cell {
  width: 30px;
  height: 30px;
  border: 1px solid #ccc;
  box-sizing: border-box;
}

JavaScript (script.js)

const board = document.getElementById('board');

for (let i = 0; i < 200; i++) {
  const cell = document.createElement('div');
  cell.classList.add('cell');
  board.appendChild(cell);
}

上記のコードでは、HTMLでゲームボードの領域を定義し、CSSでボードのデザインを設定しています。

JavaScriptでは、200個のセル(20行×10列)を作成し、ボードに追加しています。

○サンプルコード2:テトリミノを作成

次に、テトリミノを作成しましょう。

テトリミノは7種類あり、それぞれ独自の形状があります。

下記のコードでは、テトリミノの形状を二次元配列で表現し、それを回転させる関数を定義しています。

JavaScript (script.js)

const tetrominoes = [
  // I
  [
    [1, 1, 1, 1],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
  ],
  // O
  [
    [1, 1],
    [1, 1]
  ],
  // T
  [
    [1, 1, 1],
    [0, 1, 0],
    [0, 0, 0]
  ],
  // S
  [
    [0, 1, 1],
    [1, 1, 0],
    [0, 0, 0]
  ],
  // Z
  [
    [1, 1, 0],
    [0, 1, 1],
    [0, 0, 0]
  ],
  // J
  [
    [1, 0, 0],
    [1, 1, 1],
    [0, 0, 0]
  ],
  // L
  [
    [0, 0, 1],
    [1, 1, 1],
    [0, 0, 0]
  ]
];

function rotate(matrix) {
  const n = matrix.length - 1;
  const result = matrix.map((row, i) =>
    row.map((val, j) => matrix[n - j][i])
  );
  return result;
}

このコードでは、7つのテトリミノの形状を二次元配列で表現しています。

また、rotate関数を定義し、テトリミノを回転させる機能を提供しています。

この関数は、引数として渡された行列を時計回りに90度回転させた結果を返します。

次に、テトリミノをボード上で動かすための関数を実装しましょう。

○サンプルコード3:テトリミノの移動と衝突判定

テトリミノをボード上で動かすために、移動と衝突判定を行う関数を実装します。

下記のコードを追加してください。

JavaScript (script.js)に追加

function collides(board, piece, offsetX, offsetY) {
  for (let y = 0; y < piece.length; y++) {
    for (let x = 0; x < piece[y].length; x++) {
      if (piece[y][x] &&
        (board[y + offsetY] &&
        board[y + offsetY][x + offsetX]) !== 0) {
        return true;
      }
    }
  }
  return false;
}

function movePiece(board, piece, offsetX, offsetY) {
  if (collides(board, piece, offsetX, offsetY)) {
    return false;
  }
  // Update the board with the new position of the piece
  return true;
}

collides関数は、現在のボード状態、テトリミノ、オフセットX、オフセットYを受け取り、テトリミノがボードの壁や他のテトリミノに衝突するかどうかを判定します。

movePiece関数は、衝突がない場合に限り、テトリミノの位置を更新します。

○サンプルコード4:行のクリアとスコア計算

テトリスでは、一列にブロックが揃った行をクリアし、スコアを計算する必要があります。

この機能を実装するために、下記のコードを追加してください。

JavaScript (script.js)

function clearLines(board) {
  let linesCleared = 0;

  outer: for (let y = board.length - 1; y >= 0; y--) {
    for (let x = 0; x < board[y].length; x++) {
      if (!board[y][x]) {
        continue outer;
      }
    }

    // Clear the line
    board.splice(y, 1);
    board.unshift(Array(board[0].length).fill(0));
    linesCleared++;
  }

  return linesCleared;
}

function calculateScore(linesCleared) {
  const lineScores = [0, 100, 300, 500, 800];
  return lineScores[linesCleared];
}

clearLines関数は、ボードからクリアされた行を削除し、新しい行を追加します。

calculateScore関数は、クリアされた行数に基づいてスコアを計算します。

○サンプルコード5:ゲームオーバー判定と再開

ゲームオーバー判定とゲームの再開を行う関数を実装します。

下記のコードを追加してください。

JavaScript (script.js)

function isGameOver(board) {
  return board[0].some(cell => cell !== 0);
}

function startGame(board) {
  // Initialize board and variables
  // ...
  if (isGameOver(board)) {
    // Show game over message and reset the game
  } else {
    // Continue the game loop
  }
}

isGameOver関数は、ボードの最上部にブロックがあるかどうかをチェックし、ゲームオーバーかどうかを判定します。

startGame関数は、ゲームオーバー判定を行い、ゲームオーバーの場合はメッセージを表示してゲームをリセットし、そうでない場合はゲームループを続行します。

●注意点と対処法

ブラウザの互換性

異なるブラウザでは、JavaScriptやHTMLの仕様が異なる場合があります。

対策として、Can I use (https://caniuse.com/)などのウェブサイトでブラウザの互換性を確認し、必要に応じてPolyfillを使用してください。

パフォーマンス

ゲームのパフォーマンスが低下する場合は、ゲームループの最適化や、使用しているリソース(画像や音声など)のサイズを調整してください。

●応用例とサンプルコード

さらに応用して、テトリスゲームに追加機能を実装してみましょう。

○サンプルコード6:テトリスのスキン変更

プレイヤーがテトリミノの見た目を変更できるようにスキン変更機能を実装します。

下記のコードを追加してください。

JavaScript (script.js)

const skins = [
  // Add different color schemes for the tetriminoes
];

function changeSkin(index) {
  currentSkin = skins[index];
}

skins配列には、異なるカラースキームを追加します。

changeSkin関数では、指定されたインデックスに基づいて現在のスキンを変更します。

○サンプルコード7:効果音とBGMの実装

ゲーム中の効果音やBGMを追加して、ゲームの雰囲気を向上させます。

Web Audio APIを使用して、下記のコードを追加してください。

JavaScript (script.js)

const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const soundEffects = {
  // Load your sound effects here
};

function playSound(soundName) {
  const source = audioContext.createBufferSource();
  source.buffer = soundEffects[soundName];
  source.connect(audioContext.destination);
  source.start(0);
}

soundEffectsオブジェクトには、使用する効果音を追加します。

playSound関数では、指定された効果音を再生します。

○サンプルコード8:レベルとスピードの調整

ゲームのレベルが上がると、テトリミノが落ちる速度が速くなるように調整します。

下記のコードを追加してください。

JavaScript (script.js)

function updateSpeed(level) {
  speed = initialSpeed - level * speedIncrement;
}

updateSpeed関数では、現在のレベルに基づいて速度が調整されます。

○サンプルコード9:ハイスコア機能の実装

プレイヤーのハイスコアを記録し、表示する機能を実装します。

下記のコードを追加してください。

JavaScript (script.js)

function saveHighScore(score) {
  const highScore = localStorage.getItem('highScore') || 0;
  if (score > highScore) {
    localStorage.setItem('highScore', score);
  }
}

function getHighScore() {
  return localStorage.getItem('highScore') || 0;
}

saveHighScore関数では、現在のスコアがハイスコアを上回っている場合に、ハイスコアを更新します。

getHighScore関数では、現在のハイスコアを取得します。

○サンプルコード10:マルチプレイヤー対応

オンラインでのマルチプレイヤー機能を実装するために、WebSocketを使用して通信を行います。

下記のコードを追加してください。

JavaScript (script.js)

const socket = new WebSocket('ws://your-websocket-server.com');

socket.addEventListener('message', (event) => {
  // Handle messages from the server, such as other players' moves
});

function sendMove(move) {
  socket.send(JSON.stringify(move));
}

socketオブジェクトを作成して、WebSocketサーバーに接続します。

messageイベントリスナーで、サーバーからのメッセージを処理します。

sendMove関数では、プレイヤーの行動をサーバーに送信します。

まとめ

このガイドでは、テトリスゲームを作成するためのサンプルコードを提供しました。

基本的なゲームロジックから応用的な機能まで、一連のサンプルコードを使用して独自のテトリスゲームを開発できます。

必要に応じて、提供されたサンプルコードをカスタマイズし、独自の機能やスタイルを追加してください。