JS小游戏--贪吃蛇

学习JS,用JS制作了一个小游戏--贪吃蛇

代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .map {
      width: 800px;
      height: 800px;
      background-color: #ccc;
      position: relative;
      top: 100px;
      left: 50%;
      margin-left: -400px;
    }
  </style>
</head>

<body>
  <div class="map"></div>
  <script>
    // 自调用函数 --- 食物的
    (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";
      }

      //为原型添加初始化的方法(作用:在页面上显示这个食物)
      //因为食物要在地图上显示,所以,需要地图的这个参数(map---就是页面上的.class=map的这个div)
      Food.prototype.init = function (map) {
        //先删除这个小食物
        //外部无法访问的函数
        remove();
        // 创建div
        var div = document.createElement("div");
        map.appendChild(div); //把 div 加到 map 中
        // 设置div样式
        div.style.width = this.width + "px";
        div.style.height = this.height + "px";
        div.style.backgroundColor = this.color;
        // 先脱离文档流
        div.style.position = "absolute";
        // 随机横纵坐标
        this.x = Math.floor(Math.random() * map.offsetWidth / this.width) * this.width;
        this.y = Math.floor(Math.random() * map.offsetHeight / this.height) * this.height;
        div.style.left = this.x + "px";
        div.style.top = this.y + "px";
        elements.push(div); // 把 div加入到数组 elements 中
      };

      // 私有的函数---删除食物
      function remove() {
        // elements 数组中有这个食物
        for (var i = 0; i < elements.length; i++) {
          var ele = elements[i];
          // 找到这个子元素的父级元素,然后删除这个子元素
          ele.parentNode.removeChild(ele);
          // 再次把elements中的这个子元素也要删除
          elements.splice(i, 1);
        }
      }

      // 把 Food 暴露给 window ,外部可以使用
      window.Food = Food;
    }());

    // 自调用函数 --- 小蛇
    (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 原型添加方法 --- 初始化
      Snake.prototype.init = function (map) {
        // 先删除之前的小蛇
        remove();
        // 循环遍历div
        for (var i = 0; i < this.body.length; i++) {
          // body中的每一个对象
          var obj = this.body[i];
          // 创建div
          var div = document.createElement("div");
          // 向map中添加div
          map.appendChild(div);
          // 设置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 原型添加方法 --- 小蛇移动
      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) {
          // 获取小蛇最后的尾巴
          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; //2
        for (; i >= 0; i--) {
          var ele = elements[i];
          ele.parentNode.removeChild(ele);
          elements.splice(i, 1);
        }
      }

      // 把 Snake 暴露给 window,外部可以使用
      window.Snake = Snake;
    }());

    // 自调用函数 --- 游戏对象
    (function () {
      var that = null; // 该变量的目的就是为了保存游戏Game的实例对象

      function Game(map) {
        this.food = new Food();
        this.snake = new Snake();
        this.map = map;
        that = this; // 保存当前的实例对象到that变量中
      }

      // 初始化游戏-----可以设置小蛇和食物显示出来
      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是指 window
          // 移动小蛇
          this.snake.move(food, map);
          // 初始化小蛇
          this.snake.init(map);

          // 横纵坐标的最大值
          var maxX = map.offsetWidth / this.snake.width; // 40
          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 || headY < 0 || headY >= maxY) {
            clearInterval(timeId);
            alert("游戏结束!您的游戏得分:"+this.snake.body.length);
          }
        }.bind(that), 70); // bind改变了 this的指向
      };

      // 添加原型方法---设置用户按键,改变小蛇移动方向
      Game.prototype.bindKey = function () {
        document.addEventListener("keydown", function (e) {
          // 这里的this应该是触发keydown的事件的对象---document,
          // 所以,这里的this就是document
          // 获取按键的值
          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);
      };

      // 把 Game方法暴露给window,外部可以使用
      window.Game = Game;
    }());

    // 创建实例对象
    var gm = new Game(document.querySelector(".map"));

    // 初始化游戏
    gm.init();
  </script>
</body>

</html>

效果我做了个GIF动图显示一下:

 

 

 

感兴趣的朋友可以自己研究一下,改进一下细节,有什么好的idea欢迎在评论区分享,JS真的很有趣呢!

posted @ 2020-03-17 21:52  木子呆头  阅读(154)  评论(0编辑  收藏  举报