创建一个简单的贪吃蛇游戏:HTML、CSS和JavaScript教程
在本教程中,我们将逐步构建一个简单的贪吃蛇游戏。这个项目适合初学者,可以帮助你理解HTML、CSS和JavaScript的基础知识,并掌握如何将它们结合起来创建一个完整的游戏。
准备工作
在开始之前,请确保你已经安装了一个代码编辑器(如Visual Studio Code)和一个浏览器(如Chrome或Firefox)。
第一步:创建HTML文件
首先,我们需要一个HTML文件来定义游戏的结构。在你的项目文件夹中创建一个名为index.html
的文件,并添加以下代码:
<!DOCTYPE html>
<!-- 声明文档类型为 HTML5 --><html lang="en">
<!-- HTML 文档的开始,指定语言为英文 --><head><!-- 文档的头部区域,包含文档的元数据和链接到外部资源的标签 --><meta charset="UTF-8"><!-- 设置字符编码为 UTF-8,以支持各种字符 --><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- 设置视口以适应移动设备的宽度,并使用初始缩放级别 1.0 --><title>贪吃蛇小游戏</title><!-- 设置网页的标题为“贪吃蛇小游戏”,显示在浏览器标签上 --><style>/* 内部 CSS 样式,用于设置网页的外观 */canvas {background-color: #f4f4f4;/* 设置 canvas 元素的背景颜色为浅灰色 */display: block;/* 将 canvas 元素设置为块级元素,使其在页面中独占一行 */margin: 50px auto;/* 设置 canvas 元素的上下外边距为 50px,左右外边距自动对齐,居中显示 */border: 1px solid black;/* 给 canvas 元素添加 1px 宽的黑色边框 */}#score {/* 设置一个 id 为 score 的元素的样式 */}</style>
</head><body><!-- 文档的主体区域,包含网页的内容 --><canvas id="gameCanvas" width="500" height="500"></canvas><!-- 创建一个 id 为 gameCanvas 的 canvas 元素,用于绘制游戏内容,宽度和高度均为 500px --><div id="score">分数: 0</div><!-- 创建一个 id 为 score 的 div 元素,用于显示游戏的分数 --><script src="game.js"></script><!-- 引入一个名为 game.js 的外部 JavaScript 文件,用于实现游戏逻辑 -->
</body></html>text-align: center;font-size: 24px;}</style></head><body><div id="score">分数: 0</div><canvas id="gameCanvas" width="400" height="400"></canvas><audio id="eatSound" src="eat.mp3"></audio><script src="game.js"></script></body></html>
解释
<!DOCTYPE html>
:声明文档的类型为 HTML5,帮助浏览器正确渲染页面。<html lang="en">
:定义 HTML 文档的根元素,并指定语言为英文。<head>
:包含文档的元数据和资源链接。<meta charset="UTF-8">
:设置字符编码为 UTF-8,确保网页支持多语言字符。<meta name="viewport" content="width=device-width, initial-scale=1.0">
:确保网页在移动设备上适应宽度,并设置初始缩放级别。<title>贪吃蛇小游戏</title>
:设置网页的标题。<style>
:包含内部 CSS 样式,用于设置页面的样式。canvas
:设置 canvas 元素的背景颜色、显示方式、外边距和边框样式。#score
:为分数显示元素预留了样式设置位置(目前为空)。
<body>
:文档主体,包含页面的实际内容。<canvas id="gameCanvas" width="500" height="500"></canvas>
:定义了一个用于绘制游戏的画布,大小为 500x500 像素。<div id="score">分数: 0</div>
:一个显示游戏分数的 div 元素。<script src="game.js"></script>
:引入外部 JavaScript 文件,用于实现游戏逻辑。
第二步:创建JavaScript文件
在你的项目文件夹中创建一个名为game.js
的文件,并添加以下代码:
const canvas = document.getElementById('gameCanvas');const ctx = canvas.getContext('2d');const scoreDisplay = document.getElementById('score');const eatSound = document.getElementById('eatSound');const gridSize = 20;const canvasWidth = canvas.width;const canvasHeight = canvas.height;const gridWidth = canvasWidth / gridSize;const gridHeight = canvasHeight / gridSize;let snake = [{ x: 10, y: 10 }];let food = generateFood();let dx = 1, dy = 0;let score = 0;let speed = 100; // 游戏速度 (毫秒)let gameInterval;let isPaused = false; // 暂停状态document.addEventListener('keydown', changeDirection);document.addEventListener('keydown', controlGame);startGame();function changeDirection(e) {switch (e.keyCode) {case 37: // 左箭头if (dx === 0) { dx = -1; dy = 0; }break;case 38: // 上箭头if (dy === 0) { dx = 0; dy = -1; }break;case 39: // 右箭头if (dx === 0) { dx = 1; dy = 0; }break;case 40: // 下箭头if (dy === 0) { dx = 0; dy = 1; }break;}}function controlGame(e) {switch (e.keyCode) {case 80: // 'P' 键togglePause();break;case 187: // '+' 键speed = Math.max(10, speed - 10); // 增加速度updateGameSpeed();break;case 189: // '-' 键speed += 10; // 减少速度updateGameSpeed();break;}}function startGame() {gameInterval = setInterval(loop, speed);}function loop() {if (isPaused) return;const head = { ...snake[0] };head.x += dx;head.y += dy;// 碰撞检测if (head.x < 0 || head.x >= gridWidth || head.y < 0 || head.y >= gridHeight ||
snakeCollision(head)) {endGame();return;}snake.unshift(head);// 检查是否吃到食物if (snake[0].x === food.x && snake[0].y === food.y) {score += 10; // 增加分数scoreDisplay.textContent = `分数: ${score}`;eatSound.play(); // 播放音效food = generateFood(); // 生成新的食物} else {snake.pop();}drawGame();}function drawGame() {ctx.fillStyle = '#f4f4f4';ctx.fillRect(0, 0, canvasWidth, canvasHeight);ctx.fillStyle = 'red';ctx.fillRect(food.x * gridSize, food.y * gridSize, gridSize, gridSize);ctx.fillStyle = 'green';snake.forEach(segment => {ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);});}function snakeCollision(head) {for (let i = 1; i < snake.length; i++) {if (head.x === snake[i].x && head.y === snake[i].y) {return true;}}return false;}function generateFood() {let foodPosition;while (true) {foodPosition = { x: Math.floor(Math.random() * gridWidth), y:
Math.floor(Math.random() * gridHeight) };if (!snakeCollision(foodPosition)) break; // 确保食物不出现在蛇身上}return foodPosition;}function endGame() {clearInterval(gameInterval);alert(`游戏结束!你的得分是: ${score}`);resetGame();}function resetGame() {snake = [{ x: 10, y: 10 }];dx = 1;dy = 0;score = 0;scoreDisplay.textContent = `分数: ${score}`;food = generateFood();startGame();}function togglePause() {isPaused = !isPaused;if (!isPaused) {startGame();} else {clearInterval(gameInterval);}}function updateGameSpeed() {clearInterval(gameInterval);startGame();}
解释
-
changeDirection
函数用于更改蛇的移动方向。 -
controlGame
函数用于控制游戏的暂停和速度调整。 -
startGame
函数启动游戏循环。 -
loop
函数是游戏的核心逻辑,包含移动、碰撞检测、食物生成和得分更新等功能。 -
drawGame
函数用于绘制蛇和食物。 -
generateFood
函数用于随机生成食物位置。 -
endGame
函数在游戏结束时显示得分并重置游戏。 -
togglePause
函数用于暂停和恢复游戏。 -
updateGameSpeed
函数用于更新游戏速度。
第三步:功能概述
-
分数系统:
在gameloop
函数中,我们增加了一个分数检测逻辑。当蛇头与食物的位置相同时,我们会增加分数。为了显示分数,我们在index.html
中增加了一个新的<div>
标签来显示分数。在每次吃到食物后,我们将分数增加并在scoreDisplay
元素中更新这个分数。 -
游戏结束提示:
当我们检测到蛇头与蛇身任何部分发生碰撞时,我们调用endGame
函数。这个函数会清除游戏循环,通过alert
消息弹窗显示出一个游戏结束的提示,并且将游戏重置。游戏重置会清空蛇的数组并将它的起始位置设置为初始位置。 -
移动速度控制:
变量speed
被用来控制蛇移动的速度。这个值表示游戏循环loop
函数被调用的时间间隔,也就是多少毫秒后执行下一次迭代。默认情况下,speed
设置为100
毫秒。这个值越小,蛇移动的速度就越快。 -
增加音效:
为了增加音效,你需要准备好一个简单的音效文件,比如 .wav 或 .mp3 格式的文件。然后,你可以在吃到食物的时候使用HTMLAudioElement
对象来播放这个音效。你还需要确保在 Web 浏览器中可以播放音效,这通常不是问题,但是在某些环境下可能需要额外的权限或处理。
代码中的 generateFood
函数稍微做了修改,以确保随机生成的食物位置不会落在蛇身上。这通过一个循环来完成,这个循环一直运行,直到找到一个蛇不存在的位置。
还有一点是,为了在 HTML
文件中显示分数,我们使用了 textContent
属性来更新 scoreDisplay
元素的内容。
这些基本功能的加入大大提升了游戏的可玩性和用户体验。通过以上步骤,你可以实现一个更加完善和有趣的小游戏。
第四步:添加音效
为了让游戏更有趣,我们可以在吃到食物时播放音效。请确保在项目目录中有一个名为eat.mp3
的音频文件。你可以从网上下载一个合适的音效文件。
第五步:其他功能添加建议
1. 多级别/难度模式
- 描述:添加多个难度级别,随着游戏进展,蛇的速度逐渐加快。
- 实现:设置不同的速度级别,并根据游戏时间或分数调整速度。
2. 墙壁或障碍物
- 描述:在游戏区域内随机生成墙壁或障碍物,增加游戏的挑战性。
- 实现:在画布上绘制静态障碍物,并在碰撞检测中考虑这些障碍物。
3. 更多种类的食物
- 描述:除了普通食物外,添加不同类型的食物,提供不同的分数或特殊效果(如加速、减速)。
- 实现:使用不同的颜色或图案表示不同类型的食物,并在生成食物时考虑随机性。
4. 音效和背景音乐
- 描述:为游戏添加音效,如吃到食物时的声音、游戏结束时的音效,以及背景音乐。
- 实现:使用
HTMLAudioElement
或第三方库来播放音效,并在合适的时机触发播放。
5. 游戏排行榜
- 描述:记录并显示玩家的历史高分或全局排行榜。
- 实现:使用浏览器的本地存储(
localStorage
)或后端服务器来保存和检索高分记录。
6. 自定义蛇的外观
- 描述:允许玩家选择或自定义蛇的颜色或样式。
- 实现:提供一个设置界面,让玩家选择或输入颜色,并在绘制蛇时应用这些设置。
7. 增强的控制方式
- 描述:除了键盘控制,还可以添加触摸屏或鼠标控制功能。
- 实现:使用触摸事件或鼠标事件来控制蛇的移动方向。
8. 暂停和重新开始功能
- 描述:允许玩家在游戏中暂停和重新开始。
- 实现:添加暂停按钮,并在暂停时停止游戏循环;重新开始时恢复游戏状态。
9. 游戏关卡系统
- 描述:通过完成一定的任务或达到一定的分数,解锁新关卡或新场景。
- 实现:定义不同的关卡和场景,并在游戏逻辑中处理关卡切换。
10. 游戏教程
- 描述:为新手玩家提供游戏操作和规则的教程。
- 实现:在游戏开始时显示教程或提示,指导玩家如何操作游戏。
11. 游戏主题和皮肤
- 描述:提供不同的游戏主题或皮肤,使游戏界面更加多样化。
- 实现:允许玩家选择或解锁不同的主题和皮肤,并在游戏中应用这些设置。
12. 社交分享功能
- 描述:允许玩家将他们的分数或游戏截图分享到社交媒体。
- 实现:集成社交分享 API 或使用浏览器的分享功能来实现这一点。
13. 挑战模式
- 描述:添加时间限制或其他挑战模式,玩家需要在规定时间内完成任务。
- 实现:设置倒计时器或任务目标,并在达到目标时给予奖励或结束游戏。
14. 动画效果
- 描述:在游戏中加入动画效果,如蛇的移动更加流畅,食物出现时有动画效果。
- 实现:使用动画框架或手动实现帧动画来提升游戏的视觉效果。
这些功能和改进可以根据你的兴趣和项目的需求逐步实现。通过不断添加新功能,你可以使游戏变得更加有趣和丰富,同时提升自己的编程技能和开发经验。
总结
通过这个教程,你学会了如何使用HTML、CSS和JavaScript构建一个简单的贪吃蛇游戏。这个项目不仅帮助你巩固了编程基础,还提供了很多可以扩展和改进的空间。例如,你可以尝试增加障碍物、设计关卡、添加不同种类的食物等。
希望你在这个项目中学到了新的知识,并且享受了编程的乐趣。如果有任何问题或建议,请随时在评论区留言!
相关文章:
创建一个简单的贪吃蛇游戏:HTML、CSS和JavaScript教程
在本教程中,我们将逐步构建一个简单的贪吃蛇游戏。这个项目适合初学者,可以帮助你理解HTML、CSS和JavaScript的基础知识,并掌握如何将它们结合起来创建一个完整的游戏。 准备工作 在开始之前,请确保你已经安装了一个代码编辑器&…...

全面讲解电子齿轮比与脉冲数计算
一、什么是编码器分辨率 编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。编码器把角位移或直线位移转换为电信号,按照读出方式编码器可以分为接触式和非接触式两种…...

音频进阶学习一——模拟信号和数字信号
文章目录 前言|版本声明:山河君,未经博主允许,禁止转载 一、什么是模拟信号和数字信号信号模拟信号数字信号数字和模拟信号的区别一览 二、信号处理系统总结 前言 所有软件的运行都得益于硬件上的突破,数字信号是从40年前就开始高…...

SpringBoot企业人事管理系统-附源码与配套论文
1.1引言 随着计算机技术的飞速发展,计算机在各种单位机构管理中应用的普及﹐管理信息系统的开发在强调管理、强调信息的现代社会中也显得越来越重要。因此,利用计算机高效率地完成人事管理的日常事务,是适应现代各种单位机构制度要求、推动各种单位机构…...

用window计算器实现定点数的十进制和二进制之间相互转换
目录 前言 已知十进制定点数,求二进制定点数 正数 整数部分 小数部分 负数 已知二进制定点数,求十进制定点数 正数 负数 前言 windows 10自带的计算器,具有程序员模式,可以方便的进行进制的转换,但是由于二进制模式下,无法输入十进制的小数,所以无法直接实现定…...

搬砖人2024年的智能工作伙伴 —— 4款思维导图软件种草集!
幕布思维导图这玩意儿特别厉害,成了很多学生学习的好帮手,在学习中经常觉得信息太多太乱,不好理清楚。这时候用幕布思维导图,我们可以把那些复杂的知识点整理得有条有理。每个主题、每个小点都清清楚楚,学习的时候一眼…...

【Python第三方库】Requests全面解析
文章目录 安装基本用法测试网站发送GET请求发送POST请求更多请求请求参数请求头其他常用请求属性处理响应响应状态码响应内容 处理超时处理异常 requests 是一个非常流行的 Python HTTP 库,用于发送所有类型的 HTTP 请求。它简洁易用,能够处理复杂的请求…...
基于CNN的医学X-Ray图像分类全程解析
数据集 我们所使用的数据集是胸部 X 光图像,它包含 2 个类别:肺炎和正常。该数据集由 Paulo Breviglieri 发布,是 Paul Mooney 最受欢迎数据集的修订版,此更新版本的数据集在验证集和测试集中的图像分布更加均衡。数据集分为 3 个文件夹(训练、测试、验证),包含肺炎和正…...

C++初学者指南-5.标准库(第二部分)--排序序列操作
C初学者指南-5.标准库(第二部分)–排序序列操作 文章目录 C初学者指南-5.标准库(第二部分)--排序序列操作二分查找binary_searchlower_boundupper_boundequal_rangeincludes 合并mergeinplace_merge 设置操作set_unionset_intersectionset_differenceset_symmetric_difference …...

matplotlib库学习之绘图透明度设置(精炼准确)
matplotlib库学习之透明颜色设置 一、简介 在数据可视化中,透明度设置可以使图表更具层次感,特别是在多层叠加图表时。matplotlib库提供了多种方法来设置图表各个部分的透明度,包括图形、文本、图例、坐标轴等部分。 二、为什么要设置成透明…...
select多路复用(tcp通信)
文章目录 项目名称项目结构 项目名称 io_demo1 项目结构 $ tree . ├── build ├── CMakeLists.txt ├── debug.gdb ├── include │ ├── mysocket.h │ ├── tcp_client.h │ └── tcp_server.h ├── sources │ └── server.cpp └── src├─…...

STM32IIC与SPI详解
单片机里的通信协议其实蛮多的,IIC;SPI;MQTT;CAN;包括串口也是一种通信协议。而串口通信虽然实现了全双工,但需要至少三根线,为了节省这一根线的成本,于是IIC诞生了。 目录 一.IIC…...

K8s第三节:k8s1.23.1升级为k8s1.30.0
上回书说到我们使用了kubeadm安装了k8s1.23.1,但是在k8s1.24之前还是使用docker作为容器运行时,所以这一节我打算将我安装的k8s集群升级为1.30.0版本; 1、修改containerd 配置 因为我们安装的docker自带containerd,所以我们不需要重新安装con…...
.gitignore不生效的解决方案
为什么会不生效 因为文件已经被git追踪(或者说被track 或者说被索引,都是一个意思)。 目前.gitignore面对已经被git追踪的文件是无法生效的。(这是现状,我们只能接收这个现状。不过个人觉得git官方可以对这方面进行优化调整,让其…...

脱胎于 S 语言的R语言,Ross Ihaka 和 Robert Gentleman 和社区的力量让 R 在学术界与研究机构放光彩
R语言从一门用于统计学教学的编程语言,发展成为全球数据科学领域的重要工具,离不开其强大的功能、丰富的社区资源和开源精神。这些都离不开Ross Ihaka 和 Robert Gentleman 和 社区的力量。 在1990年代初,新西兰奥克兰大学的统计学教授Ross I…...

JavaEE 第6节 内存可见性问题以及解决方法
目录 一、什么是内存可见性问题? 1、问题代码演示 2、基础知识铺垫 1)硬件层面 2)模型层面(JMM) 二、内存可见性问题的原因 三、volatile解决内存可见性问题 一、什么是内存可见性问题? 1、问题代码…...
es基本操作
以下是一些 Elasticsearch 常用的命令,涵盖了索引管理、数据操作和集群管理等方面: 基本操作 检查集群状态: curl -X GET "localhost:9200/_cluster/health?pretty"查看集群健康状态和基本信息。 查看所有索引: curl…...

开源 AI 智能名片 S2B2C 商城小程序赋能下的社区团购商业模式研究
摘要:本文深入探讨了社区团购商业模式的本质、特点及其优势,并详细分析了开源 AI 智能名片 S2B2C 商城小程序在社区团购中的应用与价值。通过对相关案例的研究和数据的分析,揭示了这一创新组合对社区商业生态的重要影响,为未来社区…...
AutoSar AP软件规范中CM介绍及功能概要
1. 前言 为了理解AutoSar AP中EM的概念,生搬硬套的翻译了《 AUTOSAR SWS CommunicationManagement.pdf》的介绍部分,并按照自己的理解进行了修改。如下 2. AUTOSAR_SWS_CommunicationManagement.pdf的介绍部分 本文件包含AUTOSAR AP通信管理的功能、A…...
【图形学】TA之路-向量
向量 向量 是一个有大小和方向的数学对象。在三维空间中,向量通常表示为 (v_x, v_y, v_z)。 基本操作 加法: a b (a_x b_x, a_y b_y, a_z b_z)减法: a - b (a_x - b_x, a_y - b_y, a_z - b_z)标量乘法: k * v (k * v_x, …...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...

windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...