6. クルっと回れ!ミノの基本回転
さあ、みんな!ミノの落下までできるようになったから、次はいよいよミノを回転させる魔法に挑戦よ! テトリミノがクルクル回ると、隙間にピタッとはめ込む戦略が生まれて、ゲームがぐっと面白くなるわよね。 まずは、基本となる「90度右回転」の仕組みから見ていきましょう!
ミノの形(2次元配列)を回転させるってどういうこと?
ミノの形は2次元配列で表していたわよね(例:[[0,1,0],[1,1,1]]
みたいなの)。これを回転させるのは、ちょっと数学的なパズルみたいなものなの。
例えば、3x3のマス目があったとして、それを右に90度回転させると、各マスがどこに移動するか考えてみて。
元の配列の行と列を入れ替えて、さらに列の順番を逆にする(または行の順番を逆にする、やり方によるけど)と、回転した新しい配列ができあがるの。 言葉で言うと難しいから、右に90度回転させるための魔法の呪文(コード)はこんな感じになるわ。
function rotateShape(shape) {
const rows = shape.length; // 元の形の行数
const cols = shape[0].length; // 元の形の列数
// 新しい形を準備 (最初は空っぽの配列で)
const newShape = [];
for (let i = 0; i < cols; i++) { // 新しい形の行数は、元の形の列数になるの
newShape[i] = [];
}
// 魔法の変換!
for (let r = 0; r < rows; r++) { // 元の形の各行をループ
for (let c = 0; c < cols; c++) { // 元の形の各列をループ
// 右回転の場合: newShape[c][rows - 1 - r] = shape[r][c];
// または、こんな書き方もできるわ (結果は同じよ)
newShape[c][(rows - 1) - r] = shape[r][c];
}
}
return newShape;
}
// 例:Tミノ [[0,1,0],[1,1,1]] を回転させると…
// [[1,0], (元の(0,1)が(0,0)に、(1,1)が(1,0)に…)
// [1,1],
// [1,0]] みたいな感じになるはず!(実際には正方行列じゃないので注意)
注意点:この単純な回転アルゴリズムは、ミノの形が必ずしも正方形じゃない(例えばIミノは1x4や4x1)から、回転後の配列の大きさが変わることに注意が必要よ。
もっと一般的な回転は、新しい配列の列数が行数に、行数が列数になるように作って、newShape[c][元の行数 - 1 - r] = shape[r][c]
のように値を移すの。
今回のサンプルコードでは、この一般的な方法で回転させるわね。
回転前にも衝突判定!
ミノを回転させようとした時、ただ形を変えるだけじゃダメなの。回転した結果、新しい形がカベや床、あるいは(将来的には)他のブロックにめり込んじゃうことがあるから。
だから、回転を実行する前に、「回転しても大丈夫?」って確認する必要があるの。これは、前回も使った canMinoMoveTo
関数がまた活躍するわ!
回転後の新しい形(newShape
)と、現在のミノの位置(currentMino.x, currentMino.y
)を使って、canMinoMoveTo(newShape, currentMino.x, currentMino.y)
を呼び出すの。これが true
を返したら、回転OKってことね!
回転キーを実装しよう!
一般的に、テトリスでは上矢印キー(ArrowUp
)や、'X'キー、'Z'キーあたりで回転操作をすることが多いわね。今回は、上矢印キーで右回転するようにしましょう。
// document.addEventListener('keydown', function(event) { ... の中に追記
// ... (ArrowLeft, ArrowRight, ArrowDown の処理) ...
} else if (event.key === 'ArrowUp') {
event.preventDefault();
tryRotateMino();
}
// ...
function tryRotateMino() {
if (!currentMino) return;
const originalShape = currentMino.shape;
const rotatedShape = rotateShape(originalShape); // さっき作った回転関数
if (canMinoMoveTo(rotatedShape, currentMino.x, currentMino.y)) {
currentMino.shape = rotatedShape; // 回転成功!形を更新
// redrawGame(); // あとでゲームループで描画するからここでは不要かも
} else {
// 回転できない場合 (例えば効果音を鳴らすとか)
console.log("回転できませんでした!");
}
}
これで、上キーを押すとミノが回転しようとして、もし回転できるなら形が変わるはずよ!
実践!くるくる回してみよう!
さあ、下のCanvasでミノを回転させてみて!左右に動かしたり、下に落としたりしながら、上矢印キーで回転! ただし、今の段階では、回転した時にカベや床に少しでもかかりそうなら、回転できないはずよ。 「えー、カベ際でもうちょっとうまく回りたいのに!」って思うかもしれないけど、そのお悩みは次のページで解決するから、まずはこの基本回転をマスターしましょうね!
(ゲームの状態や操作方法が表示されるわ)
Summary of this page (Click to read in English)
This page introduces basic 90-degree clockwise rotation for Tetrominoes. The core idea is to transform the 2D array representing the Tetromino's shape. A common way to achieve this is by swapping rows and columns and then reversing the order of the new columns (or rows).
Before actually rotating, we must perform collision detection. We use the canMinoMoveTo
function (checking against walls and the floor) with the *rotated* shape at the *current* position. If the rotation is valid, the Tetromino's shape is updated. We'll map the 'ArrowUp' key to trigger this rotation attempt. For now, if a rotation would cause a collision, it's simply disallowed; advanced techniques like wall kicks will be covered next.