携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情 >>
前言
上一篇我们实现了贪吃蛇的核心功能,但是还是有很多小瑕疵,比如一进页面就开始了,而且不能暂停,速度不能调整等等,还有就是蛇移动的时候没有动效,非常不好看,这篇就是基于上一篇的代码,来实现一些更好看的移动效果
增加开始暂停结束按钮
首先,我们先增加一个按钮,通过定位的方式定在页面下方,水平居中,通过判断是开始还是暂停还是结束,显示不同的按钮
// template
<div class="start" v-if="!fail" :class="[pause?'pause':'']"></div>
<div class="end" v-else></div>
//data
...
pause: false,
fail: false
...
// less
.start{
width: 110px;
height: 37px;
position: absolute;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background-image: url("~@/assets/start.png");
background-size: contain;
background-position: center;
cursor: pointer;
}
.start.pause{
background-image: url("~@/assets/pause.png");
}
.end{
width: 110px;
height: 37px;
position: absolute;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background-image: url("~@/assets/restart.png");
background-size: contain;
background-position: center;
cursor: pointer;
}
这个时候,我们就把按钮放在页面下方了
接下来就是给按钮添加事件,能够开始和暂停,然后需要在move函数内判断失败的地方,处理重新开始逻辑,并给重新开始的按钮添加事件
start () {
if (!this.pause) {
clearInterval(this.t)
this.t = null
} else {
this.t = setInterval(() => {
this.move()
}, 2000)
}
},
// move 函数内判断失败
// 判断不能撞到自己
for (const i in this.xyMap) {
if (this.xyMap[newHead.x + '_' + newHead.y] === this.xyMap[i]) {
this.fail = true
this.showEnd = true
clearInterval(this.t)
}
}
// 判断不能撞墙
if (newHead.x + 1 > 40 || newHead.y + 1 > 50 || newHead.x < 0 || newHead.y < 0) {
this.fail = true
this.showEnd = true
clearInterval(this.t)
}
这里页面上失败的背景图出现了多个,这是因为我们设置css 背景图的时候没有指定background-repeat: no-repeat 这里,当background-size: contain;的时候,背景图会缩放到能完全展示的程度,进行展示,这时,假如无法铺满容器,就会出现重复,设置no-repeat可以指定背景图片不重复
速度调节
速度一成不变的运动给人带来的挑战和刺激都不太够,所以,我们需要设计一种机制,让吃的越多,蛇就跑的越快,那么我们该如何实现呢?蛇的运动是通过setinterval重复调用move函数实现的,也就是说,我们动态改变interval的刷新时间,就可以改变蛇的运动速度,如何实现呢?这里,每当蛇吃到食物的时候就会更新食物坐标,我们在设置食物的同时进行判断不就可以了吗?这样,我们就需要改写一下food函数
food () {
const inx = this.xy.length % 3
if (inx === 0) {
clearInterval(this.t)
this.t = null
this.pause = false
this.speed -= 50
this.start()
}
// 不能放在蛇身上
let x, y
.....
这里,我们判断蛇身长度对3取余,如果为0,说明又吃到了三个食物,然后我们就调整速度,让速度比之前快50ms,这样就实现了速度的变化,然后打开页面,发现哎?为什么直接就开始动了?我还没点开始啊?这是因为,我们在created的时候生成了食物坐标, food函数又被我们改写了,于是就会走进inx === 0的判断内,触发开始,这里,我们需要添加一个判断,就是蛇身坐标长度大于3
if (this.xy.length > 3) {
const inx = this.xy.length % 3
if (inx === 0) {
clearInterval(this.t)
this.t = null
this.pause = false
this.speed -= 50
this.start()
}
}
这样,就不会出现生成食物的同时触发开始了。 完整的代码以代码片段的形式呈现如下,欢迎试玩儿