Last active
August 7, 2025 14:25
-
-
Save kujirahand/9e53e990cd7eae443f60690c67ed6986 to your computer and use it in GitHub Desktop.
落ちものゲーム
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="ja"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>落ちものゲーム</title> | |
| <style> | |
| canvas { background: #eee; display: block; margin: 20px auto; } | |
| </style> | |
| </head> | |
| <body> | |
| <canvas id="gameCanvas" width="300" height="450"></canvas> | |
| <script> | |
| const cols = 10; | |
| const rows = 15; | |
| const cellSize = 30; | |
| const colors = ["red", "green", "blue", "yellow", "purple"]; | |
| let grid = []; | |
| // グリッド初期化 | |
| for (let y = 0; y < rows; y++) { | |
| grid[y] = Array(cols).fill(0); | |
| } | |
| // 障害物を3つランダム配置 | |
| for (let i = 0; i < 3; i++) { | |
| let x, y; | |
| do { | |
| x = Math.floor(Math.random() * cols); | |
| y = Math.floor(Math.random() * (rows - 5)) + 5; | |
| } while (grid[y][x] !== 0); | |
| grid[y][x] = Math.floor(Math.random() * colors.length) + 1; | |
| } | |
| // ブロック情報 | |
| const baseShape = [ {x:0, y:0}, {x:0, y:1}, {x:1, y:1}, {x:2, y:1} ]; | |
| let piece; | |
| let interval; | |
| // 新しいブロック生成 | |
| function spawnPiece() { | |
| piece = { | |
| coords: baseShape.map(c => ({ x: c.x, y: c.y })), | |
| x: Math.floor((cols - 3) / 2), | |
| y: 0, | |
| color: Math.floor(Math.random() * colors.length) + 1 | |
| }; | |
| // スポーン時に衝突したらゲームオーバー | |
| if (collides(piece.x, piece.y, piece.coords)) { | |
| clearInterval(interval); | |
| alert("ゲームオーバー"); | |
| } | |
| } | |
| // 衝突判定 | |
| function collides(px, py, coords) { | |
| return coords.some(c => { | |
| const x = px + c.x; | |
| const y = py + c.y; | |
| return x < 0 || x >= cols || y < 0 || y >= rows || grid[y][x] !== 0; | |
| }); | |
| } | |
| // 回転処理 | |
| function rotate(coords) { | |
| const newCoords = coords.map(c => ({ x: c.y, y: -c.x })); | |
| const minX = Math.min(...newCoords.map(c => c.x)); | |
| const minY = Math.min(...newCoords.map(c => c.y)); | |
| return newCoords.map(c => ({ x: c.x - minX, y: c.y - minY })); | |
| } | |
| // キー操作 | |
| document.addEventListener("keydown", e => { | |
| if (e.key === "ArrowLeft" && !collides(piece.x - 1, piece.y, piece.coords)) { | |
| piece.x--; | |
| } else if (e.key === "ArrowRight" && !collides(piece.x + 1, piece.y, piece.coords)) { | |
| piece.x++; | |
| } else if (e.key === "ArrowUp") { | |
| const rc = rotate(piece.coords); | |
| if (!collides(piece.x, piece.y, rc)) piece.coords = rc; | |
| } | |
| }); | |
| // ブロックを固定&消去&次生成 | |
| function placePiece() { | |
| piece.coords.forEach(c => { | |
| grid[piece.y + c.y][piece.x + c.x] = piece.color; | |
| }); | |
| clearLines(); | |
| spawnPiece(); | |
| } | |
| // 同じ色が5個並んでいたら消去 | |
| function clearLines() { | |
| const offsets = [1,2,3,4]; | |
| let toClear = []; | |
| // 横 | |
| for (let y = 0; y < rows; y++) { | |
| for (let x = 0; x <= cols - 5; x++) { | |
| const v = grid[y][x]; | |
| if (v !== 0 && offsets.every(o => grid[y][x + o] === v)) { | |
| for (let o = 0; o < 5; o++) toClear.push({ x: x + o, y: y }); | |
| } | |
| } | |
| } | |
| // 縦 | |
| for (let x = 0; x < cols; x++) { | |
| for (let y = 0; y <= rows - 5; y++) { | |
| const v = grid[y][x]; | |
| if (v !== 0 && offsets.every(o => grid[y + o][x] === v)) { | |
| for (let o = 0; o < 5; o++) toClear.push({ x: x, y: y + o }); | |
| } | |
| } | |
| } | |
| // 消去 | |
| toClear.forEach(p => { grid[p.y][p.x] = 0; }); | |
| if (toClear.length > 0) { | |
| // 落下処理 | |
| for (let x = 0; x < cols; x++) { | |
| const col = []; | |
| for (let y = rows - 1; y >= 0; y--) { | |
| if (grid[y][x] !== 0) col.push(grid[y][x]); | |
| } | |
| for (let y = rows - 1; y >= 0; y--) { | |
| grid[y][x] = col[rows - 1 - y] || 0; | |
| } | |
| } | |
| } | |
| } | |
| // 描画 | |
| function draw() { | |
| const ctx = document.getElementById("gameCanvas").getContext("2d"); | |
| ctx.clearRect(0, 0, cols * cellSize, rows * cellSize); | |
| // グリッド | |
| for (let y = 0; y < rows; y++) { | |
| for (let x = 0; x < cols; x++) { | |
| if (grid[y][x]) { | |
| ctx.fillStyle = colors[grid[y][x] - 1]; | |
| ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); | |
| ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize); | |
| } | |
| } | |
| } | |
| // 現在のブロック | |
| piece.coords.forEach(c => { | |
| ctx.fillStyle = colors[piece.color - 1]; | |
| ctx.fillRect((piece.x + c.x) * cellSize, (piece.y + c.y) * cellSize, cellSize, cellSize); | |
| ctx.strokeRect((piece.x + c.x) * cellSize, (piece.y + c.y) * cellSize, cellSize, cellSize); | |
| }); | |
| } | |
| // ゲーム開始 | |
| spawnPiece(); | |
| draw(); | |
| interval = setInterval(() => { | |
| if (!collides(piece.x, piece.y + 1, piece.coords)) { | |
| piece.y++; | |
| } else { | |
| placePiece(); | |
| } | |
| draw(); | |
| }, 300); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment