• javascript:用原生js模拟贪吃蛇游戏练习


    本次练习所有的代码:可以直接复制全部然后运行看效果~

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4   <meta charset="UTF-8">
      5   <title>title</title>
      6   <style>
      7     .map {
      8       width: 800px;
      9       height: 600px;
     10       background-color: #CCC;
     11       position: relative;
     12     }
     13   </style>
     14 </head>
     15 <body>
     16 <!--画出地图,设置样式-->
     17 <div class="map"></div>
     18 <script>
     19 
     20 
     21   //自调用函数----食物的
     22   (function () {
     23     var elements = [];//用来保存每个小方块食物的
     24     //食物就是一个对象,有宽,有高,有颜色,有横纵坐标,先定义构造函数,然后创建对象
     25     function Food(x, y, width, height, color) {
     26       //横纵坐标
     27       this.x = x || 0;
     28       this.y = y || 0;
     29       //宽和高
     30       this.width = width || 20;
     31       this.height = height || 20;
     32       //背景颜色
     33       this.color = color || "green";
     34     }
     35 
     36     //为原型添加初始化的方法(作用:在页面上显示这个食物)
     37     //因为食物要在地图上显示,所以,需要地图的这个参数(map---就是页面上的.class=map的这个div)
     38     Food.prototype.init = function (map) {
     39       //先删除这个小食物
     40       //外部无法访问的函数
     41       remove();
     42 
     43       //创建div
     44       var div = document.createElement("div");
     45       //把div加到map中
     46       map.appendChild(div);
     47       //设置div的样式
     48       div.style.width = this.width + "px";
     49       div.style.height = this.height + "px";
     50       div.style.backgroundColor = this.color;
     51       //先脱离文档流
     52       div.style.position = "absolute";
     53       //随机横纵坐标
     54       this.x = parseInt(Math.random() * (map.offsetWidth / this.width)) * this.width;
     55       this.y = parseInt(Math.random() * (map.offsetHeight / this.height)) * this.height;
     56       div.style.left = this.x + "px";
     57       div.style.top = this.y + "px";
     58 
     59       //把div加入到数组elements中
     60       elements.push(div);
     61     };
     62 
     63     //私有的函数---删除食物的
     64     function remove() {
     65       //elements数组中有这个食物
     66       for (var i = 0; i < elements.length; i++) {
     67         var ele = elements[i];
     68         //找到这个子元素的父级元素,然后删除这个子元素
     69         ele.parentNode.removeChild(ele);
     70         //再次把elements中的这个子元素也要删除
     71         elements.splice(i, 1);
     72       }
     73     }
     74 
     75     //把Food暴露给Window,外部可以使用
     76     window.Food = Food;
     77   }());
     78 
     79   //自调用函数---小蛇
     80   (function () {
     81     var elements = [];//存放小蛇的每个身体部分
     82     //小蛇的构造函数
     83     function Snake(width, height, direction) {
     84       //小蛇的每个部分的宽
     85       this.width = width || 20;
     86       this.height = height || 20;
     87       //小蛇的身体
     88       this.body = [
     89         {x: 3, y: 2, color: "red"},//
     90         {x: 2, y: 2, color: "orange"},//身体
     91         {x: 1, y: 2, color: "orange"}//身体
     92       ];
     93       //方向
     94       this.direction = direction || "right";
     95     }
     96 
     97     //为原型添加方法--小蛇初始化的方法
     98     Snake.prototype.init = function (map) {
     99       //先删除之前的小蛇
    100       remove();//===========================================
    101 
    102       //循环遍历创建div
    103       for (var i = 0; i < this.body.length; i++) {
    104         //数组中的每个数组元素都是一个对象
    105         var obj = this.body[i];
    106         //创建div
    107         var div = document.createElement("div");
    108         //把div加入到map地图中
    109         map.appendChild(div);
    110         //设置div的样式
    111         div.style.position = "absolute";
    112         div.style.width = this.width + "px";
    113         div.style.height = this.height + "px";
    114         //横纵坐标
    115         div.style.left = obj.x * this.width + "px";
    116         div.style.top = obj.y * this.height + "px";
    117         //背景颜色
    118         div.style.backgroundColor = obj.color;
    119         //方向暂时不定
    120         //把div加入到elements数组中----目的是为了删除
    121         elements.push(div);
    122       }
    123     };
    124 
    125     //为原型添加方法---小蛇动起来
    126     Snake.prototype.move = function (food, map) {
    127       //改变小蛇的身体的坐标位置
    128       var i = this.body.length - 1;//2
    129       for (; i > 0; i--) {
    130         this.body[i].x = this.body[i - 1].x;
    131         this.body[i].y = this.body[i - 1].y;
    132       }
    133       //判断方向---改变小蛇的头的坐标位置
    134       switch (this.direction) {
    135         case "right":
    136           this.body[0].x += 1;
    137           break;
    138         case "left":
    139           this.body[0].x -= 1;
    140           break;
    141         case "top":
    142           this.body[0].y -= 1;
    143           break;
    144         case "bottom":
    145           this.body[0].y += 1;
    146           break;
    147       }
    148 
    149       //判断有没有吃到食物
    150       //小蛇的头的坐标和食物的坐标一致
    151       var headX=this.body[0].x*this.width;
    152       var headY=this.body[0].y*this.height;
    153       //判断小蛇的头的坐标和食物的坐标是否相同
    154       if(headX==food.x&&headY==food.y){
    155         //获取小蛇的最后-的尾巴
    156         var last=this.body[this.body.length-1];
    157         //把最后的蛇尾复制一个,重新的加入到小蛇的body中
    158         this.body.push({
    159           x:last.x,
    160           y:last.y,
    161           color:last.color
    162         });
    163         //把食物删除,重新初始化食物
    164         food.init(map);
    165       }
    166     };
    167 
    168     //删除小蛇的私有的函数=============================================================================
    169     function remove() {
    170       //删除map中的小蛇的每个div,同时删除elements数组中的每个元素,从蛇尾向蛇头方向删除div
    171       var i = elements.length - 1;
    172       for (; i >= 0; i--) {
    173         //先从当前的子元素中找到该子元素的父级元素,然后再弄死这个子元素
    174         var ele = elements[i];
    175         //从map地图上删除这个子元素div
    176         ele.parentNode.removeChild(ele);
    177         elements.splice(i, 1);
    178       }
    179     }
    180 
    181     //把Snake暴露给window,外部可以访问
    182     window.Snake = Snake;
    183   }());
    184 
    185   //自调用函数---游戏对象================================================
    186   (function () {
    187 
    188     var that = null;//该变量的目的就是为了保存游戏Game的实例对象-------
    189 
    190     //游戏的构造函数
    191     function Game(map) {
    192       this.food = new Food();//食物对象
    193       this.snake = new Snake();//小蛇对象
    194       this.map = map;//地图
    195       that = this;//保存当前的实例对象到that变量中-----------------此时that就是this
    196     }
    197 
    198     //初始化游戏-----可以设置小蛇和食物显示出来
    199     Game.prototype.init = function () {
    200       //初始化游戏
    201       //食物初始化
    202       this.food.init(this.map);
    203       //小蛇初始化
    204       this.snake.init(this.map);
    205       //调用自动移动小蛇的方法========================||调用了小蛇自动移动的方法
    206       this.runSnake(this.food, this.map);
    207       //调用按键的方法
    208       this.bindKey();//========================================
    209     };
    210 
    211     //添加原型方法---设置小蛇可以自动的跑起来
    212     Game.prototype.runSnake = function (food, map) {
    213 
    214       //自动的去移动
    215       var timeId = setInterval(function () {
    216         //此时的this是window
    217         //移动小蛇
    218         this.snake.move(food, map);
    219         //初始化小蛇
    220         this.snake.init(map);
    221         //横坐标的最大值
    222         var maxX = map.offsetWidth / this.snake.width;
    223         //纵坐标的最大值
    224         var maxY = map.offsetHeight / this.snake.height;
    225         //小蛇的头的坐标
    226         var headX = this.snake.body[0].x;
    227         var headY = this.snake.body[0].y;
    228         //横坐标
    229         if (headX < 0 || headX >= maxX) {
    230           //撞墙了,停止定时器
    231           clearInterval(timeId);
    232           alert("游戏结束");
    233         }
    234         //纵坐标
    235         if (headY < 0 || headY >= maxY) {
    236           //撞墙了,停止定时器
    237           clearInterval(timeId);
    238           alert("游戏结束");
    239         }
    240       }.bind(that), 150);
    241     };
    242 
    243     //添加原型方法---设置用户按键,改变小蛇移动的方向
    244     Game.prototype.bindKey=function () {
    245 
    246       //获取用户的按键,改变小蛇的方向
    247       document.addEventListener("keydown",function (e) {
    248         //这里的this应该是触发keydown的事件的对象---document,
    249         //所以,这里的this就是document
    250         //获取按键的值
    251         switch (e.keyCode){
    252           case 37:this.snake.direction="left";break;
    253           case 38:this.snake.direction="top";break;
    254           case 39:this.snake.direction="right";break;
    255           case 40:this.snake.direction="bottom";break;
    256         }
    257       }.bind(that),false);
    258     };
    259 
    260     //把Game暴露给window,外部就可以访问Game对象了
    261     window.Game = Game;
    262   }());
    263 
    264 
    265 
    266   //初始化游戏对象
    267   var gm = new Game(document.querySelector(".map"));
    268 
    269   //初始化游戏---开始游戏
    270   gm.init();
    271 
    272 
    273  
    274 
    275 </script>
    276 </body>
    277 </html>
    View Code

    如下图:单个方块表示食物,三个方块连接一起表示小蛇,其中紫色方块是蛇头,虽然看起来简单,做起来也需要不少的步骤,我们先分析一下思路~

    首先,创建一个地图~然后坐标随机显示食物方块,每次食物被小蛇“吃掉”的时候重新初始化;

    然后,设置固定位置显示小蛇方块,设置定时器,让小蛇动起来,判断小蛇是否“吃掉”食物,是则初始化食物,复制蛇身最后一个方块加到小蛇身体最后~判断小蛇是否“撞墙”,是则提示游戏提示。

    那么具体步骤现在开始~

    设置食物方块的自调用函数

    • 设置方块的构造函数,同时设置一个变量准备存储每个小方块食物:
    (function () {
        var elements = [];
       
        function Food(x, y, width, height, color) {
          this.x = x || 0;
          this.y = y || 0;
          this.width = width || 20;
          this.height = height || 20;
          this.color = color || "green";
        }
    //把Food暴露给window,外部可以访问
    window.Food = Food;
    }());
    • 初始化食物,赋值并且在地图上显示出来,注意:记得把食物加到一开始设置的变量中 var elements = [ ];
    Food.prototype.init = function (map) {
          remove();
    
          var div = document.createElement("div");
          map.appendChild(div);
          div.style.width = this.width + "px";
          div.style.height = this.height + "px";
          div.style.backgroundColor = this.color;
          div.style.position = "absolute";
          this.x = parseInt(Math.random() * (map.offsetWidth / this.width)) * this.width;
          this.y = parseInt(Math.random() * (map.offsetHeight / this.height)) * this.height;
          div.style.left = this.x + "px";
          div.style.top = this.y + "px";
    
          //把div加入到数组elements中
          elements.push(div);
        };
    • 设置初始化食物的第一个步骤,先在地图上删除这个食物:
     function remove() {
          for (var i = 0; i < elements.length; i++) {
            var ele = elements[i];
            ele.parentNode.removeChild(ele);
            elements.splice(i, 1);
          }
        }

    设置小蛇的自调用函数

    • 设置方块的构造函数,同时设置一个变量准备存储每个小蛇的单个身体:
    (function () {
        var elements = [];
     function Snake(width, height, direction) {
          this.width = width || 20;
          this.height = height || 20;
          this.body = [
            {x: 3, y: 2, color: "red"},//头
            {x: 2, y: 2, color: "orange"},//身体
            {x: 1, y: 2, color: "orange"}//身体
          ];
          //方向
          this.direction = direction || "right";
        }
    //把Snake暴露给window,外部可以访问
    window.Snake = Snake;
    }());
    • 设置小蛇初始化的函数
     Snake.prototype.init = function (map) {
          //先删除之前的小蛇
          remove();
          for (var i = 0; i < this.body.length; i++) {
            var obj = this.body[i];
            var div = document.createElement("div");
            map.appendChild(div);
            div.style.position = "absolute";
            div.style.width = this.width + "px";
            div.style.height = this.height + "px";
            div.style.left = obj.x * this.width + "px";
            div.style.top = obj.y * this.height + "px";
            div.style.backgroundColor = obj.color
            //把div加入到elements数组中----目的是为了删除
            elements.push(div);
          }
        };
    • 设置小蛇动起来的函数:
      • 让小蛇动起来相当于是改变了小蛇的坐标
      • 判断小蛇动起来的方向,然后坐标对应处理
      • 判断小蛇是否“吃到”了食物,是则初始化食物,并且把蛇身最后一个部分复制一分加到蛇身最后
    Snake.prototype.move = function (food, map) {
          //改变小蛇的身体的坐标位置
          var i = this.body.length - 1;//2
          for (; i > 0; i--) {
            this.body[i].x = this.body[i - 1].x;
            this.body[i].y = this.body[i - 1].y;
          }
          
          switch (this.direction) {
            case "right":
              this.body[0].x += 1;
              break;
            case "left":
              this.body[0].x -= 1;
              break;
            case "top":
              this.body[0].y -= 1;
              break;
            case "bottom":
              this.body[0].y += 1;
              break;
          }
    
          var headX=this.body[0].x*this.width;
          var headY=this.body[0].y*this.height;
         
          if(headX==food.x&&headY==food.y){
          
            var last=this.body[this.body.length-1];
            
            this.body.push({
              x:last.x,
              y:last.y,
              color:last.color
            });
            //把食物删除,重新初始化食物
            food.init(map);
          }
        };
    • 不要忘记设置初始化小蛇的第一个步骤,在地图上删除这个小蛇:
     function remove() {
          var i = elements.length - 1;
          for (; i >= 0; i--) {
            var ele = elements[i];
            ele.parentNode.removeChild(ele);
            elements.splice(i, 1);
          }
        }

     

    设置游戏的自调用函数:

    • 设置游戏的构造函数,同时设置一个变量准备存储游戏Game的实例对象:var that=this;
     (function () {
        var that = null;//该变量的目的就是为了保存游戏Game的实例对象------
        function Game(map) {
          this.food = new Food();//食物对象
          this.snake = new Snake();//小蛇对象
          this.map = map;//地图
          that = this;//保存当前的实例对象到that变量中------此时that就是this
        }
    
        //把Game暴露给window,外部就可以访问Game对象了
        window.Game = Game;
      }());
    • 初始化游戏:可以设置小蛇和食物显示出来
     Game.prototype.init = function () {
          
          this.food.init(this.map);
         
          this.snake.init(this.map);
         
          this.runSnake(this.food, this.map);
         
          this.bindKey();
        };
    • 设置小蛇可以自动的跑起来
    Game.prototype.runSnake = function (food, map) {
    
          var timeId = setInterval(function () {
            
            this.snake.move(food, map);
            this.snake.init(map);
            
            var maxX = map.offsetWidth / this.snake.width;
            var maxY = map.offsetHeight / this.snake.height;
         
            var headX = this.snake.body[0].x;
            var headY = this.snake.body[0].y;
            
            if (headX < 0 || headX >= maxX) {
              //撞墙了,停止定时器
              clearInterval(timeId);
              alert("游戏结束");
            }
            
            if (headY < 0 || headY >= maxY) {
              //撞墙了,停止定时器
              clearInterval(timeId);
              alert("游戏结束");
            }
          }.bind(that), 150);
        };
    • 设置用户按键,改变小蛇移动的方向
     Game.prototype.bindKey=function () {
    
          document.addEventListener("keydown",function (e) {
             switch (e.keyCode){
              case 37:this.snake.direction="left";break;
              case 38:this.snake.direction="top";break;
              case 39:this.snake.direction="right";break;
              case 40:this.snake.direction="bottom";break;
            }
          }.bind(that),false);
        };

    初始化游戏对象,开始游戏

    var gm = new Game(document.querySelector(".map"));
    gm.init();

    好的,到这里结束啦~

    另外如果有前端学习者想要寻找伙伴一起合作项目,可以来我这个群~群内还有大神等你哈哈哈~

    前端学习交流群 883726280 

  • 相关阅读:
    FPGA--Cyclone中的时钟资源
    网易的翻译蛋
    程序员的健康问题,水桶腰
    如何像如何像 NASA 顶级程序员一样编程 — 10 条重要原则
    FOC_矢量控制相关资料
    BLDC 无刷电机FOC驱动 STM32官方培训资料
    ueditor插入百度音乐无法播放-403 问题
    phpstudy APACHE支持.htaccess以及 No input file specified解决方案
    linux数据库备份脚本
    阿里云centos 搭建SVN
  • 原文地址:https://www.cnblogs.com/xhysns/p/10164418.html
Copyright © 2020-2023  润新知