Files
nanocode/happy-games/games/tetris/test_game_loop.html
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

342 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🎮 俄罗斯方块 - 游戏循环测试</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0a0a1a;
color: white;
font-family: monospace;
padding: 20px;
}
canvas {
border: 2px solid white;
background: #111827;
display: block;
margin: 20px auto;
}
.info {
text-align: center;
margin: 20px;
}
.debug {
background: black;
color: lime;
padding: 10px;
border-radius: 5px;
margin: 10px auto;
max-width: 600px;
max-height: 200px;
overflow-y: auto;
}
button {
padding: 10px 20px;
background: #00d4ff;
border: none;
border-radius: 5px;
color: black;
font-weight: bold;
cursor: pointer;
margin: 5px;
}
</style>
</head>
<body>
<div class="info">
<h1>🎮 俄罗斯方块 - 游戏循环测试</h1>
<p>测试游戏循环是否正常工作</p>
</div>
<canvas id="game-canvas" width="240" height="480"></canvas>
<div class="info">
<button onclick="startGame()">▶️ 开始游戏</button>
<button onclick="pauseGame()">⏸️ 暂停</button>
<button onclick="resetGame()">🔄 重置</button>
</div>
<div class="debug" id="debug">
<div>调试信息:</div>
</div>
<script>
// 调试日志
function debugLog(message) {
const debugEl = document.getElementById('debug');
const logEntry = document.createElement('div');
logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
debugEl.appendChild(logEntry);
debugEl.scrollTop = debugEl.scrollHeight;
console.log(message);
}
// 游戏配置
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const gridWidth = 10;
const gridHeight = 20;
const cellSize = 24;
let board = Array(gridHeight).fill().map(() => Array(gridWidth).fill(0));
let currentPiece = null;
let gameLoop = null;
let dropTimer = 0;
let lastFrameTime = 0;
let isPaused = false;
let isGameOver = false;
// 方块类型
const pieceTypes = [
{ type: 'I', shape: [[1,1,1,1]], color: '#00f5ff' },
{ type: 'J', shape: [[1,0,0],[1,1,1]], color: '#0000ff' },
{ type: 'L', shape: [[0,0,1],[1,1,1]], color: '#ff8000' },
{ type: 'O', shape: [[1,1],[1,1]], color: '#ffff00' },
{ type: 'S', shape: [[0,1,1],[1,1,0]], color: '#00ff00' },
{ type: 'T', shape: [[0,1,0],[1,1,1]], color: '#8000ff' },
{ type: 'Z', shape: [[1,1,0],[0,1,1]], color: '#ff0000' }
];
// 游戏函数
function spawnNewPiece() {
const randomType = pieceTypes[Math.floor(Math.random() * pieceTypes.length)];
currentPiece = {
type: randomType.type,
shape: randomType.shape,
color: randomType.color,
x: Math.floor(gridWidth / 2) - Math.floor(randomType.shape[0].length / 2),
y: 0
};
debugLog(`生成新方块: ${currentPiece.type}`);
}
function isValidMove(shape, x, y) {
for (let row = 0; row < shape.length; row++) {
for (let col = 0; col < shape[row].length; col++) {
if (shape[row][col]) {
const newX = x + col;
const newY = y + row;
if (newX < 0 || newX >= gridWidth || newY >= gridHeight) {
return false;
}
if (newY >= 0 && board[newY][newX]) {
return false;
}
}
}
}
return true;
}
function movePiece(dx, dy) {
if (!currentPiece || isPaused || isGameOver) return;
const newX = currentPiece.x + dx;
const newY = currentPiece.y + dy;
if (isValidMove(currentPiece.shape, newX, newY)) {
currentPiece.x = newX;
currentPiece.y = newY;
} else if (dy > 0) {
lockPiece();
spawnNewPiece();
if (!isValidMove(currentPiece.shape, currentPiece.x, currentPiece.y)) {
gameOver();
}
}
}
function lockPiece() {
const { shape, x, y, color } = currentPiece;
for (let row = 0; row < shape.length; row++) {
for (let col = 0; col < shape[row].length; col++) {
if (shape[row][col]) {
const boardX = x + col;
const boardY = y + row;
if (boardY >= 0) {
board[boardY][boardX] = color;
}
}
}
}
debugLog(`方块固定在位置: (${x}, ${y})`);
}
function gameOver() {
isGameOver = true;
if (gameLoop) {
cancelAnimationFrame(gameLoop);
gameLoop = null;
}
debugLog(`游戏结束!`);
}
// 渲染函数
function render() {
// 清空画布
ctx.fillStyle = '#111827';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制网格
ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
ctx.lineWidth = 1;
for (let x = 0; x <= gridWidth; x++) {
ctx.beginPath();
ctx.moveTo(x * cellSize, 0);
ctx.lineTo(x * cellSize, canvas.height);
ctx.stroke();
}
for (let y = 0; y <= gridHeight; y++) {
ctx.beginPath();
ctx.moveTo(0, y * cellSize);
ctx.lineTo(canvas.width, y * cellSize);
ctx.stroke();
}
// 绘制已固定的方块
for (let y = 0; y < gridHeight; y++) {
for (let x = 0; x < gridWidth; x++) {
if (board[y][x]) {
ctx.fillStyle = board[y][x];
ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize);
ctx.strokeStyle = 'white';
ctx.lineWidth = 2;
ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize);
}
}
}
// 绘制当前方块
if (currentPiece) {
const { shape, x, y, color } = currentPiece;
ctx.fillStyle = color;
for (let row = 0; row < shape.length; row++) {
for (let col = 0; col < shape[row].length; col++) {
if (shape[row][col]) {
ctx.fillRect((x + col) * cellSize, (y + row) * cellSize, cellSize, cellSize);
ctx.strokeStyle = 'white';
ctx.lineWidth = 2;
ctx.strokeRect((x + col) * cellSize, (y + row) * cellSize, cellSize, cellSize);
}
}
}
}
}
// 游戏循环
function startGameLoop() {
if (gameLoop) {
cancelAnimationFrame(gameLoop);
}
const loop = (timestamp) => {
if (!lastFrameTime) lastFrameTime = timestamp;
const deltaTime = timestamp - lastFrameTime;
// 自动下落
if (!isPaused && !isGameOver) {
dropTimer += deltaTime;
if (dropTimer > 1000) { // 每秒下落一次
movePiece(0, 1);
dropTimer = 0;
debugLog('方块自动下落');
}
}
// 渲染
render();
// 继续循环
gameLoop = requestAnimationFrame(loop);
lastFrameTime = timestamp;
};
gameLoop = requestAnimationFrame(loop);
debugLog('✅ 游戏循环已启动');
}
// 控制函数
window.startGame = function() {
debugLog('🎮 开始游戏...');
// 重置游戏状态
board = Array(gridHeight).fill().map(() => Array(gridWidth).fill(0));
isPaused = false;
isGameOver = false;
dropTimer = 0;
lastFrameTime = 0;
// 生成第一个方块
spawnNewPiece();
// 开始游戏循环
startGameLoop();
debugLog('✅ 游戏开始!');
};
window.pauseGame = function() {
isPaused = !isPaused;
debugLog(isPaused ? '⏸️ 游戏暂停' : '▶️ 游戏继续');
};
window.resetGame = function() {
debugLog('🔄 重置游戏');
startGame();
};
// 键盘控制
document.addEventListener('keydown', (e) => {
if (!currentPiece || isPaused || isGameOver) return;
switch(e.key) {
case 'ArrowLeft':
movePiece(-1, 0);
debugLog('← 左移');
break;
case 'ArrowRight':
movePiece(1, 0);
debugLog('→ 右移');
break;
case 'ArrowDown':
movePiece(0, 1);
debugLog('↓ 下移');
break;
case 'ArrowUp':
// 旋转
debugLog('↑ 旋转');
break;
}
});
// 页面加载完成
window.addEventListener('load', () => {
debugLog('页面加载完成');
debugLog(`浏览器: ${navigator.userAgent}`);
debugLog(`平台: ${navigator.platform}`);
// 自动开始游戏
setTimeout(() => {
startGame();
}, 1000);
});
</script>
</body>
</html>