这是我用chat GPT 生成的一个vue3.2 运用setup语法糖生成的一个贪吃蛇小游戏
<template>
<div class="container">
<div
class="game-board"
:style="{ width: boardWidth + 'px', height: boardHeight + 'px' }"
>
<div
class="snake"
v-for="(snake, index) in snakes"
:key="index"
:style="{ left: snake.x + 'px', top: snake.y + 'px' }"
></div>
<div
class="food"
:style="{ left: food.x + 'px', top: food.y + 'px' }"
></div>
</div>
<div class="game-info">
<div>得分: {{ score }}</div>
<div v-if="gameOver">游戏结束!</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted } from "vue";
const boardWidth = ref(500); // 游戏界面的宽度
const boardHeight = ref(500); // 游戏界面的高度
const snakeSize = 10; //蛇的大小
const snakeSpeed = 100; //移动速度
const direction = ref("right"); //蛇的方向
const snakes = reactive([{ x: 0, y: 0 }]); //蛇的位置
const food = reactive({ x: 0, y: 0 }); //食物的位置
const score = ref(0); //得分
const gameOver = ref(false); //游戏是否结束
/**
* init 函数用于初始化游戏,包括生成食物和设置定时器来处理蛇的移动
*/
const init = () => {
createFood();
setInterval(() => {
move();
}, snakeSpeed);
};
/**
* createFood 函数用于生成食物的位置
*/
const createFood = () => {
const x =
Math.floor(Math.random() * (boardWidth.value / snakeSize)) * snakeSize;
const y =
Math.floor(Math.random() * (boardHeight.value / snakeSize)) * snakeSize;
food.x = x;
food.y = y;
};
/**
* move 函数用于处理蛇的移动,包括蛇头的位置、蛇的碰撞检测、蛇身的增长和移动、得分的更新等
*/
const move = () => {
if (gameOver.value) return;
const head = snakes[snakes.length - 1];
const x =
head.x +
(direction.value === "right"
? snakeSize
: direction.value === "left"
? -snakeSize
: 0);
const y =
head.y +
(direction.value === "down"
? snakeSize
: direction.value === "up"
? -snakeSize
: 0);
const newHead = { x, y };
if (isCollision(newHead)) {
gameOver.value = true;
return;
}
snakes.push(newHead);
if (newHead.x === food.x && newHead.y === food.y) {
createFood();
score.value += 10;
} else {
snakes.shift();
}
};
/**
* 函数用于判断蛇是否与边界或自身碰撞;
* @param head
*/
const isCollision = (head: any) => {
return (
head.x < 0 ||
head.y < 0 ||
head.x >= boardWidth.value ||
head.y >= boardHeight.value ||
snakes.some((snake) => snake.x === head.x && snake.y === head.y)
);
};
/**
* handleKeyDown 函数用于处理键盘按键事件,根据按键来改变蛇的方向
*/
const handleKeyDown = (event: any) => {
switch (event.keyCode) {
case 37:
if (direction.value !== "right") {
direction.value = "left";
}
break;
case 38:
if (direction.value !== "down") {
direction.value = "up";
}
break;
case 39:
if (direction.value !== "left") {
direction.value = "right";
}
break;
case 40:
if (direction.value !== "up") {
direction.value = "down";
}
break;
default:
break;
}
};
/**
* onMounted 和 onUnmounted 函数用于在组件挂载和销毁时绑定和解绑键盘事件
*/
onMounted(() => {
init();
window.addEventListener("keydown", handleKeyDown);
});
onUnmounted(() => {
window.removeEventListener("keydown", handleKeyDown);
});
</script>
<style lang="scss" scoped>
.container {
display: flex;
justify-content: center;
align-items: center;
height: 50vh;
background-color: #f6f6f6;
}
.game-board {
position: relative;
background-color: #fff;
border: 1px solid #ddd;
}
.snake {
position: absolute;
width: 10px;
height: 10px;
background-color: #333;
}
.food {
position: absolute;
width: 10px;
height: 10px;
background-color: #f00;
}
.game-info {
margin-top: 20px;
text-align: center;
}
</style>