使用canvas实现js原生贪吃蛇
先看效果图:
游戏要求:
1.方向键可以控制蛇头的运动方向。
2.食物随机出现在画布中。
3.蛇身跟随蛇头运动。
4.蛇头不能撞墙或撞到蛇身。
5.蛇吃了食物后蛇身增长。
细节注意事项:
其实贪吃蛇游戏有几个细节需要注意:
1.当蛇向上时向下键无效,同理当蛇向左时向右键无效等等。
2.蛇身的每一次移动相对前一段有延后性。
3.当蛇身长度小于等于三个时是无论如何也不会装上自己的。(可以减少一些计算量)
实现思路:
一,准备画布和按钮(主要逻辑不在此,所以不需要深入)
css用到了flex布局,在此不再展示
<div class="contain"><canvas width="360" height="360" id="canvas"></canvas><div class="direction"><div class="up" onclick="toUp()">上</div><div class="down" onclick="toDown()">下</div><div class="left" onclick="toLeft()">左</div><div class="right" onclick="toRight()">右</div></div></div>
还有一些初始化内容
const canvas = document.querySelector("#canvas")const ctx = canvas.getContext("2d")const w = 360//画布宽const h = 360//画布高const per_length = 40
二,准备两个类和两个数组:
1.蛇的类
//蛇的类class ball {/*** @description: * @param {*} x:圆心x轴坐标* @param {*} y:圆心y轴坐标* @param {*} color:颜色* @return {*}*/constructor(x, y, color) {this.dijige = she_body.lengththis.x = x || 20this.y = y || 20this.r = 20this.color = color || "#" + parseInt(Math.random() * 0xffffff).toString(16)this.xspeed = per_lengththis.yspeed = 0}/*** @description: 蛇的运动* @param {string} direct:方向* @return {*}*/move(direct) {//控制运动she_position[0].x = this.xshe_position[0].y = this.yswitch (direct) {case "x":this.x += this.xspeedcontrolMove()break;case "y":this.y += this.yspeedcontrolMove()break;}}make() {//根据每个实例制造蛇头或蛇身ctx.beginPath()ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2)ctx.fillStyle = this.colorctx.fill()}check() {//边境检测if (this.x < this.r || w - this.x < this.r) {clearInterval(timer)return false}if (this.y < this.r || h - this.y < this.r) {clearInterval(timer)return false}return true}isEatFood() {//是否吃到了食物if (Math.abs(food.x - this.x + 20) <= this.r && Math.abs(food.y - this.y + 20) <= this.r) {food = new Food()she_body.push(new ball(she_position[she_position.length - 1].x, she_position[she_position.length - 1].y, "red"))she_position.push({ x: she_position[she_position.length - 1].x, y: she_position[she_position.length - 1].y })console.log("吃到了");}}}
2.食物的类
//食物的类class Food {constructor() {this.x = Math.floor(Math.random() * 9) * 40 //[1,10)this.y = Math.floor(Math.random() * 9) * 40 //[1,10)this.widthRect = per_lengththis.heigthRect = per_lengththis.color = "#" + parseInt(Math.random() * 0xffffff).toString(16)}make() {ctx.beginPath()ctx.fillStyle = this.colorctx.fillRect(this.x, this.y, this.widthRect, this.heigthRect)}}
3.存放蛇身的数组(注意,不包括蛇头哈)
const she_body = []//蛇身
4.记录蛇身每一段在未来一个单位时间运动的坐标
该数组是为了实现蛇身跟随运动,例如:到了某一位置会依次转弯
const she_position = [{ x: 20, y: 20 }]//蛇头走过的坐标
数组中有一个原始数据,这是蛇头最初的位置;数组的长度对应蛇身的长度。
例如:数组中第一个数据对应蛇头前一时间单位的位置。
该数组的数据是在不断更新的,每一项对应下一步的位置
判断游戏是否结束:
1.撞墙
这里使用边界检测:放到了蛇的类中
check() {//边境检测if (this.x < this.r || w - this.x < this.r) {clearInterval(timer)return false}if (this.y < this.r || h - this.y < this.r) {clearInterval(timer)return false}return true}
2.撞到自己
这个思路很简单,没走一步遍历蛇身数组(she_body),是否与蛇头相撞。
注意当蛇身的长度<=3无需判断,因为永远不会相撞
控制蛇头的转向
其实可以继续封装一下,但是这个游戏已经花了我一整天时间了,是在是懒了。
function toDown() {//下if (she.check() && she.yspeed === 0) {direct = "y"she.xspeed = 0she.yspeed = per_length}}function toRight() {//右if (she.check() && she.xspeed === 0) {direct = "x"she.yspeed = 0she.xspeed = per_length}}function toLeft() {//左if (she.check() && she.xspeed === 0) {direct = "x"she.yspeed = 0she.xspeed = -per_length}}function toUp() {//上if (she.check() && she.yspeed === 0) {direct = "y"she.xspeed = 0she.yspeed = -per_length}}
源码展示:
啊~哈哈哈哈哈~鸡汤来喽
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.contain {width: 100vw;display: flex;flex-direction: column;justify-content: center;align-items: center;}#canvas {display: block;border: 2px solid black;}.contain>.direction {width: 200px;height: 200px;position: relative;}.up,.down,.left,.right {width: 60px;height: 60px;background-color: rgb(245, 183, 103);position: absolute;cursor: pointer;text-align: center;line-height: 60px;}.contain>.direction>.up {top: 0;left: 50%;transform: translateX(-50%);}.contain>.direction>.down {bottom: 0;left: 50%;transform: translateX(-50%);}.contain>.direction>.left {top: 50%;left: 0;transform: translateY(-50%);}.contain>.direction>.right {top: 50%;right: 0;transform: translateY(-50%);}</style>
</head><body><div class="contain"><canvas width="360" height="360" id="canvas"></canvas><div class="direction"><div class="up" onclick="toUp()">上</div><div class="down" onclick="toDown()">下</div><div class="left" onclick="toLeft()">左</div><div class="right" onclick="toRight()">右</div></div></div><script type="text/javascript">const canvas = document.querySelector("#canvas")const ctx = canvas.getContext("2d")const w = 360//画布宽const h = 360//画布高const per_length = 40const she_body = []//蛇身const she_position = [{ x: 20, y: 20 }]//蛇头走过的坐标function controlMove() {//move函数的公共部分if (she.check()) {ctx.clearRect(0, 0, w, h)} else {alert("撞墙了")}she.isEatFood()food.make()she.make()she_body.forEach((item, index) => {she_position[index + 1].x = item.xshe_position[index + 1].y = item.yitem.x = she_position[index].xitem.y = she_position[index].yitem.make()})}//蛇的类class ball {/*** @description: * @param {*} x:圆心x轴坐标* @param {*} y:圆心y轴坐标* @param {*} color:颜色* @return {*}*/constructor(x, y, color) {this.dijige = she_body.lengththis.x = x || 20this.y = y || 20this.r = 20this.color = color || "#" + parseInt(Math.random() * 0xffffff).toString(16)this.xspeed = per_lengththis.yspeed = 0}/*** @description: 蛇的运动* @param {string} direct:方向* @return {*}*/move(direct) {//控制运动she_position[0].x = this.xshe_position[0].y = this.yswitch (direct) {case "x":this.x += this.xspeedcontrolMove()break;case "y":this.y += this.yspeedcontrolMove()break;}}make() {//根据每个实例制造蛇头或蛇身ctx.beginPath()ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2)ctx.fillStyle = this.colorctx.fill()}check() {//边境检测if (this.x < this.r || w - this.x < this.r) {clearInterval(timer)return false}if (this.y < this.r || h - this.y < this.r) {clearInterval(timer)return false}return true}isEatFood() {//是否吃到了食物if (Math.abs(food.x - this.x + 20) <= this.r && Math.abs(food.y - this.y + 20) <= this.r) {food = new Food()she_body.push(new ball(she_position[she_position.length - 1].x, she_position[she_position.length - 1].y, "red"))she_position.push({ x: she_position[she_position.length - 1].x, y: she_position[she_position.length - 1].y })console.log("吃到了");}}}//食物的类class Food {constructor() {this.x = Math.floor(Math.random() * 9) * 40 //[1,10)this.y = Math.floor(Math.random() * 9) * 40 //[1,10)this.widthRect = per_lengththis.heigthRect = per_lengththis.color = "#" + parseInt(Math.random() * 0xffffff).toString(16)}make() {ctx.beginPath()ctx.fillStyle = this.colorctx.fillRect(this.x, this.y, this.widthRect, this.heigthRect)}}let she = new ball()let food = new Food()she.make()let direct = "x"//定时器const timer = setInterval(() => {she.move(direct)}, 300);function toDown() {//下if (she.check() && she.yspeed === 0) {direct = "y"she.xspeed = 0she.yspeed = per_length}}function toRight() {//右if (she.check() && she.xspeed === 0) {direct = "x"she.yspeed = 0she.xspeed = per_length}}function toLeft() {//左if (she.check() && she.xspeed === 0) {direct = "x"she.yspeed = 0she.xspeed = -per_length}}function toUp() {//上if (she.check() && she.yspeed === 0) {direct = "y"she.xspeed = 0she.yspeed = -per_length}}</script>
</body></html>
使用canvas实现js原生贪吃蛇相关推荐
- 好玩的小游戏系列 (一)基于html+js 原生贪吃蛇
一朵花如果只被用来观赏那只呈现出它的外在意义只是它生命的一部分若是不能够将其内在更实质的美发挥出来充其量也不过就是一朵死的花而已. 目录 一.前言 二.代码介绍 三.效果显示 四.编码实现 index ...
- eclipse javascript_原生js实现贪吃蛇游戏_javascript技巧
更新时间:2020年10月26日 11:46:36 作者:leisure-ZL 这篇文章主要为大家详细介绍了原生js实现贪吃蛇小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴 ...
- 前端那些事之原生 js实现贪吃蛇篇
2019独角兽企业重金招聘Python工程师标准>>> 原生js实现贪吃蛇 <!DOCTYPE html> <html lang="en"> ...
- 原生JS实现贪吃蛇游戏
原生JS实现贪吃蛇游戏 贪吃蛇游戏(原生JavaScript) 贪吃蛇游戏思路分析 游戏思想: 面向对象的思想 三个js文件分别代表三个对象 三个对象相互独立,在HTML中控制全局 使用面向对象思想的 ...
- 利用HTML5 canvas元素+原生JS编写贪吃蛇
我们先来看一个最简单的例子 利用canvas动画编写贪吃蛇:https://clacier.github.io/tcs/ 一.什么是canvas? canvas是HTML5中新增加的一个元素,专门用于 ...
- 原生JS实现贪吃蛇——项目总结
项目准备 项目展示图 建立新文件夹,新建出images CSS JS 三个文件夹,并在根目录下创建出index.html 将下列素材图片转到images文件中 接下来可以开始着手操作了 HTML结构 ...
- 使用前端原生 js,贪吃蛇小游戏
好久好久,真的是好久好久没来写过了,因为最近有点小忙.不过即使是忙,也也还是写了两个小游戏,其中一个就是这个,贪吃蛇啦. 算是一个小练手了,这个是在有点太简单了,只是第一次写这种小游戏,还是零零星星花 ...
- js练习--贪吃蛇(转)
最近一直在看javascript,但是发现不了动力.就开始想找动力,于是在网上找到了一个用js写的贪吃蛇游戏.奈何还不会用git,就只能先这样保存着.哈哈哈,这也算第一篇博客了,以后会坚持用自己的代码 ...
- 用JS实现贪吃蛇小游戏
疫情期间呆在家里无聊,于是深入学习了一下JS.自己也模仿写一个贪吃蛇的小游戏,本人刚接触JS不久如有错误,望评论区指出. 因为一般贪吃蛇游戏中的CSS样式较为简单,所以这里主要讲一下JS的写法. 食物 ...
最新文章
- 2019牛客暑期多校训练营(第三场)
- 模糊匹配 读音_onenote搜索机制详解②:两种搜索模式,模糊与精确匹配
- OPPO和微软合作,开放“召唤小冰”
- 每秒处理请求数和并发的关系
- Spring MVC Converter(类型转换器)详解
- mui 页面滚动解决方案
- Helm 3 完整教程(十九):Helm 流控制结构(3)range 语句
- vue使用vue-video-player插件播放视频
- 精密电阻选购及换算方法
- 高数 | 旋转体体积计算方法汇总、二重积分计算旋转体体积
- 阿里P7级别面试经验总结,面试心得体会
- CodeForces - 1169D : Neko Performs Cat Furrier Transform(思维)
- http://dongxicheng.org/
- [软件补丁]VS6 sp6补丁下载
- 基于RGB-D数据的语义建图
- Tekton系列之实践篇-使用Tekton Trigger让Tekton使用更简单
- 论马加爵也为GDP发展作出了贡献
- php监听网卡数据,VnStat PHP:用于监控网络带宽使用的基于Web的界面
- mysql下载教程(如何从官方网站下载)
- CentOS7系统下将多个磁盘合并到根目录
热门文章
- [武术书籍]醒思录:李小龙的生活智慧(李小龙经典原著书系)
- 国家绿色数据中心名单(第一批)
- 于殿泓 图像检测与处理技术_图像检测与处理技术(21世纪高等学校仪器仪表及自动化类专业规划教材)...
- 浅谈亚马逊测评,及四大测评干货!
- element plus+vue3.0 el-date-picker之panel-change无效果,为el-date-picker加标识。
- GBASE核心业务系统解决方案入围工信部“2022年信息技术应用创新典型解决方案”
- Ubuntu 与Windows共享文件夹的操作
- [ICLR19] ORDERED NEURONS: INTEGRATING TREE STRUCTURES INTO RECURRENT NEURAL NETWORKS
- MATLAB笔记4:特殊矩阵 zeros、ones、eye、rand、randn;magic、vander、hilb、pascal
- 出道的第八年,依然AI着......