Files
snake-game/game.js
openclaw dab43051ab 阶段1:项目初始化完成
- 创建基础项目结构
- 实现 HTML/CSS/JS 基础框架
- 配置游戏界面和样式

Closes #1
2026-02-27 14:01:03 +00:00

279 lines
6.6 KiB
JavaScript

// 游戏配置
const CONFIG = {
gridSize: 20, // 网格大小
canvasSize: 400, // 画布大小
easySpeed: 150, // 简单模式速度
mediumSpeed: 100, // 中等模式速度
hardSpeed: 50 // 困难模式速度
};
// 游戏状态
let snake = [];
let food = {};
let direction = 'right';
let nextDirection = 'right';
let score = 0;
let gameLoop = null;
let isPaused = false;
let isGameRunning = false;
// DOM 元素
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const startBtn = document.getElementById('startBtn');
const pauseBtn = document.getElementById('pauseBtn');
const resetBtn = document.getElementById('resetBtn');
const difficultySelect = document.getElementById('difficulty');
// 初始化游戏
function initGame() {
snake = [
{ x: 5, y: 10 },
{ x: 4, y: 10 },
{ x: 3, y: 10 }
];
direction = 'right';
nextDirection = 'right';
score = 0;
isPaused = false;
isGameRunning = false;
updateScore();
spawnFood();
draw();
}
// 生成食物
function spawnFood() {
const maxPos = CONFIG.canvasSize / CONFIG.gridSize;
let newFood;
do {
newFood = {
x: Math.floor(Math.random() * maxPos),
y: Math.floor(Math.random() * maxPos)
};
} while (snake.some(segment => segment.x === newFood.x && segment.y === newFood.y));
food = newFood;
}
// 更新游戏状态
function update() {
if (isPaused) return;
direction = nextDirection;
// 计算蛇头新位置
const head = { ...snake[0] };
switch (direction) {
case 'up':
head.y -= 1;
break;
case 'down':
head.y += 1;
break;
case 'left':
head.x -= 1;
break;
case 'right':
head.x += 1;
break;
}
// 检查碰撞
if (checkCollision(head)) {
gameOver();
return;
}
// 添加蛇头
snake.unshift(head);
// 检查是否吃到食物
if (head.x === food.x && head.y === food.y) {
score += 10;
updateScore();
spawnFood();
} else {
snake.pop();
}
draw();
}
// 检查碰撞
function checkCollision(head) {
const maxPos = CONFIG.canvasSize / CONFIG.gridSize;
// 撞墙检测
if (head.x < 0 || head.x >= maxPos || head.y < 0 || head.y >= maxPos) {
return true;
}
// 撞自己检测
return snake.some(segment => segment.x === head.x && segment.y === head.y);
}
// 绘制游戏
function draw() {
// 清空画布
ctx.fillStyle = '#2c3e50';
ctx.fillRect(0, 0, CONFIG.canvasSize, CONFIG.canvasSize);
// 绘制蛇
snake.forEach((segment, index) => {
const gradient = ctx.createRadialGradient(
segment.x * CONFIG.gridSize + CONFIG.gridSize / 2,
segment.y * CONFIG.gridSize + CONFIG.gridSize / 2,
0,
segment.x * CONFIG.gridSize + CONFIG.gridSize / 2,
segment.y * CONFIG.gridSize + CONFIG.gridSize / 2,
CONFIG.gridSize
);
if (index === 0) {
gradient.addColorStop(0, '#2ecc71');
gradient.addColorStop(1, '#27ae60');
} else {
gradient.addColorStop(0, '#82e0aa');
gradient.addColorStop(1, '#58d68d');
}
ctx.fillStyle = gradient;
ctx.fillRect(
segment.x * CONFIG.gridSize + 1,
segment.y * CONFIG.gridSize + 1,
CONFIG.gridSize - 2,
CONFIG.gridSize - 2
);
});
// 绘制食物
const foodGradient = ctx.createRadialGradient(
food.x * CONFIG.gridSize + CONFIG.gridSize / 2,
food.y * CONFIG.gridSize + CONFIG.gridSize / 2,
0,
food.x * CONFIG.gridSize + CONFIG.gridSize / 2,
food.y * CONFIG.gridSize + CONFIG.gridSize / 2,
CONFIG.gridSize
);
foodGradient.addColorStop(0, '#e74c3c');
foodGradient.addColorStop(1, '#c0392b');
ctx.fillStyle = foodGradient;
ctx.beginPath();
ctx.arc(
food.x * CONFIG.gridSize + CONFIG.gridSize / 2,
food.y * CONFIG.gridSize + CONFIG.gridSize / 2,
CONFIG.gridSize / 2 - 2,
0,
Math.PI * 2
);
ctx.fill();
}
// 更新分数
function updateScore() {
scoreElement.textContent = score;
}
// 游戏结束
function gameOver() {
stopGame();
alert(`游戏结束!得分:${score}\n点击"重置"重新开始`);
}
// 开始游戏
function startGame() {
if (isGameRunning) return;
initGame();
isGameRunning = true;
startBtn.disabled = true;
pauseBtn.disabled = false;
difficultySelect.disabled = true;
const speed = getGameSpeed();
gameLoop = setInterval(update, speed);
}
// 停止游戏
function stopGame() {
if (gameLoop) {
clearInterval(gameLoop);
gameLoop = null;
}
isGameRunning = false;
startBtn.disabled = false;
pauseBtn.disabled = true;
pauseBtn.textContent = '暂停';
difficultySelect.disabled = false;
}
// 暂停/继续游戏
function togglePause() {
if (!isGameRunning) return;
isPaused = !isPaused;
if (isPaused) {
pauseBtn.textContent = '继续';
} else {
pauseBtn.textContent = '暂停';
}
}
// 重置游戏
function resetGame() {
stopGame();
initGame();
}
// 获取游戏速度
function getGameSpeed() {
const difficulty = difficultySelect.value;
switch (difficulty) {
case 'easy':
return CONFIG.easySpeed;
case 'medium':
return CONFIG.mediumSpeed;
case 'hard':
return CONFIG.hardSpeed;
default:
return CONFIG.mediumSpeed;
}
}
// 键盘控制
document.addEventListener('keydown', (e) => {
const key = e.key;
if (key === 'ArrowUp' && direction !== 'down') {
nextDirection = 'up';
e.preventDefault();
} else if (key === 'ArrowDown' && direction !== 'up') {
nextDirection = 'down';
e.preventDefault();
} else if (key === 'ArrowLeft' && direction !== 'right') {
nextDirection = 'left';
e.preventDefault();
} else if (key === 'ArrowRight' && direction !== 'left') {
nextDirection = 'right';
e.preventDefault();
} else if (key === ' ' && isGameRunning) {
togglePause();
e.preventDefault();
}
});
// 按钮事件
startBtn.addEventListener('click', startGame);
pauseBtn.addEventListener('click', togglePause);
resetBtn.addEventListener('click', resetGame);
// 初始化
initGame();