// 游戏常量 const COLS = 10; const ROWS = 20; const BLOCK_SIZE = 30; // 方块形状定义 const SHAPES = [ [[1, 1, 1, 1]], // I [[1, 1], [1, 1]], // O [[0, 1, 0], [1, 1, 1]], // T [[1, 0, 0], [1, 1, 1]], // L [[0, 0, 1], [1, 1, 1]], // J [[0, 1, 1], [1, 1, 0]], // S [[1, 1, 0], [0, 1, 1]] // Z ]; // 方块颜色 const COLORS = [ '#00f0f0', // I - 青色 '#f0f000', // O - 黄色 '#a000f0', // T - 紫色 '#f0a000', // L - 橙色 '#0000f0', // J - 蓝色 '#00f000', // S - 绿色 '#f00000' // Z - 红色 ]; // 游戏状态 let canvas, ctx, nextCanvas, nextCtx; let board = []; let currentPiece = null; let nextPiece = null; let score = 0; let level = 1; let lines = 0; let gameLoop = null; let isPaused = false; let isGameOver = false; let dropInterval = 1000; // 初始化 function init() { canvas = document.getElementById('game-canvas'); ctx = canvas.getContext('2d'); nextCanvas = document.getElementById('next-canvas'); nextCtx = nextCanvas.getContext('2d'); // 初始化游戏板 for (let r = 0; r < ROWS; r++) { board[r] = []; for (let c = 0; c < COLS; c++) { board[r][c] = 0; } } // 绑定事件 document.addEventListener('keydown', handleKeyPress); document.getElementById('start-btn').addEventListener('click', startGame); document.getElementById('restart-btn').addEventListener('click', startGame); // 绘制初始游戏板 drawBoard(); } // 创建新方块 function createPiece() { const shapeIndex = Math.floor(Math.random() * SHAPES.length); return { shape: SHAPES[shapeIndex], color: COLORS[shapeIndex], x: Math.floor(COLS / 2) - Math.floor(SHAPES[shapeIndex][0].length / 2), y: 0 }; } // 绘制方块 function drawBlock(ctx, x, y, color, size = BLOCK_SIZE) { ctx.fillStyle = color; ctx.fillRect(x * size, y * size, size, size); // 添加3D效果 ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; ctx.fillRect(x * size, y * size, size, 2); ctx.fillRect(x * size, y * size, 2, size); ctx.fillStyle = 'rgba(0, 0, 0, 0.3)'; ctx.fillRect(x * size + size - 2, y * size, 2, size); ctx.fillRect(x * size, y * size + size - 2, size, 2); } // 绘制游戏板 function drawBoard() { // 清空画布 ctx.fillStyle = '#1a1a2e'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 绘制网格 ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)'; for (let r = 0; r < ROWS; r++) { for (let c = 0; c < COLS; c++) { ctx.strokeRect(c * BLOCK_SIZE, r * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); } } // 绘制已放置的方块 for (let r = 0; r < ROWS; r++) { for (let c = 0; c < COLS; c++) { if (board[r][c]) { drawBlock(ctx, c, r, board[r][c]); } } } } // 绘制当前方块 function drawPiece() { if (!currentPiece) return; for (let r = 0; r < currentPiece.shape.length; r++) { for (let c = 0; c < currentPiece.shape[r].length; c++) { if (currentPiece.shape[r][c]) { drawBlock(ctx, currentPiece.x + c, currentPiece.y + r, currentPiece.color); } } } } // 绘制下一个方块 function drawNextPiece() { if (!nextPiece) return; nextCtx.fillStyle = '#fff'; nextCtx.fillRect(0, 0, nextCanvas.width, nextCanvas.height); const size = 20; const offsetX = (nextCanvas.width - nextPiece.shape[0].length * size) / 2; const offsetY = (nextCanvas.height - nextPiece.shape.length * size) / 2; for (let r = 0; r < nextPiece.shape.length; r++) { for (let c = 0; c < nextPiece.shape[r].length; c++) { if (nextPiece.shape[r][c]) { nextCtx.fillStyle = nextPiece.color; nextCtx.fillRect(offsetX + c * size, offsetY + r * size, size, size); nextCtx.strokeStyle = 'rgba(0, 0, 0, 0.3)'; nextCtx.strokeRect(offsetX + c * size, offsetY + r * size, size, size); } } } } // 检测碰撞 function collide(piece, offsetX = 0, offsetY = 0) { for (let r = 0; r < piece.shape.length; r++) { for (let c = 0; c < piece.shape[r].length; c++) { if (piece.shape[r][c]) { const newX = piece.x + c + offsetX; const newY = piece.y + r + offsetY; if (newX < 0 || newX >= COLS || newY >= ROWS) { return true; } if (newY >= 0 && board[newY][newX]) { return true; } } } } return false; } // 锁定方块 function lockPiece() { for (let r = 0; r < currentPiece.shape.length; r++) { for (let c = 0; c < currentPiece.shape[r].length; c++) { if (currentPiece.shape[r][c]) { if (currentPiece.y + r < 0) { gameOver(); return; } board[currentPiece.y + r][currentPiece.x + c] = currentPiece.color; } } } clearLines(); currentPiece = nextPiece; nextPiece = createPiece(); drawNextPiece(); if (collide(currentPiece)) { gameOver(); } } // 消除行 function clearLines() { let linesCleared = 0; for (let r = ROWS - 1; r >= 0; r--) { if (board[r].every(cell => cell !== 0)) { board.splice(r, 1); board.unshift(new Array(COLS).fill(0)); linesCleared++; r++; } } if (linesCleared > 0) { updateScore(linesCleared); } } // 更新分数 function updateScore(linesCleared) { const points = [0, 100, 300, 500, 800]; score += points[linesCleared] * level; lines += linesCleared; // 升级 if (lines >= level * 10) { level++; dropInterval = Math.max(100, 1000 - (level - 1) * 100); resetGameLoop(); } updateDisplay(); } // 更新显示 function updateDisplay() { document.getElementById('score').textContent = score; document.getElementById('level').textContent = level; document.getElementById('lines').textContent = lines; } // 移动方块 function movePiece(offsetX, offsetY) { if (!currentPiece || isPaused || isGameOver) return; if (!collide(currentPiece, offsetX, offsetY)) { currentPiece.x += offsetX; currentPiece.y += offsetY; draw(); } } // 旋转方块 function rotatePiece() { if (!currentPiece || isPaused || isGameOver) return; const rotated = currentPiece.shape[0].map((_, index) => currentPiece.shape.map(row => row[index]).reverse() ); const originalShape = currentPiece.shape; currentPiece.shape = rotated; // 墙踢 - 尝试调整位置 const kicks = [0, -1, 1, -2, 2]; for (let kick of kicks) { if (!collide(currentPiece, kick, 0)) { currentPiece.x += kick; draw(); return; } } // 无法旋转,恢复原状 currentPiece.shape = originalShape; } // 硬降落 function hardDrop() { if (!currentPiece || isPaused || isGameOver) return; while (!collide(currentPiece, 0, 1)) { currentPiece.y++; score += 2; } lockPiece(); updateDisplay(); draw(); } // 绘制 function draw() { drawBoard(); drawPiece(); } // 游戏循环 function gameStep() { if (!isPaused && !isGameOver) { if (!collide(currentPiece, 0, 1)) { currentPiece.y++; draw(); } else { lockPiece(); } } } // 开始游戏循环 function startGameLoop() { gameLoop = setInterval(gameStep, dropInterval); } // 重置游戏循环 function resetGameLoop() { clearInterval(gameLoop); startGameLoop(); } // 开始游戏 function startGame() { // 重置状态 for (let r = 0; r < ROWS; r++) { for (let c = 0; c < COLS; c++) { board[r][c] = 0; } } score = 0; level = 1; lines = 0; dropInterval = 1000; isPaused = false; isGameOver = false; // 隐藏游戏结束界面 document.getElementById('game-over').classList.add('hidden'); // 创建方块 currentPiece = createPiece(); nextPiece = createPiece(); updateDisplay(); drawNextPiece(); draw(); startGameLoop(); } // 游戏结束 function gameOver() { isGameOver = true; clearInterval(gameLoop); document.getElementById('final-score').textContent = score; document.getElementById('game-over').classList.remove('hidden'); } // 键盘事件处理 function handleKeyPress(e) { if (isGameOver) return; switch (e.key) { case 'ArrowLeft': e.preventDefault(); movePiece(-1, 0); break; case 'ArrowRight': e.preventDefault(); movePiece(1, 0); break; case 'ArrowDown': e.preventDefault(); movePiece(0, 1); score += 1; updateDisplay(); break; case 'ArrowUp': e.preventDefault(); rotatePiece(); break; case ' ': e.preventDefault(); hardDrop(); break; case 'p': case 'P': isPaused = !isPaused; break; } } // 启动 window.onload = init;