読み込み中...

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

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

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

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

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

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

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

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

はじめに

JavaScriptを使ってテトリスゲームを作成する方法を詳しく解説します。

プログラミング初心者の方でも、この記事の説明とサンプルコードを参考にすれば、オリジナルのテトリスゲームを作り上げることができるでしょう。

さらに、ゲームをカスタマイズする方法も学べます。

●テトリスの仕組み

テトリスは、シンプルながら奥深いゲームメカニクスを持つパズルゲームです。

その基本的な仕組みを理解することは、ゲーム開発の第一歩となります。

○基本ルール

テトリスは、様々な形のブロック(テトリミノ)が画面上部から落下してくるゲームです。

プレイヤーは、このテトリミノを左右に移動したり回転させたりしながら、画面下部に積み上げていきます。

横一列にブロックが揃うと、その行が消えてポイントが加算されます。テトリミノが画面上部まで積み上がってしまうと、ゲームオーバーとなります。

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

テトリスゲームを開発するには、適切な開発環境を整えることが重要です。

ここでは、必要なツールとその選び方について説明します。

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

JavaScriptでテトリスを開発するためには、まず適切な環境を整える必要があります。

最新のウェブブラウザ(Google ChromeやFirefoxなど)と、コードを記述するためのテキストエディタ(Visual Studio CodeやSublime Textなど)を用意しましょう。

このツールを使用することで、効率的にプログラミングを進められます。

●JavaScriptの基本知識

テトリスゲームを開発する前に、JavaScriptの基本的な概念を理解しておくことが重要です。

ここで、ゲーム開発に特に関連する重要な概念を説明します。

○変数と関数

JavaScriptにおいて、変数はデータを保持するための「箱」のような役割を果たします。

letconstキーワードを使って宣言します。

一方、関数は特定の処理をまとめたものです。functionキーワードを使って定義します。

これらの概念は、テトリスゲームの開発において重要な役割を果たします。

○ループと条件分岐

ループは同じ処理を繰り返し行うために使用されます。

JavaScriptにはfor文やwhile文などがあります。

条件分岐は、特定の条件に応じて処理を変える際に使用され、主にif文が用いられます。

テトリスゲームでは、ブロックの移動や衝突判定などにこれらの制御構造が頻繁に登場します。

●テトリスの基本構成

テトリスゲームを開発するには、ウェブ技術の3つの柱であるHTML、CSS、JavaScriptを適切に組み合わせる必要があります。

各技術の役割を理解し、それを効果的に活用することで、魅力的なゲームを作り上げることができます。

○HTMLとCSS

HTMLはウェブページの骨格を形成し、CSSはその見た目を整えます。

テトリスゲームの開発では、HTMLでゲーム画面やスコア表示の領域を作成し、CSSでそれらの要素をスタイリングします。

この組み合わせにより、ゲームの基本的な外観が形作られます。

○JavaScriptの役割

JavaScriptは、ウェブページに動的な機能を追加するプログラミング言語です。

テトリスゲームにおいては、JavaScriptを使ってテトリミノの動き、衝突判定、行のクリアなど、ゲームの核心となるロジックを実装します。

これで、静的なHTMLとCSSに「命」を吹き込むことができるのです。

○サンプルコード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種類のテトリミノがあり、それぞれ独自の形状を持っています。

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

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:テトリミノの移動と衝突判定

テトリミノをゲームボード上で動かすためには、移動と衝突判定の機能が必要です。

次のコードを追加して、これらの機能を実装しましょう。

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;
  }
  // ここでボードの状態を更新します
  return true;
}

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

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

この関数を使用することで、テトリミノを安全に移動させることができます。

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

テトリスゲームの醍醐味の一つは、ブロックが一列に揃った時に行がクリアされ、スコアが加算される点です。

この機能を実装するために、次のコードを追加しましょう。

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;
      }
    }

    // 行をクリアします
    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:ゲームオーバー判定と再開

テトリスゲームでは、ブロックが画面上部に達するとゲームオーバーとなります。

また、ゲームオーバー後に新しくゲームを開始する機能も必要です。

次のコードでこれらの機能を実装しましょう。

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

function startGame(board) {
  // ボードと変数を初期化します
  // ...
  if (isGameOver(board)) {
    // ゲームオーバーのメッセージを表示し、ゲームをリセットします
  } else {
    // ゲームループを継続します
  }
}

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

startGame関数は、ゲームの初期化とゲームオーバー判定を行い、適切な処理を実行します。

この関数を使用することで、ゲームの開始から終了までのフローを管理することができます。

●注意点と対処法

ブラウザの互換性に関する問題は、開発者にとって常に頭痛の種となります。

異なるブラウザでは、JavaScriptやHTMLの仕様が微妙に異なる場合があるためです。

この問題に対処するために、Can I use (https:// caniuse.com/) などのウェブサイトでブラウザの互換性を事前に確認し、必要に応じてPolyfillを使用することをお勧めします。

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

これらの調整により、スムーズなゲームプレイを実現することができます。

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

基本的なテトリスゲームの実装ができたら、さらに機能を追加してゲームを充実させてみましょう。

それでは、具体的に応用例とそのサンプルコードを紹介します。

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

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

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

const skins = [
  // テトリミノの異なるカラースキームをここに追加します
];

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

skins配列には、テトリミノの異なるカラースキームを追加します。

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

この機能により、プレイヤーは好みのスキンを選択してゲームを楽しむことができます。

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

ゲーム体験をより豊かにするために、効果音やバックグラウンドミュージック(BGM)を追加しましょう。

Web Audio APIを使用して、次のコードを実装します。

const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const soundEffects = {
  // ここに効果音を読み込みます
};

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

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

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

この関数を適切なタイミングで呼び出すことで、ゲーム内のアクションに合わせた音響効果を実現できます。

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

ゲームのレベルが上がるにつれて、テトリミノが落下する速度が徐々に速くなるように調整しましょう。

これで、プレイヤーにとって適度な難易度の上昇が期待できます。

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

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

updateSpeed関数は、現在のレベルに基づいて落下速度を調整します。

initialSpeedは初期速度、speedIncrementはレベルごとの速度増加量を表します。

この関数を使用することで、ゲームの進行に応じて難易度が段階的に上昇し、プレイヤーに常に適度な挑戦を提供することができます。

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

プレイヤーのモチベーションを高めるために、ハイスコアを記録し表示する機能を実装しましょう。

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

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を使用して、複数のプレイヤー間でリアルタイムの通信を行います。

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

socket.addEventListener('message', (event) => {
  // サーバーからのメッセージ(他プレイヤーの動きなど)を処理します
});

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

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

messageイベントリスナーでは、サーバーからのメッセージ(例えば、他のプレイヤーの動きなど)を処理します。

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

これらの機能を実装することで、複数のプレイヤーが同時にゲームを楽しむことができ、より競争的で楽しい環境を提供することができます。

まとめ

本記事では、JavaScriptを使用してテトリスゲームを開発するための詳細な手順とサンプルコードを提供しました。

基本的なゲームロジックから応用的な機能まで、幅広いトピックをカバーしています。

また、プログラミングの学習過程では、試行錯誤が重要です。

エラーが発生しても、それを学びの機会と捉え、粘り強く取り組んでいけば、必ず素晴らしい成果を得ることができるはずです。

皆さんの創造力と技術力を存分に発揮して、独自のテトリスゲームを作り上げてください。

プログラミングの楽しさを存分に味わいながら、素晴らしい作品を生み出せるといいですね。