a
This commit is contained in:
@@ -0,0 +1,342 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user