一.演示
二.代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<title>贪吃蛇</title>
<style>
#myCanvas {
display: block;
margin: 0 auto;
margin-top: 100px;
border: 5px solid #76B947;
background: #F0F0F0;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="800" height="500"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let foodWidth = 10;
let foodHeight = 10;
let snakeWidth = 10;
let snakeHeight = 10;
let foodX = Math.floor(Math.random() * (canvas.width / snakeWidth)) * snakeWidth;
let foodY = Math.floor(Math.random() * (canvas.height / snakeHeight)) * snakeHeight;
let dx = 10;
let dy = 0;
let score = 0;
let snake = [
{ x: canvas.width / 2, y: canvas.height / 2 },
{ x: canvas.width / 2 - snakeWidth, y: canvas.height / 2 },
{ x: canvas.width / 2 - 2 * snakeWidth, y: canvas.height / 2 }
];
document.addEventListener("keydown", keydownHandler, false);
//定义了蛇的移动方式,并且确保了蛇不能掉头
function keydownHandler(e) {
if (e.key == "ArrowUp" && dy === 0) {
dx = 0;
dy = -snakeHeight;
} else if (e.key == "ArrowDown" && dy === 0) {
dx = 0;
dy = snakeHeight;
} else if (e.key == "ArrowLeft" && dx === 0) {
dx = -snakeWidth;
dy = 0;
} else if (e.key == "ArrowRight" && dx === 0) {
dx = snakeWidth;
dy = 0;
}
}
function drawFood() {
ctx.beginPath();
ctx.fillStyle = '#0095DD';
ctx.fillRect(foodX, foodY, foodWidth, foodHeight);
}
function drawScore() {
ctx.font = '16px Arial'
ctx.fillStyle = '#0095DD'
ctx.fillText('Score:' + score, 10, 20)
}
function drawSnake() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
console.log(canvas.width, canvas.height);
drawScore();
drawFood();
for (let i = 0; i < snake.length; i++) {
ctx.fillStyle = i == 0 ? 'black' : 'green';
ctx.fillRect(snake[i].x, snake[i].y, snakeWidth, snakeHeight);
// 添加轻微的阴影效果
ctx.shadowBlur = 3;
ctx.shadowColor = "gray";
}
ctx.shadowBlur = 0;
}
function moveSnake() {
const head = { x: snake[0].x + dx, y: snake[0].y + dy };
snake.unshift(head);
console.log(snake.length);
if (head.x === foodX && head.y === foodY) {
foodX = Math.floor(Math.random() * (canvas.width / snakeWidth)) * snakeWidth;
foodY = Math.floor(Math.random() * (canvas.height / snakeHeight)) * snakeHeight;
score++;
} else {
snake.pop();
}
// 边界检测
if (head.x < 0 - 10 || head.x >= canvas.width + 10 || head.y < 0 - 10 || head.y >= canvas.height + 10) {
alert("游戏结束");
document.location.reload();
}
// 检测蛇是否咬到自己
for (let i = 4; i < snake.length; i++) {
if (head.x == snake[i].x && head.y == snake[i].y) {
alert("游戏结束");
document.location.reload();
}
}
}
function draw() {
drawSnake();
moveSnake();
}
setInterval(draw, 100); // 每100毫秒更新一次游戏状态
</script>
</body>
</html>
三.复盘
完成贪吃蛇核心的逻辑就是食物的随机生成,蛇的移动逻辑, 游戏的边界检测,蛇吃到食物身体增加等,虽然还有其它方法完成这个游戏,但我认为用画布就是最一目了然的,而且逻辑方面也很好解决,推荐使用。