引言
在当今数字化时代,编程已经成为一种极具创造力和趣味性的活动。通过编写代码,我们可以创造出各种各样的应用程序和游戏,其中包括经典的贪吃蛇游戏。本文将向您介绍如何使用 JavaScript 编程语言制作一个简单而有趣的贪吃蛇游戏,并通过代码分析和解释帮助您了解游戏的实现原理。
一、游戏背景
贪吃蛇是一款经典的街机游戏,早在 Nokia 手机时代就备受欢迎。玩家控制一条蛇在一个有限的空间内移动,吃掉食物以增加长度,同时要避免撞到墙壁或自身。本文将使用 HTML5 的 Canvas 元素和 JavaScript 语言来实现这个经典游戏的简化版本。
二、游戏功能及实现
首先,我们需要定义一些游戏所需的变量,如蛇的初始位置、食物的位置、移动速度等。接着,我们监听键盘事件,根据用户按键改变蛇的移动方向。蛇的移动是通过周期性地更新蛇头位置并移除蛇尾来实现的。当蛇吃到食物时,增加得分并重新生成食物位置;当蛇头碰到墙壁或自身时,游戏结束。
三、代码分析
3.1 html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>贪吃蛇游戏</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="header">
<div>难度:<span id="speed"></span></div>
<div>分数:<span id="score"></span></div>
</div>
<canvas id="gameCanvas" width="400" height="400"></canvas>
</div>
<script src="game.js"></script>
</body>
</html>
3.2 css代码
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #212121;
}
.header {
background-color: #266e61;
color: #f9f9f9;
display: flex;
justify-content: space-between;
padding: 10px 40px;
border-radius: 10px;
margin-bottom: 10px;
}
span {
font-size: 20px;
}
canvas {
background-color: #353535;
border: 1px solid black;
border-radius: 10px;
padding: 10px;
}
3.3 JavaScript核心代码
我们将代码分为几个主要功能函数:
changeDirection(event)
:监听键盘事件,根据按键改变蛇的移动方向。
function changeDirection(event) {
const keyPressed = event.key; // 获取按下的键值
// 根据按键改变蛇的移动方向,确保蛇不会向相反方向移动
if (keyPressed === "ArrowUp" && dy === 0) {
dx = 0;
dy = -gridSize;
} else if (keyPressed === "ArrowDown" && dy === 0) {
dx = 0;
dy = gridSize;
} else if (keyPressed === "ArrowLeft" && dx === 0) {
dx = -gridSize;
dy = 0;
} else if (keyPressed === "ArrowRight" && dx === 0) {
dx = gridSize;
dy = 0;
}
}
moveSnake()
:更新蛇的位置,处理吃食物和碰撞检测逻辑。
function moveSnake() {
const head = { x: snake[0].x + dx, y: snake[0].y + dy }; // 计算蛇头的新位置
snake.unshift(head); // 将新的蛇头加入到蛇的数组中
// 如果蛇吃到食物
if (head.x === food.x && head.y === food.y) {
food = getRandomPosition(); // 重新生成食物位置
score += 10; // 增加得分
document.getElementById("score").textContent = score; // 更新得分显示
// 每吃到50分,增加游戏速度
if (score % 50 === 0) {
speed += 1; // 增加速度
document.getElementById("speed").textContent = speed; // 更新速度显示
}
} else {
snake.pop(); // 如果没有吃到食物,移除蛇尾,实现蛇的移动效果
}
// 如果蛇碰到墙壁或者自身,游戏结束
if (
head.x < 0 ||
head.x >= canvas.width ||
head.y < 0 ||
head.y >= canvas.height ||
collision()
) {
gameOver = true; // 设置游戏结束标志为true
}
}
drawSnake()
和drawFood()
:绘制蛇和食物。
function drawSnake() {
// 绘制蛇身
snake.forEach((segment) => {
ctx.fillStyle = "#266e5f"; // 设置蛇的颜色
ctx.fillRect(segment.x, segment.y, gridSize, gridSize); // 绘制蛇的每一段
});
}
collision()
:检测蛇头是否与蛇身相撞。
function collision() {
// 检测蛇头是否与蛇身相撞
return snake
.slice(1)
.some((segment) => segment.x === snake[0].x && segment.y === snake[0].y);
}
drawGrid()
:绘制游戏网格。
function drawGrid() {
// 绘制游戏网格
for (let x = 0; x < canvas.width; x += gridSize) {
for (let y = 0; y < canvas.height; y += gridSize) {
ctx.strokeStyle = "black"; // 设置边框颜色
ctx.lineWidth = gridBorderWidth; // 设置边框宽度
ctx.strokeRect(x, y, gridSize, gridSize); // 绘制方格边框
}
}
}
3.4 整体代码
const canvas = document.getElementById("gameCanvas"); // 获取画布元素
const ctx = canvas.getContext("2d"); // 获取2D绘图上下文
const gridSize = 20; // 网格大小
const gridBorderWidth = 1; // 新增的边框宽度
let snake = [{ x: 200, y: 200 }]; // 蛇的初始位置
let food = getRandomPosition(); // 随机生成食物位置
let dx = gridSize; // 蛇的水平移动速度
let dy = 0; // 蛇的垂直移动速度
let gameOver = false; // 游戏结束标志
let speed = 1; // 游戏速度
let score = 0; // 得分
init(); //初始化
document.addEventListener("keydown", changeDirection); // 监听键盘按下事件,改变蛇的移动方向
function init() {
document.getElementById("score").textContent = score;
document.getElementById("speed").textContent = speed;
}
function changeDirection(event) {
const keyPressed = event.key; // 获取按下的键值
// 根据按键改变蛇的移动方向,确保蛇不会向相反方向移动
if (keyPressed === "ArrowUp" && dy === 0) {
dx = 0;
dy = -gridSize;
} else if (keyPressed === "ArrowDown" && dy === 0) {
dx = 0;
dy = gridSize;
} else if (keyPressed === "ArrowLeft" && dx === 0) {
dx = -gridSize;
dy = 0;
} else if (keyPressed === "ArrowRight" && dx === 0) {
dx = gridSize;
dy = 0;
}
}
function drawSnake() {
// 绘制蛇身
snake.forEach((segment) => {
ctx.fillStyle = "#266e5f"; // 设置蛇的颜色
ctx.fillRect(segment.x, segment.y, gridSize, gridSize); // 绘制蛇的每一段
});
}
function moveSnake() {
const head = { x: snake[0].x + dx, y: snake[0].y + dy }; // 计算蛇头的新位置
snake.unshift(head); // 将新的蛇头加入到蛇的数组中
// 如果蛇吃到食物
if (head.x === food.x && head.y === food.y) {
food = getRandomPosition(); // 重新生成食物位置
score += 10; // 增加得分
document.getElementById("score").textContent = score; // 更新得分显示
// 每吃到50分,增加游戏速度
if (score % 50 === 0) {
speed += 1; // 增加速度
document.getElementById("speed").textContent = speed; // 更新速度显示
}
} else {
snake.pop(); // 如果没有吃到食物,移除蛇尾,实现蛇的移动效果
}
// 如果蛇碰到墙壁或者自身,游戏结束
if (
head.x < 0 ||
head.x >= canvas.width ||
head.y < 0 ||
head.y >= canvas.height ||
collision()
) {
gameOver = true; // 设置游戏结束标志为true
}
}
function drawFood() {
ctx.fillStyle = "#FFF"; // 设置食物的颜色
ctx.fillRect(food.x, food.y, gridSize, gridSize); // 绘制食物
}
function getRandomPosition() {
// 随机生成食物的位置,确保在网格内
return {
x: Math.floor(Math.random() * (canvas.width / gridSize)) * gridSize,
y: Math.floor(Math.random() * (canvas.height / gridSize)) * gridSize,
};
}
function collision() {
// 检测蛇头是否与蛇身相撞
return snake
.slice(1)
.some((segment) => segment.x === snake[0].x && segment.y === snake[0].y);
}
function drawGrid() {
// 绘制游戏网格
for (let x = 0; x < canvas.width; x += gridSize) {
for (let y = 0; y < canvas.height; y += gridSize) {
ctx.strokeStyle = "black"; // 设置边框颜色
ctx.lineWidth = gridBorderWidth; // 设置边框宽度
ctx.strokeRect(x, y, gridSize, gridSize); // 绘制方格边框
}
}
}
function draw() {
// 主绘制函数
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
drawGrid(); // 绘制游戏网格
drawSnake(); // 绘制蛇身
drawFood(); // 绘制食物
moveSnake(); // 移动蛇
// 如果游戏结束,显示游戏结束文字
if (gameOver) {
ctx.fillStyle = "#FFF";
ctx.font = "35px Arial";
ctx.fillText("游戏 结束", canvas.width / 2 - 65, canvas.height / 2);
return;
}
setTimeout(draw, 1000 / speed); // 根据速度调整 setTimeout 的时间间隔,实现游戏速度控制
}
draw(); // 开始游戏