怎么用Vue做个贪吃蛇游戏

发布时间:2022-11-25 17:09:09 作者:iii
来源:亿速云 阅读:156

怎么用Vue做个贪吃蛇游戏

贪吃蛇是一款经典的游戏,相信很多人都玩过。本文将详细介绍如何使用Vue.js框架来制作一个简单的贪吃蛇游戏。我们将从项目初始化开始,逐步实现游戏的各个功能模块,包括蛇的移动、食物的生成、碰撞检测等。

1. 项目初始化

首先,我们需要创建一个新的Vue项目。如果你还没有安装Vue CLI,可以通过以下命令进行安装:

npm install -g @vue/cli

安装完成后,使用Vue CLI创建一个新的项目:

vue create snake-game

在项目创建过程中,选择默认配置即可。创建完成后,进入项目目录并启动开发服务器

cd snake-game
npm run serve

2. 项目结构

在开始编写代码之前,我们先来看一下项目的目录结构:

snake-game/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── App.vue
│   └── main.js
├── package.json
└── ...

我们将主要在src/components/目录下创建游戏相关的组件。

3. 创建游戏组件

首先,我们在src/components/目录下创建一个新的组件SnakeGame.vue

<template>
  <div class="snake-game">
    <div class="game-board">
      <div v-for="(row, y) in grid" :key="y" class="row">
        <div
          v-for="(cell, x) in row"
          :key="x"
          class="cell"
          :class="{ snake: cell === 1, food: cell === 2 }"
        ></div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      grid: [],
      gridSize: 20,
      snake: [{ x: 10, y: 10 }],
      direction: { x: 0, y: 0 },
      food: { x: 5, y: 5 },
    };
  },
  created() {
    this.initializeGrid();
    this.placeFood();
  },
  methods: {
    initializeGrid() {
      this.grid = Array.from({ length: this.gridSize }, () =>
        Array.from({ length: this.gridSize }, () => 0)
      );
    },
    placeFood() {
      let x, y;
      do {
        x = Math.floor(Math.random() * this.gridSize);
        y = Math.floor(Math.random() * this.gridSize);
      } while (this.grid[y][x] !== 0);
      this.food = { x, y };
      this.grid[y][x] = 2;
    },
  },
};
</script>

<style scoped>
.snake-game {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.game-board {
  display: grid;
  grid-template-rows: repeat(20, 20px);
  grid-template-columns: repeat(20, 20px);
  gap: 1px;
  background-color: #333;
}

.row {
  display: flex;
}

.cell {
  width: 20px;
  height: 20px;
  background-color: #222;
}

.snake {
  background-color: lime;
}

.food {
  background-color: red;
}
</style>

在这个组件中,我们定义了一个20x20的网格,用于表示游戏区域。蛇和食物的位置分别用12来表示。initializeGrid方法用于初始化网格,placeFood方法用于随机生成食物的位置。

4. 实现蛇的移动

接下来,我们需要实现蛇的移动功能。我们将在SnakeGame.vue组件中添加一个moveSnake方法,并在mounted钩子中使用setInterval来定期调用这个方法。

<script>
export default {
  data() {
    return {
      grid: [],
      gridSize: 20,
      snake: [{ x: 10, y: 10 }],
      direction: { x: 0, y: 0 },
      food: { x: 5, y: 5 },
      interval: null,
    };
  },
  created() {
    this.initializeGrid();
    this.placeFood();
  },
  mounted() {
    this.interval = setInterval(this.moveSnake, 200);
    window.addEventListener('keydown', this.changeDirection);
  },
  beforeDestroy() {
    clearInterval(this.interval);
    window.removeEventListener('keydown', this.changeDirection);
  },
  methods: {
    initializeGrid() {
      this.grid = Array.from({ length: this.gridSize }, () =>
        Array.from({ length: this.gridSize }, () => 0)
      );
    },
    placeFood() {
      let x, y;
      do {
        x = Math.floor(Math.random() * this.gridSize);
        y = Math.floor(Math.random() * this.gridSize);
      } while (this.grid[y][x] !== 0);
      this.food = { x, y };
      this.grid[y][x] = 2;
    },
    moveSnake() {
      const head = { ...this.snake[0] };
      head.x += this.direction.x;
      head.y += this.direction.y;

      if (
        head.x < 0 ||
        head.x >= this.gridSize ||
        head.y < 0 ||
        head.y >= this.gridSize ||
        this.grid[head.y][head.x] === 1
      ) {
        this.gameOver();
        return;
      }

      this.snake.unshift(head);

      if (head.x === this.food.x && head.y === this.food.y) {
        this.placeFood();
      } else {
        const tail = this.snake.pop();
        this.grid[tail.y][tail.x] = 0;
      }

      this.updateGrid();
    },
    updateGrid() {
      this.initializeGrid();
      this.snake.forEach((segment) => {
        this.grid[segment.y][segment.x] = 1;
      });
      this.grid[this.food.y][this.food.x] = 2;
    },
    changeDirection(event) {
      switch (event.key) {
        case 'ArrowUp':
          if (this.direction.y === 0) {
            this.direction = { x: 0, y: -1 };
          }
          break;
        case 'ArrowDown':
          if (this.direction.y === 0) {
            this.direction = { x: 0, y: 1 };
          }
          break;
        case 'ArrowLeft':
          if (this.direction.x === 0) {
            this.direction = { x: -1, y: 0 };
          }
          break;
        case 'ArrowRight':
          if (this.direction.x === 0) {
            this.direction = { x: 1, y: 0 };
          }
          break;
      }
    },
    gameOver() {
      clearInterval(this.interval);
      alert('Game Over!');
    },
  },
};
</script>

moveSnake方法中,我们首先计算蛇头的新位置。如果新位置超出边界或与蛇身碰撞,则游戏结束。如果蛇头碰到食物,则蛇身增长,并重新生成食物。否则,蛇尾缩短。

updateGrid方法用于更新网格,将蛇和食物的位置反映到网格中。

changeDirection方法用于根据键盘输入改变蛇的移动方向。

5. 添加游戏控制

为了让玩家能够控制蛇的移动,我们需要监听键盘事件。我们在mounted钩子中添加了键盘事件监听器,并在beforeDestroy钩子中移除监听器。

<script>
export default {
  // ... 其他代码
  mounted() {
    this.interval = setInterval(this.moveSnake, 200);
    window.addEventListener('keydown', this.changeDirection);
  },
  beforeDestroy() {
    clearInterval(this.interval);
    window.removeEventListener('keydown', this.changeDirection);
  },
  methods: {
    // ... 其他方法
    changeDirection(event) {
      switch (event.key) {
        case 'ArrowUp':
          if (this.direction.y === 0) {
            this.direction = { x: 0, y: -1 };
          }
          break;
        case 'ArrowDown':
          if (this.direction.y === 0) {
            this.direction = { x: 0, y: 1 };
          }
          break;
        case 'ArrowLeft':
          if (this.direction.x === 0) {
            this.direction = { x: -1, y: 0 };
          }
          break;
        case 'ArrowRight':
          if (this.direction.x === 0) {
            this.direction = { x: 1, y: 0 };
          }
          break;
      }
    },
  },
};
</script>

6. 游戏结束处理

当蛇撞到墙壁或自身时,游戏结束。我们在moveSnake方法中添加了游戏结束的逻辑,并在游戏结束时弹出一个提示框。

<script>
export default {
  // ... 其他代码
  methods: {
    // ... 其他方法
    gameOver() {
      clearInterval(this.interval);
      alert('Game Over!');
    },
  },
};
</script>

7. 完善游戏界面

最后,我们可以为游戏添加一些样式和交互效果,使其更加美观和易用。例如,我们可以为游戏区域添加边框,为蛇和食物添加动画效果等。

<style scoped>
.snake-game {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #000;
}

.game-board {
  display: grid;
  grid-template-rows: repeat(20, 20px);
  grid-template-columns: repeat(20, 20px);
  gap: 1px;
  background-color: #333;
  border: 2px solid #fff;
}

.row {
  display: flex;
}

.cell {
  width: 20px;
  height: 20px;
  background-color: #222;
}

.snake {
  background-color: lime;
  border-radius: 50%;
}

.food {
  background-color: red;
  border-radius: 50%;
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
</style>

8. 总结

通过以上步骤,我们成功地使用Vue.js实现了一个简单的贪吃蛇游戏。我们创建了一个20x20的网格,实现了蛇的移动、食物的生成、碰撞检测等功能。我们还添加了键盘事件监听器,使玩家能够控制蛇的移动。

当然,这个游戏还有很多可以改进的地方,例如增加难度级别、添加音效、优化界面等。希望本文能够帮助你入门Vue.js游戏开发,并激发你进一步探索的兴趣。

9. 完整代码

以下是SnakeGame.vue组件的完整代码:

<template>
  <div class="snake-game">
    <div class="game-board">
      <div v-for="(row, y) in grid" :key="y" class="row">
        <div
          v-for="(cell, x) in row"
          :key="x"
          class="cell"
          :class="{ snake: cell === 1, food: cell === 2 }"
        ></div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      grid: [],
      gridSize: 20,
      snake: [{ x: 10, y: 10 }],
      direction: { x: 0, y: 0 },
      food: { x: 5, y: 5 },
      interval: null,
    };
  },
  created() {
    this.initializeGrid();
    this.placeFood();
  },
  mounted() {
    this.interval = setInterval(this.moveSnake, 200);
    window.addEventListener('keydown', this.changeDirection);
  },
  beforeDestroy() {
    clearInterval(this.interval);
    window.removeEventListener('keydown', this.changeDirection);
  },
  methods: {
    initializeGrid() {
      this.grid = Array.from({ length: this.gridSize }, () =>
        Array.from({ length: this.gridSize }, () => 0)
      );
    },
    placeFood() {
      let x, y;
      do {
        x = Math.floor(Math.random() * this.gridSize);
        y = Math.floor(Math.random() * this.gridSize);
      } while (this.grid[y][x] !== 0);
      this.food = { x, y };
      this.grid[y][x] = 2;
    },
    moveSnake() {
      const head = { ...this.snake[0] };
      head.x += this.direction.x;
      head.y += this.direction.y;

      if (
        head.x < 0 ||
        head.x >= this.gridSize ||
        head.y < 0 ||
        head.y >= this.gridSize ||
        this.grid[head.y][head.x] === 1
      ) {
        this.gameOver();
        return;
      }

      this.snake.unshift(head);

      if (head.x === this.food.x && head.y === this.food.y) {
        this.placeFood();
      } else {
        const tail = this.snake.pop();
        this.grid[tail.y][tail.x] = 0;
      }

      this.updateGrid();
    },
    updateGrid() {
      this.initializeGrid();
      this.snake.forEach((segment) => {
        this.grid[segment.y][segment.x] = 1;
      });
      this.grid[this.food.y][this.food.x] = 2;
    },
    changeDirection(event) {
      switch (event.key) {
        case 'ArrowUp':
          if (this.direction.y === 0) {
            this.direction = { x: 0, y: -1 };
          }
          break;
        case 'ArrowDown':
          if (this.direction.y === 0) {
            this.direction = { x: 0, y: 1 };
          }
          break;
        case 'ArrowLeft':
          if (this.direction.x === 0) {
            this.direction = { x: -1, y: 0 };
          }
          break;
        case 'ArrowRight':
          if (this.direction.x === 0) {
            this.direction = { x: 1, y: 0 };
          }
          break;
      }
    },
    gameOver() {
      clearInterval(this.interval);
      alert('Game Over!');
    },
  },
};
</script>

<style scoped>
.snake-game {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #000;
}

.game-board {
  display: grid;
  grid-template-rows: repeat(20, 20px);
  grid-template-columns: repeat(20, 20px);
  gap: 1px;
  background-color: #333;
  border: 2px solid #fff;
}

.row {
  display: flex;
}

.cell {
  width: 20px;
  height: 20px;
  background-color: #222;
}

.snake {
  background-color: lime;
  border-radius: 50%;
}

.food {
  background-color: red;
  border-radius: 50%;
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
</style>

10. 运行游戏

将上述代码保存为SnakeGame.vue文件,并在App.vue中引入该组件:

<template>
  <div id="app">
    <SnakeGame />
  </div>
</template>

<script>
import SnakeGame from './components/SnakeGame.vue';

export default {
  components: {
    SnakeGame,
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

然后运行项目:

npm run serve

打开浏览器,访问http://localhost:8080,即可开始玩贪吃蛇游戏。

11. 结语

通过本文的学习,你应该已经掌握了如何使用Vue.js制作一个简单的贪吃蛇游戏。希望你能在此基础上继续探索,添加更多有趣的功能,提升游戏的体验。祝你编程愉快!

推荐阅读:
  1. 用JS实现的贪吃蛇游戏
  2. 用html5如何制作贪吃蛇游戏

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue

上一篇:CSS渐变锯齿问题怎么解决

下一篇:Java顺序表和链表如何实现

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》