「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。
前情回顾
- 在前面两篇文章,我们实现了地图类和食物类相关的一些逻辑
- 今天我们来实现蛇类
Snake,蛇是本游戏的主角,所以它的属性和方法会相对而言复杂一点
实现蛇类
- 蛇类实现的功能主要有蛇的移动,吃食物,转弯
- 老规矩我们先来品鉴蛇类的代码
class Snake {
constructor() {
this.data = [
{ x: 6, y: 4, color: '#94dd94' },
{ x: 5, y: 4, color: 'white' },
{ x: 4, y: 4, color: 'white' },
{ x: 3, y: 4, color: 'white' },
{ x: 2, y: 4, color: 'white' },
];
this.direction = 'right';
// 保存最后一个数据,用于吃到食物的时候添加到蛇的末尾,达到变长的效果
this.lastData = {};
}
moveFn() {
// 最后一个元素的索引值
let i = this.data.length - 1;
// 保存最后一个数据,用于吃到食物的时候添加到蛇的末尾,达到变长的效果
this.lastData = {
x: this.data[i].x,
y: this.data[i].y,
color: this.data[i].color,
};
// 蛇的身体 从蛇尾开始,每走一下就是 后面的蛇的格子 移动到 前面的蛇的格子上
for (i; i > 0; i--) {
this.data[i].x = this.data[i - 1].x;
this.data[i].y = this.data[i - 1].y;
}
// 蛇的头部 是根据方向来移动的
switch (this.direction) {
case 'left':
this.data[0].x--;
break;
case 'right':
this.data[0].x++;
break;
case 'top':
this.data[0].y--;
break;
case 'bottom':
this.data[0].y++;
break;
default:
break;
}
}
turnFn(direction) {
let vertical = ['top', 'bottom'];
let horizontal = ['left', 'right'];
if (horizontal.includes(this.direction) && horizontal.includes(direction)) {
return false;
} else if (vertical.includes(this.direction) && vertical.includes(direction)) {
return false;
}
this.direction = direction;
return true;
}
eatFn() {
this.data.push(this.lastData);
}
}
-
如上代码所示,我们需要先初始化一个蛇的位置数据,以及它移动的初始方向
-
然后还初始化了一个 lastData,它用于存放蛇身体最后一个元素的坐标信息
- 为什么要这样做,我们暂时先不管这个问题
-
moveFn是负责控制蛇移动逻辑的函数- 每次移动我们都需要将蛇身体的最后一个元素,的坐标信息保存起来
- 蛇移动的本质,可以分为蛇身体移动和蛇头移动
- 蛇每走一步,对于蛇身体的每个元素来说,就是后面蛇身元素移动到了前面蛇身元素的位置上
- 所以移动蛇身体,只需要遍历每个蛇身元素,将前面的蛇身元素的坐标,赋值给后面的蛇身元素即可
- 那怎么移动蛇的头部呢?
- 其实也很简单,蛇头部的移动,都是按照方向 direction,向前移动一格
- 而向前移动一格,对应在是上下左右四个方向上,就是相应的横坐标或纵坐标,加 1 或者减 1,具体代码可以看上面
moveFn的实现
-
turnFn是控制蛇头部转向逻辑的函数- 这个很好实现,只需要更新方向值即可
- 但是有个边界条件需要判断
- 当前蛇移动的方向与改变的方向不能相同或者相反,也就是改变的方向只能与原方向垂直
- 为了表示转向是否成功,我们可以在这个函数最后返回一个布尔值
-
eatFn是实现蛇吃食物逻辑的函数- 这里可以解释上面说的那个 lastData 的问题了
- 当蛇吃掉一个食物时,蛇的身体长度应该变长一个单元格
- 因为每次移动,蛇身体都往前移动了一个单元格
- 所以当,蛇吃掉食物时,相当于在蛇尾添加了一个元素
- 只用在蛇移动前记录蛇身最后一个元素的信息,在蛇移动一个单元格后,将这个数据添加到蛇身数据末尾即可
小结
- 到这里蛇类的实现就已经完成了
- 为了不影响阅读体验,我会将这个 demo 的实现过程分为 4 篇文章来写,下一篇实现游戏主流程的控制类
最后
- 今天的分享就到这里,欢迎大家在评论区留言讨论
- 如果觉得文章写的还不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰