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 相关文章推荐
js动态设置div的值下例子
Oct 29 Javascript
JavaScript类属性的访问方式详解
Feb 11 Javascript
angularjs实现下拉列表的选中事件示例
Mar 03 Javascript
react性能优化达到最大化的方法 immutable.js使用的必要性
Mar 09 Javascript
AngularJS实用基础知识_入门必备篇(推荐)
Jul 10 Javascript
Element Table的row-class-name无效与动态高亮显示选中行背景色
Nov 30 Javascript
JavaScript动态添加数据到表单并提交的几种方式
Jun 26 Javascript
vue+moment实现倒计时效果
Aug 26 Javascript
javascript中正则表达式语法详解
Aug 07 Javascript
Vue-cli打包后部署到子目录下的路径问题说明
Sep 02 Javascript
springboot+vue实现文件上传下载
Nov 17 Vue.js
Javascript实现单选框效果
Dec 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函数
2006/10/09 PHP
自动把纯文本转换成Web页面的php代码
2009/08/27 PHP
php 各种应用乱码问题的解决方法
2010/05/09 PHP
PHP数组中头部和尾部添加元素的方法(array_unshift,array_push)
2017/04/10 PHP
简单通用的JS滑动门代码
2008/12/19 Javascript
基于jQuery的左右滚动实现代码
2010/12/03 Javascript
js正文内容高亮效果的实现方法
2013/06/30 Javascript
JS实现侧悬浮浮动实例代码
2013/11/29 Javascript
node.js中使用node-schedule实现定时任务实例
2014/06/03 Javascript
jquery插件hiAlert实现网页对话框美化
2015/05/03 Javascript
KnockoutJS 3.X API 第四章之表单textInput、hasFocus、checked绑定
2016/10/11 Javascript
js实现tab选项卡切换功能
2017/01/13 Javascript
浅谈Vue.js中的v-on(事件处理)
2017/09/05 Javascript
vue.js实现的绑定class操作示例
2018/07/06 Javascript
laydate只显示时分 不显示秒的功能实现方法
2019/09/28 Javascript
js实现中文实时时钟
2020/01/15 Javascript
解决vue-cli@3.xx安装不成功的问题及搭建ts-vue项目
2020/02/09 Javascript
jquery+css3实现的经典弹出层效果示例
2020/05/16 jQuery
JavaScript中使用Spread运算符的八种方法总结
2020/06/18 Javascript
python 多线程应用介绍
2012/12/19 Python
Python实现把xml或xsl转换为html格式
2015/04/08 Python
Python 常用的安装Module方式汇总
2017/05/06 Python
Python实现可自定义大小的截屏功能
2018/01/20 Python
PyQt5每天必学之关闭窗口
2018/04/19 Python
计算机二级python学习教程(1) 教大家如何学习python
2019/05/16 Python
flask 使用 flask_apscheduler 做定时循环任务的实现
2019/12/10 Python
python爬虫容易学吗
2020/06/02 Python
HTML5中的网络存储实现方式
2020/04/28 HTML / CSS
线程同步的方法
2016/11/23 面试题
文秘应聘自荐书范文
2014/02/18 职场文书
村安全生产责任书
2014/08/25 职场文书
党的群众路线教育实践活动个人对照检查材料(乡镇)
2014/11/05 职场文书
写景作文评语集锦
2014/12/25 职场文书
演讲稿:​快乐,从不抱怨开始!
2019/04/02 职场文书
使用nginx配置访问wgcloud的方法
2021/06/26 Servers
SQL实现LeetCode(196.删除重复邮箱)
2021/08/07 MySQL