前端学习笔记JavaScript - 贪吃蛇

创建地图

直接通过css来创建

@charset "UTF-8";

.map {
  width: 600px;
  height: 600px;
  border: 1px solid gray;
  margin: 100px auto;
  position: relative;
}

创建食物

首先定义食物的构造函数,在构造函数中有食物的大小、颜色,由于需要获取地图能放置多少食物,所以还需要获取地图对象。
地图每行能放多少食物 = 地图的高/食物的高;
地图每列能放多少食物 = 地图的宽/食物的宽;

constructor(obj,oMap) {
      this.width  = obj.width;
      this.height = obj.height;
      this.color  = obj.color;
      this.oMap   = oMap;

      // -- 获取地图的大小
      let oMapStyle = getComputedStyle(oMap);
      // --  获取每行每列可以放多少个食物
      this.col = parseInt(oMapStyle.width) / this.width;
      this.row = parseInt(oMapStyle.height) / this.height;
    }
  • 渲染食物(将食物显示在地图中)

食物的位置 = 0到每行或每列最大食物个数中的随机数再乘以食物本身的宽或高就是食物的位置。这样食物出现的位置就是随机位置且不回超出地图的边界。
需要报食物的位置传递给蛇,让蛇知道吃到了食物,所以增加了x和y两个属性

  // -- 渲染
  render(){
      // -- 创建食物
      let ofood = document.createElement("div");
      ofood.style.width  = this.width + "px";
      ofood.style.height = this.height + "px";
      ofood.style.backgroundColor = this.color;
      ofood.className = "food";
      ofood.style.position = "absolute"
      // -- 食物位置,通过getRandomIntInclusive生成0到每行或每列最大食物个数中的随机数再乘以食物本身的宽或高就是食物的位置。
      ofood.style.left = getRandomIntInclusive(0,this.col-1) * this.width + "px";
      ofood.style.top  = getRandomIntInclusive(0,this.row-1) * this.height + "px";
      this.oMap.appendChild(ofood);
      // -- x和y给蛇获取,用于判断是否吃到食物
      this.x = ofood.style.left;
      this.y = ofood.style.top;
    }
  • 生成随机数
// - 获取min和max之前的随机数,包括min和max
  function getRandomIntInclusive(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }
  • 删除食物

当蛇吃到食物后需要删除食物

    // -- 删除食物
    remove() {
      let food = document.querySelector(".food");
      food.parentNode.removeChild(food);
    }

创建蛇

首先定义蛇的构造函数,在构造函数中有蛇头蛇身的大小、颜色,同时将每个蛇身和蛇头放进数组中,通过改变数组中蛇头蛇身的值来使蛇移动。

  constructor(obj,oMap) {
    this.width     = obj.width;
    this.height    = obj.height;
    this.headColor = obj.headColor;
    this.bodyColor = obj.bodyColor;
    this.oMap = oMap;

    /* 将默认的蛇头和身体放入数组
     * type:1(蛇头) 0(蛇身)
     * x:1 距离左边1个蛇身的位置,y:1 距离顶部一个蛇身的位置
     */
    this.list = [
      {x:2,y:1,type:1},
      {x:1,y:1,type:0},
      {x:0,y:1,type:0}
    ]

    // -- 获取地图的大小
    let oMapStyle = getComputedStyle(oMap);
    // --  获取每行每列可以放多少个食物
    this.col = parseInt(oMapStyle.width) / this.width;
    this.row = parseInt(oMapStyle.height) / this.height;
  }
  • 蛇移动
// - 蛇移动的方法
  move(food) {
    /* 蛇身体每个部位移动的方法
     * 蛇的身体的位置只要获取前一个身体移动的位置就可以了
     * 所以先循环获取到最后一个身体,将最后一个身体前面的身体的位置复制给最后一个身体,最后一个身体就移动了
     * 同理可证,其他按照这个思路就实现了蛇身的移动    *
     */

    for (let i = this.list.length - 1;i > 0;i--){
      this.list[i].x = this.list[i-1].x;
      this.list[i].y = this.list[i-1].y;
    }

    /* 蛇头的移动
     * 获取到蛇头,根据上下左右方向键判断对x或y值累加或累减
     * x+1,说明蛇头向右移动一格
     */
    let head = this.list[0];
    switch (this.downKey) {
      case "ArrowUp":
        head.y -= 1;
        break;
      case "ArrowDown":
        head.y += 1;
        break;
      case "ArrowLeft":
        head.x -= 1;
        break;
      case "ArrowRight":
        head.x += 1;
        break;
      default:
        head.x += 1;
        break;
    }
  }
  • 撞墙吃食检车
  // - 检测方法
  check(food) {
    // -- 蛇头
    let head = this.list[0];
    // -- 判断蛇头是不是到达地图的边界
    if (head.x >= this.col || head.y >= this.row || head.x < 0 || head.y < 0){
      alert("撞了")
      clearInterval(this.timer);
      return false;
    }

    // -- 蛇头的x和y值
    let sX = head.x * this.width;
    let sY = head.y * this.height;
    console.log(sX,food.x);

    // -- 判断蛇头的x和y值是不是和食物的x和y值完全相等
    if (sX === parseInt(food.x) && sY === parseInt(food.y)){
      // -- 获取到蛇的最后一截身体
      let lastBody = this.list[this.list.length -1];
      let newBody = {x:lastBody.x,y:lastBody.y,type:0};
      // -- 在最后一截身体后面再添加
      switch (this.downKey) {
        case "ArrowUp":
          newBody.y -= 1;
          break;
        case "ArrowDown":
          newBody.y += 1;
          break;
        case "ArrowLeft":
          newBody.x -= 1;
          break;
        case "ArrowRight":
          newBody.x += 1;
          break;
        default:
          newBody.x += 1;
          break;
      }
      this.list.push(newBody);
      food.remove();
      food.render();
    }
    return true;
  }
  • 渲染蛇
 render() {
    // -- 渲染前先删除
    let snakeList = document.querySelectorAll(".snake");
    for (let i = snakeList.length -1;i>= 0;i--){
      let s = snakeList[i];
      this.oMap.removeChild(s);
    }
    // -- 遍历数组,创建蛇头和蛇身
    for (let temp of this.list) {
      // -- 创建元素
      let oSnake = document.createElement("div");
      // -- 设置样式
      if (temp.type === 1){
        // -- 蛇头
        oSnake.style.backgroundColor = this.headColor;
      }else
      {
        // -- 蛇身
        oSnake.style.backgroundColor = this.bodyColor;
      }
      oSnake.className = "snake";
      oSnake.style.position = "absolute"
      // -- 设置位置
      oSnake.style.left   = temp.x * this.width + "px";
      oSnake.style.top    = temp.y * this.height + "px";;
      oSnake.style.width  = this.width + "px";
      oSnake.style.height = this.height + "px";
      this.oMap.appendChild(oSnake);
    }
    let self = this;
    document.onkeydown = function (event) {
      self.downKey = event.key;
      console.log(event.key);
    }
  }
  • 让蛇开始进行游戏

创建一个定时器,定时器的时间就是蛇移动的速度

  // -- 开始贪吃蛇
  update(food){
    let self = this;
    this.timer = setInterval(function () {
      // -- 移动
      self.move(food)
      // -- 撞墙检测和食物检测
      let a = self.check(food);
      if (!a){
        return;
      }
      // -- 重新渲染蛇(吃到豆了)
      self.render()
    },300);


  }
posted @ 2020-08-13 15:45  cmg123  阅读(148)  评论(0)    收藏  举报