はじめに
この記事を読めば、JavaScriptを使ってテトリスを作る方法が身に付きます。
JavaScriptに触れたことがない初心者の方でも、下記の解説とサンプルコードに沿って進めれば、テトリスを作成し、さらにカスタマイズする方法が理解できるでしょう。
●テトリスの仕組み
○基本ルール
テトリスは、さまざまな形のブロック(テトリミノ)が上から下へ落ちてくるゲームです。
プレイヤーはテトリミノを移動させたり回転させて、画面下部に積み上げます。
テトリミノが横一列に並ぶと、その行は消えてスコアが加算されます。
テトリミノが画面上部に積み上がるとゲームオーバーになります。
●JavaScriptでテトリスを作るための環境構築
○ブラウザとエディタの選択
JavaScriptでテトリスを作成するには、最新のウェブブラウザ(Google ChromeやFirefoxなど)と、コードを記述するためのエディタ(Visual Studio CodeやSublime Textなど)が必要です。
●JavaScriptの基本知識
○変数と関数
JavaScriptでは、変数を使ってデータを保持し、関数を使って処理をまとめることができます。
変数はlet
やconst
で宣言し、関数は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
関数では、プレイヤーの行動をサーバーに送信します。
まとめ
このガイドでは、テトリスゲームを作成するためのサンプルコードを提供しました。
基本的なゲームロジックから応用的な機能まで、一連のサンプルコードを使用して独自のテトリスゲームを開発できます。
必要に応じて、提供されたサンプルコードをカスタマイズし、独自の機能やスタイルを追加してください。