JavaScript写个贪吃蛇小游戏(超详细)


Posted in Javascript onMarch 17, 2020

贪吃蛇大家都玩过,但你会制作嘛?听起来好像很难的样子,其实非常的简单,话不多说直接上代码

我们先把dom结构写出来

<div id="content">
      <div id="snake">
          <div class="box head"></div>
          <div class="box"></div>

      </div>
  
    </div>

其中,content为整个布局的大盒子,snake就是蛇,里面的box就是他的身体,为了区分头部我们给第一个box加了个head名字用于区分,下面我们再把css加上

<style>
    .box{
      width: 60px;
      height: 60px;
      background-color: red;
      position:absolute;
      left: 0;
      top: 0;
      line-height: 60px;
    }
    .head{
      background-color: yellowgreen;
    }
  </style>

我们给蛇的每一节的宽高设置为60像素,并给了一个定位,因为如果不加定位的话无法让他脱离文档流(在页面中飘起来),而且后续也无法通过left和top来判断他的坐标.

JavaScript写个贪吃蛇小游戏(超详细)

好的这样我们就得到了一条可爱的小蛇(然鹅并没有看出来哪里可爱- -)。什么?你问我他的头哪去了,很简单,在给元素加了定位以后后面的元素会覆盖掉前面的元素,所以只是头部和身体重叠了你看不到而已。
随后咱们得让这条蛇动起来是吧,那么我们怎么让他动起来呢?原理很简单,我们可以设置一个定时器,每过一个时间就让他动一下,而怎么让他动呢,只需要设置一个数值,让这个值每动一下就+=60,然后通过判断是上下动还是左右动,来给元素的left与top赋值。我们把逻辑写成代码,就出来了如下的代码

<script>
    var boxs = document.querySelectorAll(".box");
    var snake_x = 0;
    var snake_y = 0;
    var turn  = "right";
    setInterval(function(){
      snakeMove();
    },100)
    function snakeMove(){ 
      switch( turn ){
        case "right": snake_x += 60;break;
        case "left" : snake_x -= 60;break;
        case "top"  : snake_y -= 60;break;
        case "bottom": snake_y += 60;break;
      }

      for(var i = boxs.length - 1; i > 0 ; i --){
        boxs[i].style.left = boxs[i - 1].style.left;
        boxs[i].style.top = boxs[i - 1].style.top;
        
      }
      boxs[i].style.left = snake_x + "px";
      boxs[i].style.top = snake_y + "px";

    }
document.onkeydown = function(evt){
      var e = evt || event;
      var keyCode = e.keyCode || e.which;
      switch( keyCode ){
        case 37 : turn = "left";break;
        case 38 : turn = "top";break;
        case 39 : turn = "right";break;
        case 40 : turn = "bottom";break;
      }
    }

</script>

上述代码中,我们给小蛇的初始位置的x和y的坐标都设置为0,并且默认初始向右走,通过键盘上方向键的输入,来改变他的方向。其中,难点在于

for(var i = boxs.length - 1; i > 0 ; i --){
        boxs[i].style.left = boxs[i - 1].style.left;
        boxs[i].style.top = boxs[i - 1].style.top;
        
      }
      boxs[i].style.left = snake_x + "px";
      boxs[i].style.top = snake_y + "px";

这一块代码,这块代码的目的是让后面的元素跟着前面的走,也就是让蛇的每一块身体都跟着上一块去运动,然后最后再给头部设置为snake_x和snake_y当前的值即可,这样就形成了第一块(头部)坐标为
snake_x,snake_y实时变化的值,第二块为第一块之前的值,第三块为第二块之前的值。。。以此类推就得到了一个身体跟着头部走的效果

JavaScript写个贪吃蛇小游戏(超详细)

但是当你把代码输进去以后一运行会发现,这条小蛇过于顽皮,以至于走到边界以后还会无限的向前走,那这不行啊,总不能让蛇跑了不是,所以得给小蛇加上一个边界

var snake_x_max = document.documentElement.clientWidth ;
    var snake_y_max = document.documentElement.clientHeight;
if(snake_x > snake_x_max){
        snake_x = 0;
      }
      if(snake_x < 0){
        snake_x = snake_x_max;
      }
      if(snake_y > snake_y_max){
        snake_y = 0;
      }
      if(snake_y < 0){
        snake_y = snake_y_max;
      }

这里我们设置x和y的最大值为当前窗口的宽高,然后通过if语句进行判断,如果当前坐标大于了最大值,就讲当前坐标归0,如果小于0的话(也就是跑到了左边的边界),就将当前坐标设置为最大值,这样就可以得到一个边界啦

JavaScript写个贪吃蛇小游戏(超详细)

你以为这样就完事啦?nonono,没有食物吃的蛇怎么能叫做贪吃蛇呢,那是没有灵魂哒。下面我们开始制作食物(不能让蛇饿着是吧)。

<div id="food">
  
      </div>

然后给他加个css

#food{
    width: 60px;
    height: 60px;
    position: absolute;
    background: greenyellow;
  }

然后再绑定一下元素并将他的left和top值设为范围内随机数,这样可以做到随机位置生成

var fd=document.getElementById("food");
    fd.style.left=Math.random()*snake_x_max+"px";
    fd.style.top=Math.random()*snake_y_max+"px";

好的这样我们就得到了一个随机生成的食物

JavaScript写个贪吃蛇小游戏(超详细)

不过我们的小蛇好像对食物并没有什么兴趣呢,路过以后并不会吃掉,所以我们得给他加一个碰撞检测吧,碰撞检测的逻辑很简单,只需要让食物的left值与头部的left值相减的绝对值<=食物的大小,并且食物的top值与头部的top值相减的绝对值<=食物的大小,设置小于等于是因为如果直接用相等来判断的话,必须两个元素完全重合才行,我们需要的是碰到边缘就算迟到,所以用两个数值相减小于等于来做。然后判断当头部与食物发生碰撞时,将蛇的身体部分克隆一块出来放到蛇的身体里面,并让食物的位置重新刷新(适用克隆为偷懒方法,此偷懒方法仅适用于当小蛇开局自带一个身体的时候,如果小蛇开局不自带身体的话,我们无法克隆已有身体,只能通过createElement去新创建一个身体块出来并添加className后再添加到父元素中去才行)。下面我们把逻辑转换为代码

var dl=snake_x;
    var dt=snake_y;
    var fl=fd.style.left;
    var ft=fd.style.top;
    var dv=document.querySelectorAll("#snake div");
    var sk=document.getElementById("snake");
    var a2=Number(fl.substring(0,fl.indexOf("px")));
    var b2=Number(ft.substring(0,ft.indexOf("px")));
    if(Math.abs(dl-a2)<=60&&Math.abs(dt-b2)<=60){
       fd.style.left=Math.random()*1000+"px";
       fd.style.top=Math.random()*800+"px";
       sk.appendChild(dv[1].cloneNode());
       boxs = document.querySelectorAll(".box");
    }

其中那一大长串的substring的方法是因为获取到的left与top的值的格式是例如”200px”这样的数组,无法进行数学运算,所以要把px给截掉,并将剩下的字符串”200”转换成number类型才可以进行数学运算。

JavaScript写个贪吃蛇小游戏(超详细)

这样一个简单的贪吃蛇就做好啦~
啥?你问我什么什么类似碰到自己会死这样更多的规则机制咋没写,肯定是因为我懒啊!我连createElement都懒得用直接克隆一个出来了,咋会勤快到把剩下这么多的机制补全呢哈哈。基础机制我已经写出来了,各种奇奇怪怪的机制还是留给小伙伴们自由发挥吧~
PS:大家完全可以把头部的背景图片改成你小伙伴的照片,再把食物改成一些你想让ta吃的东西,可以拿来恶搞啊哈哈哈

到此这篇关于JavaScript写个贪吃蛇小游戏(超详细)的文章就介绍到这了,更多相关js 贪吃蛇内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Domino中运用jQuery读取视图内容的方法
Oct 21 Javascript
IE6下出现JavaScript未结束的字符串常量错误的解决方法
Nov 21 Javascript
jQuery实现点击文本框弹出热门标签的提示效果
Nov 17 Javascript
JavaScript中的操作符==与===介绍
Dec 31 Javascript
基于javascript实现窗口抖动效果
Jan 03 Javascript
Javascript实现图片懒加载插件的方法
Oct 20 Javascript
移动端手指放大缩小插件与js源码
May 22 Javascript
vue多种弹框的弹出形式的示例代码
Sep 18 Javascript
vue中的watch监听数据变化及watch中各属性的详解
Sep 11 Javascript
vue实现多个元素或多个组件之间动画效果
Sep 25 Javascript
ES6 Iterator接口和for...of循环用法分析
Jul 31 Javascript
js实现的在本地预览图片功能示例
Nov 09 Javascript
JS+CSS+HTML实现“代码雨”类似黑客帝国文字下落效果
Mar 17 #Javascript
js实现简单点赞操作
Mar 17 #Javascript
vue+ESLint 配置保存 自动格式化代码
Mar 17 #Javascript
HTML+JS实现“代码雨”效果源码(黑客帝国文字下落效果)
Mar 17 #Javascript
JavaScript实现横版菜单栏
Mar 17 #Javascript
JavaScript实现留言板案例
Mar 17 #Javascript
es6函数之严格模式用法实例分析
Mar 17 #Javascript
You might like
PHP类的静态(static)方法和静态(static)变量使用介绍
2012/02/19 PHP
php判断linux下程序问题实例
2015/07/09 PHP
Laravel框架Auth用户认证操作实例分析
2019/09/29 PHP
js一般方法改写成面向对象方法的无限级折叠菜单示例代码
2013/07/04 Javascript
js switch case default 的用法示例介绍
2013/10/23 Javascript
js向上无缝滚动,网站公告效果 具体代码
2013/11/18 Javascript
js中小数转换整数的方法
2014/01/26 Javascript
JS自定义选项卡函数及用法实例分析
2015/09/02 Javascript
jquery获取table指定行和列的数据方法(当前选中行、列)
2016/11/07 Javascript
Angularjs单选改为多选的开发过程及问题解析
2017/02/17 Javascript
JQuery 获取多个select标签option的text内容(实例)
2017/09/07 jQuery
深入浅析AngularJs模版与v-bind
2018/07/06 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
2019/03/07 Javascript
Node.js API详解之 zlib模块用法分析
2020/05/19 Javascript
[50:02]完美世界DOTA2联赛PWL S2 Magma vs FTD 第三场 11.29
2020/12/03 DOTA
在Django框架中编写Contact表单的教程
2015/07/17 Python
python读写json文件的简单实现
2017/04/11 Python
Java及python正则表达式详解
2017/12/27 Python
Numpy掩码式数组详解
2018/04/17 Python
python实现最长公共子序列
2018/05/22 Python
Django中的ajax请求
2018/10/19 Python
浅谈keras中loss与val_loss的关系
2020/06/22 Python
如何在Win10系统使用Python3连接Hive
2020/10/15 Python
ANINE BING官方网站:奢华的衣橱基本款和时尚永恒的单品
2019/11/26 全球购物
String这个类型的class为何定义成final?
2012/11/13 面试题
高中学生干部学习的自我评价
2014/02/21 职场文书
三年级小学生评语
2014/04/22 职场文书
实习单位鉴定评语
2014/04/26 职场文书
学校党的群众路线教育实践活动总结报告
2014/07/03 职场文书
做一个有道德的人活动实施方案
2014/08/23 职场文书
中国汉字听写大会观后感
2015/06/02 职场文书
Python竟然能剪辑视频
2021/05/25 Python
mysql升级到5.7时,wordpress导数据报错1067的问题
2021/05/27 MySQL
详解Python为什么不用设计模式
2021/06/24 Python
JavaScript执行机制详细介绍
2021/12/06 Javascript
攻击最高的10只幽灵系神奇宝贝,坚盾剑怪排第一,第五最为可怕
2022/03/18 日漫