面向对象-贪吃蛇

一、面向对象-贪吃蛇

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Document</title>
  </head>
  <body>
    <button>按钮</button>
  </body>
  <script type="text/javascript">
    var timerId;
    document.querySelector("button").onclick = function () {
      // 让蛇动起来 - 定时器移动
      timerId = setInterval(() => {
        s.move();
      }, 100);
    };
    // 地图对象
    function Map() {
      // 地图对象负责创建范围,放蛇和食物
      this.map = document.createElement("div");
      setStyle(this.map, {
        width: "800px",
        height: "500px",
        background: "pink",
        border: "2px solid #000",
        position: "relative",
      });
      // 将地图放在body中
      document.body.appendChild(this.map);
    }
    var m = new Map();
    // 食物对象
    function Food() {
      // 食物对象负责生成,消失(地图干掉他)
      this.food = document.createElement("div");
      setStyle(this.food, {
        width: "10px",
        height: "10px",
        background: "blue",
        position: "absolute",
        left: parseInt(getRandom(0, m.map.clientWidth - 10) / 10) * 10 + "px",
        top: parseInt(getRandom(0, m.map.clientHeight - 10) / 10) * 10 + "px",
      });
      // 将食物放到地图中
      m.map.appendChild(this.food);
    }
    var f = new Food();
    // 蛇对象
    function Snake() {
      // 定义蛇的身体的left和top
      this.body = [
        {
          x: 0,
          y: 0,
        },
        {
          x: 10,
          y: 0,
        },
        {
          x: 20,
          y: 0,
        },
      ];
      // 定义蛇的移动方向
      this.direction = "right";
      // 通过按键改变蛇的移动方向
      this.changeDirection();
      // 显示蛇的身体
      this.show();
    }
    Snake.prototype.changeDirection = function () {
      document.onkeypress = (e) => {
        var e = e || window.event;
        // 获取键码
        var code = e.keyCode || e.which;
        // 根据键码改变direction属性
        // console.log(code); // 119 115 97 100
        switch (code) {
          case 119:
            this.direction = "up";
            break;
          case 115:
            this.direction = "down";
            break;
          case 97:
            this.direction = "left";
            break;
          case 100:
            this.direction = "right";
            break;
        }
      };
    };
    Snake.prototype.move = function () {
      console.log(this.direction);
      // 蛇移动需要一个方向 - 默认方向
      // 蛇在移动过程中,不管是哪个方向,移动一步,蛇的第二节身体就是蛇头原来的位置,蛇的最后一节身体就是,第二节身体原来的位置
      for (var i = 0; i < this.body.length - 1; i++) {
        this.body[i].x = this.body[i + 1].x;
        this.body[i].y = this.body[i + 1].y;
      }
      // console.log(this.body);
      // 单独设置蛇头
      switch (this.direction) {
        case "up":
          this.body[this.body.length - 1].y -= 10;
          break;
        case "down":
          this.body[this.body.length - 1].y += 10;
          break;
        case "left":
          this.body[this.body.length - 1].x -= 10;
          break;
        case "right":
          this.body[this.body.length - 1].x += 10;
          break;
      }
      // console.log(this.body);
      // 根据新的数组显示身体
      this.show();
      this.eat();
      // 蛇不能撞墙
      this.die();
    };
    Snake.prototype.die = function () {
      // 撞墙
      if (
        this.body[this.body.length - 1].x > m.map.clientWidth ||
        this.body[this.body.length - 1].x < 0 ||
        this.body[this.body.length - 1].y < 0 ||
        this.body[this.body.length - 1].y > m.map.clientHeight
      ) {
        
        clearInterval(timerId);
        alert("GAME OVER");
        s = new Snake();
      }
      // 撞身体
      for (var i = 0; i < this.body.length - 1; i++) {
        if (
          this.body[i].x === this.body[this.body.length - 1].x &&
          this.body[i].y === this.body[this.body.length - 1].y
        ) {
          clearInterval(timerId);
          alert("GAME OVER");
          s = new Snake();
        }
      }
    };
    Snake.prototype.eat = function () {
      // 蛇头的x和y跟食物的left和top完全相等的时候就吃到了
      if (
        this.body[this.body.length - 1].x === f.food.offsetLeft &&
        this.body[this.body.length - 1].y === f.food.offsetTop
      ) {
        // 吃到了
        // 蛇的身体要加一节
        var oneBody = {
          x: this.body[0].x,
          y: this.body[0].y,
        };
        // 将这个对象放到身体数组的最前面
        this.body.unshift(oneBody);
        // 根据新的数组生成新的身体
        this.show();
        // 食物要消失,并再生成一个
        f.food.parentElement.removeChild(f.food);
        f = new Food();
      }
    };
    Snake.prototype.show = function () {
      // 先删除之前的身体 - 再创建新的身体
      var snakes = m.map.querySelectorAll(".snake");
      // console.log(snakes);
      if (snakes.length !== 0) {
        for (var i = 0; i < snakes.length; i++) {
          snakes[i].parentElement.removeChild(snakes[i]);
        }
      }
      // 遍历身体属性,创建div
      for (var i = 0; i < this.body.length; i++) {
        var div = document.createElement("div");
        div.className = "snake";
        setStyle(div, {
          width: "10px",
          height: "10px",
          background: "#0f0",
          position: "absolute",
          left: this.body[i].x + "px",
          top: this.body[i].y + "px",
        });
        if (i === this.body.length - 1) {
          div.style.background = "red";
        }
        m.map.appendChild(div);
      }
    };
    var s = new Snake();

    function setStyle(ele, styleObj) {
      for (var attr in styleObj) {
        ele.style[attr] = styleObj[attr];
      }
    }
    function getRandom(min, max) {
      if (min > max) {
        var tmp = min;
        min = max;
        max = tmp;
      }
      return parseInt(Math.random() * (max - min) + 1);
    }
  </script>
</html>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
利用面向对象的方法,实现贪吃蛇。 1. 利用面向对象的思想实现——一个食物对象、一个蛇对象、一个游戏总控对象。 2. 在使用××.prototype= {}重写原型对象的时候,一定要加上一句constructor:该对象。不然会造成实例化出来的实例的constructor为object。 3. 在underscore中,使用_.random(a,b)即可获得a-b中的一个随机数。 4. 在求食物的随机位置的时候,用到了panel.clientHeight/this.height - 1) * this.height。 原理是使用盒子的高度/小球的高度,可以算得最多放多少个小球。因为要控制小球不能超过边界,所以总数量要减去1,数量×高度即为随机位置的最大值。 5. 在蛇对象中,用body数组存放蛇身体每一个部分对象。蛇的绘制过程就是遍历body,在面板上绘制。 6. 蛇的移动分为两部分。 ① 蛇节移动到前一个蛇节的位置。直到蛇头后一个蛇节移动到蛇头的位置。 ② 根据direction判断蛇头如何移动。 注意:在游戏绘制的过程中,界面的每一次绘制都要**删除**之前的绘制,不然会叠加到一起。 7. 在蛇的闭包中建一个局部数组,存储蛇对象,可以更加方便的删除操作。 8. 只有在原型对象中的方法和属性,外界是可以调用的。 9. 蛇的移动(动画)必然需要定时器协助。定时器的时间,即象征着刷新速度,也就是难度。 10. this所在的函数在哪一个对象中,this就指向谁。单独写一个函数的时候,如果调用之前对象的this,需要备份指针(将对象的this赋值给另一个变量)。 11. JavaScript原生的键盘按下事件(keydown) 中,事件有一个keyCode属性,其值代表按下的键。其中:37—left、38—top、39—right、40—bottom。 12. 边界控制。通过判断蛇头与最大X和Y的关系,判断是否碰到边界。 13. confirm()方法用于显示一个带有指定消息和确认及取消按钮的对话框。 14. window.location.reload(); 重新加载当前文档 15. window.close() 方法用于关闭浏览器窗口。 16. 与食物的碰撞检测:如果蛇头和食物坐标重叠,将蛇尾添加到body中。并重新绘制一个食物点,将之前的食物删掉。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值