【前端】使用 Canvas 实现贪吃蛇小游戏

使用 Canvas 实现贪吃蛇小游戏

在这篇博客中,我们将介绍如何使用 HTML5 Canvas 和 JavaScript 实现一个简单的贪吃蛇(Snake)小游戏。这个项目是一个基础的游戏开发练习,它可以帮助你理解如何在 Canvas 上绘图、如何处理用户输入以及如何管理游戏状态。
在这里插入图片描述

项目结构

在开始之前,确保你的项目文件结构如下:

  • index.html
  • index.css
  • index.js

HTML 部分

首先,我们在 index.html 中定义 Canvas 和一个重新开始按钮。

<!DOCTYPE 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="index.css">
</head>
<body><canvas id="gameCanvas" width="400" height="400"></canvas><button id="restartButton" style="display: none;" onclick="restartGame()">重新开始</button><script src="index.js"></script>
</body>
</html>

CSS 部分

index.css 中,我们可以设置 Canvas 和按钮的样式。

/* styles.css */
body {display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100vh;margin: 0;background-color: #f0f0f0;
}canvas {border: 1px solid #000;background-color: #fff;
}button {display: none;margin-top: 20px;padding: 10px 20px;font-size: 16px;cursor: pointer;position: absolute;
}

JavaScript 部分

接下来,我们在 script.js 中编写游戏的主要逻辑。

1. 初始化 Canvas 和变量

我们首先获取 Canvas 元素及其上下文,并定义游戏所需的一些变量。

const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const restartButton = document.getElementById("restartButton");const gridSize = 20; // 格子大小
const rows = canvas.height / gridSize;
const cols = canvas.width / gridSize;

2. 初始化游戏

创建 initGame 函数来初始化游戏状态:

function initGame() {snake = [{ x: cols / 2, y: rows / 2 }, { x: cols / 2 + 1, y: rows / 2 }];food = {x: Math.floor(Math.random() * cols),y: Math.floor(Math.random() * rows),};direction = { x: 1, y: 0 };lastDirection = { x: 1, y: 0 };gameOver = false;restartButton.style.display = "none";gameLoop();
}

3. 绘制游戏元素

我们需要两个函数来绘制蛇和食物:

function drawCell(x, y, color) {ctx.fillStyle = color;ctx.fillRect(x * gridSize, y * gridSize, gridSize, gridSize);ctx.strokeStyle = "#000";ctx.lineWidth = 2; // 可以根据需要调整ctx.strokeRect(x * gridSize, y * gridSize, gridSize, gridSize);
}function drawSnake() {snake.forEach((part) => drawCell(part.x, part.y, "#409EFF"));
}function drawFood() {drawCell(food.x, food.y, "#E6A23C");
}

4. 更新蛇的位置

创建 updateSnake 函数来更新蛇的位置,并检查它是否吃到食物或撞到墙及自身:

function updateSnake() {const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };if (head.x === food.x && head.y === food.y) {food = {x: Math.floor(Math.random() * cols),y: Math.floor(Math.random() * rows),};} else {snake.pop();}snake.unshift(head);// 撞墙或撞到自己if (head.x < 0 ||head.x >= cols ||head.y < 0 ||head.y >= rows ||snake.slice(1).some((part) => part.x === head.x && part.y === head.y)) {gameOver = true;}lastDirection = direction;
}

5. 游戏循环

创建 gameLoop 函数来处理游戏的绘制和更新:

function gameLoop() {if (!gameOver) {ctx.clearRect(0, 0, canvas.width, canvas.height);drawFood();updateSnake();drawSnake();setTimeout(gameLoop, 100);} else {ctx.font = "100px Arial";ctx.fillStyle = "#F56C6C";ctx.fillText("Game Over", canvas.width / 4, canvas.height / 2);restartButton.style.display = "block"; // 显示重新开始按钮}
}

6. 处理用户输入

添加键盘事件监听来控制蛇的移动方向:

window.addEventListener("keydown", (event) => {switch (event.key) {case "ArrowUp":if (lastDirection.y === 0) direction = { x: 0, y: -1 };break;case "ArrowDown":if (lastDirection.y === 0) direction = { x: 0, y: 1 };break;case "ArrowLeft":if (lastDirection.x === 0) direction = { x: -1, y: 0 };break;case "ArrowRight":if (lastDirection.x === 0) direction = { x: 1, y: 0 };break;}
});

7. 重新开始游戏

最后,创建一个函数用于重新启动游戏:

function restartGame() {initGame();  // 重新启动游戏
}initGame();  // 启动游戏

总结

通过这篇博客,你学习了如何使用 HTML5 Canvas 和 JavaScript 来实现一个简单的贪吃蛇小游戏。我们展示了如何绘制游戏元素,处理用户输入,并管理游戏状态。希望这个项目能帮助你对游戏开发有更深入的理解,并激发你进行更多有趣的项目开发!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/13535.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Laravel(Lumen8) + Supervisor 实现多进程redis消息队列

相关文章:Supervisor守护进程工具安装与使用 1、通用消息队列 /App/Job/CommonJob.php: <?phpnamespace App\Jobs; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str;class CommonJob extends Job {public $timeout; //超时时间protected $data; //队列…

Android:OkHttp网络请求框架的使用

目录 一&#xff0c;OkHttp简介 二&#xff0c;OkHttp请求处理流程 三&#xff0c;OkHttp环境配置 四&#xff0c;OkHttp的使用 1.get网络请求 2.post上传表单数据 3.post上传json格式数据 4.文件上传 5.文件下载 一&#xff0c;OkHttp简介 OkHttp是square公司推出的一…

npm 源管理工具 nrm

npm 源管理工具 nrm 安装(可能很慢, 多试几次) npm install -g nrm查看可选择源列表 nrm ls切换源 nrm use <registry>如: nrm use taobao

rust的版本问题,安装问题,下载问题

rust的版本、安装、下载问题 rust版本问题&#xff0c; 在使用rust的时候&#xff0c;应用rust的包&#xff0c;有时候包的使用和rust版本有关系。 error: failed to run custom build command for pear_codegen v0.1.2 Caused by: process didnt exit successfully: D:\rus…

鸿蒙全面开发指南:入门、生态安全与资源支持

鸿蒙全面开发指南&#xff1a;入门、生态安全与资源支持 本文全面梳理了鸿蒙操作系统的开发入门流程&#xff0c;涵盖了开发环境准备、工具使用、项目创建、模拟器配置到应用安全设计的各个方面。通过本文&#xff0c;读者不仅能够了解鸿蒙开发的基本步骤&#xff0c;也能深入理…

Aspose.PDF功能演示:在 JavaScript 中将 TXT 转换为 PDF

您是否正在寻找一种在 JavaScript 项目中将纯文本文件从TXT无缝转换为PDF格式的方法&#xff1f;您来对地方了&#xff01;无论您是要构建 Web 应用程序、创建生产力工具&#xff0c;还是只是希望简化工作流程&#xff0c;直接从 JavaScript 代码中将 TXT 转换为 PDF 的功能都可…

第3天 Web源码拓展_小迪网络安全笔记

1.关于web源码目录结构 #数据库配置文件 后台目录 模板目录 数据库目录 1.1数据库配置文件: 1.1就拿wordpress来说,先到官网下载源码:Download – WordPress.org,解压源码之后: 2.2找到目录下名为 wp-config-sample.php的文件,这就是数据库配置文件: 设想: 我们在渗透…

FOURIER NEURAL OPERATOR FOR PARAMETRIC PARTIAL DIFFERENTIAL EQUATIONS

参数偏微分方程的傅里叶神经算子 论文链接&#xff1a;https://arxiv.org/abs/2010.08895 项目链接&#xff1a;https://github.com/neuraloperator/neuraloperator 作者博客&#xff1a;https://zongyi-li.github.io/blog/2020/fourier-pde/ 参数偏微分方程的傅里叶神经算子…

本地部署Terraria泰拉瑞亚私服并通过内网穿透生成公网地址远程联机

文章目录 前言1. 下载Terraria私服2. 本地运行Terraria 私服3. 本地Terraria私服连接4. Windwos安装Cpolar 工具5. 配置Terraria远程联机地址6. Terraria私服远程联机7. 固定远程联机地址8. 固定的联机地址测试 前言 本文将为你详细介绍在本地如何运行泰拉瑞亚本地私服和结合C…

认识 React Hooks

回顾函数组件 函数组件 没有组件实例 不能监听各个生命周期 无法扩展属性和方法 没有 state 和 setState 只是输入 props &#xff0c;输出 jsx &#xff0c;纯函数。 // class 组件class List extends React.Component {constructor(props) {super(props)}render() {con…

信息泄露--注意点点

目录 明确目标: 信息泄露: 版本软件 敏感文件 配置错误 url基于文件: url基于路由: 状态码: http头信息泄露 报错信息泄露 页面信息泄露 robots.txt敏感信息泄露 .get文件泄露 --判断: 搜索引擎收录泄露 BP: 爆破: 明确目标: 失能 读取 写入 执行 信息泄…

【文末附gpt升级方案】Ilya离开OpenAI内幕探究:算力削减与商业优先策略的冲突

Ilya离开OpenAI内幕探究&#xff1a;算力削减与商业优先策略的冲突 一、引言 在人工智能&#xff08;AI&#xff09;领域的飞速发展中&#xff0c;OpenAI一直以其领先的技术和创新产品而备受瞩目。然而&#xff0c;近日发生的Ilya Sutskever离开OpenAI的事件却引起了业界的广…

java企业级云MES系统全套源码,支持app、小程序、H5、台后管理

企业级云MES全套源码&#xff0c;支持app、小程序、H5、台后管理端 企业级智能制造MES系统源码&#xff0c;技术架构&#xff1a;springboot vue-element-plus-admin MES指的是制造企业生产过程执行系统&#xff0c;是一套面向制造企业车间执行层的生产信息化管理系统。MES可以…

栈(基于动态顺序表实现的栈)

栈的简单介绍 关于栈的性质咳咳 栈&#xff1a;栈是一种特殊的线性表,其中只让在一端插入和删除元素。 后进先出 进行插入删除的那一端叫栈顶&#xff0c;另一端叫栈底 我们实现的栈是基于一个动态顺序表的的栈&#xff0c;会实现栈的 入栈&#xff0c;出栈&#xff0c;获取…

修改默认时区,默认语言,默认国家

确认时区&#xff0c;语言&#xff0c;国家 build/make/target/product/languages_default.mkframeworks/base/packages/SettingsLib/res/xml/timezones.xml设备mk中添加相关内容 PRODUCT_PROPERTY_OVERRIDES \persist.sys.timezoneEurope/AmsterdamPRODUCT_PROPERTY_OVERRI…

嵌入式学习——3——超时timeout

1、自带超时参数的函数 select自带超时 定义超时时间变量 struct timeval tv {5, 0}; while(1) { tv.tv_sec 5; tv.tv_usec 0; int res select(1, &readfds, NULL, NULL, &tv); ..... } poll自带超时 1、poll函数的第三个参数&#xff0c;是以毫秒为单位的超时时间…

前端vue用el-table如何实现表头内容过长换行处理,实现换行效果

前端vue用el-table如何实现表头内容过长换行处理&#xff0c;实现换行效果 这是效果图 有两种方法&#xff0c;一种简易版本&#xff0c;一种万能方法,都是el-table&#xff0c;先看文档 表头标题是可以自定义的 方法一 label的解释写在代码里面了&#xff0c;这里会自动形成换…

Python概述

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 了解Python Python&#xff0c;本义是指“蟒蛇”。1989年&#xff0c;荷兰人Guido van Rossum发明了一种面向对象的解释型高级编程语言&#xff0c;…

利用神经网络学习语言(六)——总结与常见面试问题

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 文章列表&#xff1a; 利用神经网络学习语言&#xff08;一&#xff09;——自然语言处理的基本要素利用神经网络学习语言&…

Java基础入门day49

day49 tomcat 启动 进入tomcat的bin目录&#xff0c;双击或者运行startup.bat文件启动tomcat 控制台最后出现服务器启动在多少毫米之内&#xff0c;代表服务器成功启动 org.apache.catalina.startup.Catalina.start Server startup in 405 ms 验证tomcat 在浏览器中输入 loca…