携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情 >>
前言
回忆最开始做编程的初心,找回曾经的热爱与激情
实现思路
贪吃蛇的玩儿法就是在一张有限大小的棋盘上,通过上下左右变换蛇移动的方向去吃掉随机位置出现的食物,蛇不可以撞墙,不能撞到自己。了解完玩儿法之后,我们就是一步步基于面向对象是去实现贪吃蛇.
创建棋盘与背景
背景的话,我们找一张好看的图片,作为背景即可
<style lang="less" scoped>
.home{
width: 100%;
height: 100%;
overflow: hidden;
background-image: url('~@/assets/bg1.jpeg');
background-size: cover;
background-position: center;
position: relative;
.pan{
width: 90%;
height: 90%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background: rgba(255, 255, 255, 0.5);
display: flex;
flex-wrap: wrap;
border-left: 1px solid #f4f4f4;
border-top: 1px solid #f4f4f4;
&>div{
width: 2%;
height: 2.5%;
border-right: 1px solid #f4f4f4;
position: relative;
border-bottom: 1px solid #f4f4f4;
}
}
}
</style>
棋盘的话,我们创建50*40一共2000个格子,使用vue 的话,就是v-for进行循环即可
<div class="home">
<div class="pan">
<template v-for="i in 40" >
<template v-for="k in 50" >
<div :key="`${i}_${k}`" :id="`${i}_${k}`"></div>
</template>
</template>
</div>
</div>
创建好的棋盘如下
接下来,就是基于面向对象去创建蛇了
创建蛇
首先,一开始我们让蛇的长度为3,从棋盘的左上角开始,那么蛇占据的坐标就是0,0,0,1,0,2
xyMap: { '1_1': true, '1_2': true, '1_3': true },
xy: [
{ x: 1, y: 1 },
{ x: 1, y: 2 },
{ x: 1, y: 3 }
]
接下来,就需要把蛇放进棋盘里,我们通过动态添加class的方式来实现,修改一下之前遍历棋盘的代码,通过判断是否存在来返回动态类名.head
<div :class="{head: judgeHead(x,y)}" :key="`${x}_${y}`" :id="`${x}_${y}`"></div>
judgeHead (x, y) {
return this.xyMap[`${x}_${y}`] ? 'head' : ''
}
放置食物小球
食物小球需要随机出现在棋盘上,并且不能出现在蛇身位置上。代码判断如下
//data
foodXy: null
// methods
food () {
// 不能放在蛇身上
let x, y
do {
x = Math.floor(Math.random() * 40) + 1
y = Math.floor(Math.random() * 50) + 1
} while (this.xyMap[x + '_' + y])
return { x, y }
}
created () {
this.foodXy = this.food()
},
此时,棋盘上就已经有了蛇和我们的食物
让蛇动起来,然后根据按键变化方向
首先我们需要监听方向键事件,这里为了方便,我们直接使用方向键返回的key
//data
direction: 'ArrowRight'
// mounted
// ArrowLeft ArrowRight ArrowDown ArrowUp
document.onkeydown = (e) => {
e.preventDefault()
this.direction = e.key
}
然后就是根据方向让蛇动起来,这里我们通过setInterval的方式实现的方式实现
setInterval(() => {
this.move()
}, 200)
move () {
const oldHead = this.xy[this.xy.length - 1] // 原来的位置
let newHead = { x: oldHead.x, y: oldHead.y } // 新的位置
if (this.direction === 'ArrowRight') {
newHead = { x: parseInt(oldHead.x), y: parseInt(oldHead.y) + 1 }
} else if (this.direction === 'ArrowDown') {
newHead = { x: parseInt(oldHead.x) + 1, y: parseInt(oldHead.y) }
} else if (this.direction === 'ArrowUp') {
const x = parseInt(oldHead.x) - 1 > 0 ? parseInt(oldHead.x) - 1 : 0
newHead = { x: x, y: parseInt(oldHead.y) }
} else if (this.direction === 'ArrowLeft') {
const y = parseInt(oldHead.y) - 1 > 0 ? parseInt(oldHead.y) - 1 : 0
newHead = { x: parseInt(oldHead.x), y }
}
this.xy.push(newHead)
this.$set(this.xyMap, newHead.x + '_' + newHead.y, true)
if (this.foodXy.x === newHead.x && this.foodXy.y === newHead.y) {
this.foodXy = this.food()
} else {
const xy = this.xy.shift()
delete this.xyMap[xy.x + '_' + xy.y]
}
}
这样,我们的蛇就动起来了,接下来,我们需要判断,蛇不可以撞墙,不能碰到自己,撞墙就是x,y坐标超出限制,撞到自己就是我们的newHead在xyMap中已存在,对吧,这样,我们优化一下move的代码
// 判断不能撞到自己
for (const i in this.xyMap) {
if (this.xyMap[newHead.x + '_' + newHead.y] === this.xyMap[i]) {
clearInterval(this.t)
}
}
this.xy.push(newHead)
....
// 判断不能撞墙
if (newHead.x + 1 > 40 || newHead.y + 1 > 50 || newHead.x < 0 || newHead.y < 0) {
clearInterval(this.t)
}
这样,我们就完成了贪吃蛇的基础功能了,可以移动,可以吃小球食物长大
下一篇,我们将继续完善贪吃的相关功能,把分值和速度以及暂停,移动动效加上,让我们的贪吃蛇更加的完美。下一篇完成后,将会把代码以代码片段的形式放出,欢迎大家试玩儿。