vue写的贪吃蛇(完整源码)

vue写的贪吃蛇(完整源码)_第1张图片
vue写的贪吃蛇(完整源码)_第2张图片
vue写的贪吃蛇(完整源码)_第3张图片
vue写的贪吃蛇(完整源码)_第4张图片

整个代码页面:

<template>
  <div class="can">
    
    <div class="content" v-if="show">
      <div class="snake-grassland">
        <div
          class="snake"
          v-for="(item, index) in snake"
          :key="`snake${index}`"
          :style="location(item.x, item.y)"
        >div>
        <div
          class="food"
          v-for="(item, index) in foods"
          :key="`food${index}`"
          :style="location(item.x, item.y)"
        >div>
      div>
      <div class="right">
        <div class="content-title">
          <div class="username">用户名:{{ form.name }}div>
          <div class="score">得分:{{ score }}div>
        div>
        <div class="button">
          <el-button @click="stopGame" type="warning">暂停游戏el-button>
          <el-button type="primary" @click="continueGame">继续游戏el-button>
        div>
      div>

      
      <div class="fail" v-if="showFail">
        <div class="fail-title">游戏结束!div>
        <div class="total-score">score:{{ score }}div>
        <el-button @click="reStart" type="danger">重新开始el-button>
        <el-button @click="exitGame" type="danger">退出游戏el-button>
      div>
    div>

    
    <div class="login" v-if="showLogin">
      
      <el-form
        ref="form"
        :model="form"
        :rules="rules"
        label-width="70px"
        class="ruleForm"
      >
        <el-form-item label="昵称" prop="name">
          <el-input v-model="form.name" placeholder="请输入昵称">el-input>
        el-form-item>
      el-form>
      <el-button type="primary" @click="active" :disabled="btnState == false"
        >开始游戏el-button
      >
    div>
  div>
template>
<script>
export default {
  // snake-grassland 50*50的格子
  data() {
    return {
      form: {
        name: "",
      },
      rules: {
        name: [
          {
            required: true,
            message: "请输入昵称,长度在 3 到 20 个字符",
            trigger: "blur",
          },
          { min: 3, max: 5, message: "长度在 3 到 20 个字符", trigger: "blur" },
        ],
      },
      name: "", // 玩家名
      score: 0, // 得分
      showLogin: true,
      show: false,
      showFail: false,
      foods: [],
      direction: 3, //初始方向向右
      timer: null,
      snake: [
        { x: 0, y: 0 }, //蛇尾
        { x: 1, y: 0 },
        { x: 2, y: 0 }, //蛇头
      ], //(x, y) 组成蛇的每一块儿的位置
      xStep: 1,
      yStep: 1,
    };
  },
  computed: {
    btnState() {
      return this.form.name !== "";
    },
  },
  created() {
    // 随机生成3个食物
    this.foods = this.generateFoods(3);
  },
  mounted() {
    window.addEventListener("keyup", (event) => {
      // event.key = ArrowUp 上
      switch (event.key) {
        case "ArrowUp":
          this.direction = 0;
          this.snakeMove();
          break;
        case "ArrowDown":
          this.direction = 1;
          this.snakeMove();
          break;
        case "ArrowLeft":
          this.direction = 2;
          this.snakeMove();
          break;
        case "ArrowRight":
          this.direction = 3;
          this.snakeMove();
          break;
        default:
          break;
      }
    });
  },
  methods: {
    // 暂停游戏
    stopGame() {
      clearInterval(this.timer); //清除了定时器
      this.timer = null; //清除了timer的内存占用
    },
    //继续游戏
    continueGame() {
      this.timer = setInterval(() => {
        this.snakeMove();
      }, 200);
    },

    // 重新开始
    reStart() {
      this.showFail = false;

      this.snake = [
        { x: 0, y: 0 },
        { x: 1, y: 0 },
        { x: 2, y: 0 },
      ]; //(x, y) 组成蛇的每一块儿的位置
      this.foods = this.generateFoods(3);
      this.direction = 3;
      this.score = 0;
      this.timer = setInterval(() => {
        this.snakeMove();
      }, 200);
    },
    //退出游戏
    exitGame() {
      this.showFail = false;
      this.showLogin = !this.showLogin;
      this.show = !this.show;
      this.form.name = "";
      this.score = 0;
      clearInterval(this.timer); //清除了定时器
      this.timer = null; //清除了timer的内存占用
    },
    //碰撞检测是否吃到食物
    isEat() {
      // 小蛇移动就是除头部以外的部分向前移动一个身位,即前一个状态的最后一个身位丢弃
      let head = this.snake[this.snake.length - 1];
      let isEat = false;
      // 消除吃掉的食物
      this.foods = this.foods.filter((food) => {
        if (head.x === food.x && head.y === food.y) {
          isEat = true;
          this.eat(); // 加长蛇身
          //碰撞一次加10分
          this.score = this.score + 10;
          return false;
        }
        return true;
      });
      // 添加一个新食物,使食物总量保持不变
      if (isEat) {
        this.foods.push(...this.generateFoods(1));
      }
    },
    // 吃食物
    eat() {
      let tail = this.snake[0];
      let xStep = 0,
        yStep = 0;

      if (this.direction === 0) {
        yStep = -1;
      } else if (this.direction === 1) {
        yStep = 1;
      } else if (this.direction === 2) {
        xStep = -1;
      } else if (this.direction === 3) {
        xStep = 1;
      }
      //添加到数组的开头
      this.snake.unshift({ x: tail.x - xStep, y: tail.y - yStep });
    },
    // 开始游戏
    active() {
      this.show = true;
      this.showLogin = false;

      if (this.form.name.length <= 2) {
        this.showLogin = !this.showLogin;
        this.show = !this.show;
        return alert("用户名不可小于三位字符");
      } else {
        this.snake = [
          { x: 0, y: 0 },
          { x: 1, y: 0 },
          { x: 2, y: 0 },
        ]; //(x, y) 组成蛇的每一块儿的位置
        this.foods = this.generateFoods(3);
        this.direction = 3;
        this.timer = setInterval(() => {
          this.snakeMove();
        }, 200);
      }
    },

    // 随机生成食物
    generateFoods(total) {
      const foods = [];
      for (let i = 0; i < total; i++) {
        //食物的随机x轴坐标,也就是第几行
        const foodX = Math.floor(Math.random() * 50);
        //食物的随机x轴坐标,也就是第几列
        const foodY = Math.floor(Math.random() * 50);
        foods.push({ x: foodX, y: foodY });
      }
      return foods;
    },
    // 获取位置
    location(x, y) {
      return {
        left: x * 10 + "px",
        top: y * 10 + "px",
      };
    },
    //蛇开始动 判断是否超出界限 head表示贪吃蛇的头部,当头部超过地图的范围时
    //先获取下一步数据,坐标值,判断坐标值是否非法,如果不非法就可以动了
    move(xStep, yStep) {
      //定义蛇的头部位置
      let head = this.snake[this.snake.length - 1];
      //需要监听蛇头的方向而且判断
      if (
        (this.direction == 2 && head.x <= 0) ||
        (this.direction == 0 && head.y <= 0) ||
        (this.direction == 3 && head.x >= 49) ||
        (this.direction == 1 && head.y >= 49)
      ) {
        clearInterval(this.timer);
        this.timer = null;
        this.endGame();
      }  else {
        this.snake.push({ x: head.x + xStep, y: head.y + yStep });
        this.snake.shift();
      }
     
    },
    //结束游戏
    endGame() {
      this.showFail = true;
    },
    // 改变方向
    changeDirection(direction) {
      this.direction = direction;
      this.snakeMove();
    },
    // 控制蛇的方向
    snakeMove() {
      switch (this.direction) {
        case 0: // 上  网上移动就是列的改变,列减1行
          this.move(0, -1);
          break;
        case 1: // 下
          this.move(0, 1);
          break;
        case 2: // 左
          this.move(-1, 0);
          break;
        case 3: // 右
          this.move(1, 0);
          break;
        default:
          break;
      }
      this.isEat();
    },
  },
};
script>
<style scope="lang">
* {
  padding: 0;
  margin: 0;
}
.can {
  height: 500px;
}
.content {
  width: 750px;
  height: 500px;

  margin-left: 520px;
  position: relative;
  border: 1px solid gainsboro;
  display: flex;
}
.snake-grassland {
  position: relative;
  background-color: #52af4a;
  width: 500px;
  height: 500px;
}
.snake-grassland .snake {
  background-color: #000;
  position: absolute;
  border: 1px solid #ccc;
  box-sizing: border-box;
  width: 10px;
  height: 10px;
}

.snake-grassland .food {
  background-color: red;
  position: absolute;
  border: 1px solid #ccc;
  box-sizing: border-box;
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.right {
  position: absolute;
  width: 200px;
  margin: 150px 500px;
  text-align: left;
  padding: 10px;
}
.button {
  display: flex;
  justify-content: space-evenly;
  margin: 20px 0;
}

.login {
  position: absolute;
  width: 500px;
  height: 500px;
  background: linear-gradient(#d5ddbb, transparent) no-repeat,
    url("~@/img/贪吃蛇.jpg") no-repeat;
  background-size: auto 500px, 500px 640px;
  left: 520px;
}
.ruleForm {
  padding: 180px 60px 20px;
}
.fail {
  position: absolute;
  width: 400px;
  height: 300px;
  background-color: rgb(207, 202, 224);
  top: 150px;
  left: 50px;
  border: 1px solid black;
  border-radius: 25px;
}
.fail-title {
  margin: 20px auto;
  font-size: 28px;
  font-weight: bold;
}
.total-score {
  margin: 40px auto 20px;
  font-size: 28px;
  font-weight: bold;
}
style>

你可能感兴趣的:(vue,vue,javascript)