本系列是作者自学实践过程的记录
本文是关于贪吃蛇的滑动控制
有问题欢迎讨论
一、滑动控制
1.1 设计思想
在之间的滑动控制中,我们使用的代码过于复杂,这里我们要有模块化设计思想,即将判断函数和滑动控制函数分开,进一步理清设计思路。
前面我们提到了,根据tapstart和tapend获取触摸开始和触摸结束的坐标,并分别计算出两个点之间横纵距离的差值。
水平方向移动:
- 若横坐标差值绝对值大于纵坐标差值绝对值,则当前移动是沿水平方向
- 若此时横坐标差值为正,则沿正反向,即向左(自定义坐标系)
垂直方向移动:
- 若纵坐标差值绝对值大于横坐标差值绝对值,则当前移动是沿垂直方向
- 若此时纵坐标差值为正,则沿正反向,即向下(自定义坐标系)
1.2 代码实现
于是,我们可以这样设计函数:
// 手指触摸结束函数
tapend:function(e){
// 获取滑动距离,当手指划出屏幕不再赋值
var distance_x = (this.data.end_x > 0)? this.data.end_x - this.data.start_x : 0
var distance_y = (this.data.end_y > 0)? this.data.end_y - this.data.start_y : 0
// 简单判断滑动方向,已注释
// 向右滑动
// if(Math.abs(distance_x) > Math.abs(distance_y) && distance_x > 0){
// console.log("向右滑动")
// }
// else if(Math.abs(distance_x) > Math.abs(distance_y) && distance_x < 0){
// console.log("向左滑动")
// }
// else if(Math.abs(distance_x) < Math.abs(distance_y) && distance_y < 0){
// console.log("向上滑动")
// }
// else if(Math.abs(distance_x) < Math.abs(distance_y) && distance_y > 0){
// console.log("向下滑动")
// }
// else{
// console.log("点击但未滑动")
// }
// 使用面向对象方法进行滑动判断
if(Math.abs(distance_x) > 5 || Math.abs(distance_y) > 5){
var direction
if(Math.abs(distance_x) > Math.abs(distance_y)){
direction = this.judge(1,distance_x)
}
else{
direction = this.judge(0,distance_y)
}
console.log(direction)
}
console.log("触摸结束")
},
// 判断方向的函数,这里参数一个是布尔值,1表示水平方向,0表示垂直方向,distance是传回的距离值
judge:function(judge,distance){
// 左右滑动
if(judge)
return distance > 0 ? "right":"left"
// 上下滑动
else
return distance > 0 ? "down":"up"
}
1.3 效果展示:
1.4 整体赋值
我们这里输出的只是tapend函数的局部变量,我们需要使用setData对全局变量进行数据绑定。
这里我们选择使用switch函数代替不断的if语句,不过需要注意的是这里要对局部变量和全局变量进行一个判断,因为蛇不可以直接掉头,例如不可以直接由向左改变为向右。
switch(direction){
case "left":
if(this.data.direction == "right")
return;
break;
case "right":
if(this.data.direction == "left")
return;
break;
case "down":
if(this.data.direction == "up")
return;
break;
case "up":
if(this.data.direction == "down")
return;
break;
}
this.setData({
direction:direction,
start_x:0,
start_y:0,
end_x:0,
end_y:0
})
二、setInterval函数
这里有一个新的知识点,即setInterval(function,time)方法,执行这个代码块,那么小程序就会依据给定的时间间隔,不断执行function函数,直到执行了clearInterval()函数。
我们可以在后面的课程中使用这个函数对蛇的移动和更新进行设计。
代码如下:
// 移动函数
move:function(){
this.data.timer = setInterval(function() {
},400)
},
三、碰撞检测
视觉上碰撞检测需要判断是小蛇的头是否碰到操场或者碰到自己的身体。
逻辑上碰撞检测即小蛇的头的坐标是否和某些坐标重合,这时候便是游戏失败。
3.1 游戏介绍碰撞检测
当碰撞发生时,我们只需要将移动速度中的timer进行关闭就可以暂停游戏,再输出对应的游戏结束效果即可。
碰撞代码如下:
// 游戏状态
check_Game:function(){
// 获取小蛇数据
var snake = this.data.snake
var len = this.data.snake.length
var snake_head = arr[len-1];
// 小蛇超过了操场边框
if(snake_head[0] < 0 || snake_head[0] >= this.data.rows ||
snake_head[1] < 0 || snake_head[1] >= this.data.cols){
clearInterval(this.data.timer)
}
// 小蛇碰到了自己
for(var i=0;i<len-1;i++){
if(snake_head[0] == arr[i][0] && snake_head[1] == arr[i][1]){
clearInterval(this.data.timer)
}
}
}
3.2 食物碰撞检测
当小蛇碰撞到食物时,身体应该变长,这里就可以用到shift和unshift函数对数组头部进行添加和删除,类似于栈的push和pop函数。
代码如下:
// 小蛇碰撞到食物
if(snake_head[0] == this.data.food[0] && snake_head[1] == this.data.food[1]){
// snakeTAIL专门用来添加蛇的长度
arr.unshift(snakeTAIL)
this.setData({
score:this.data.score + 10
})
// 再创建一个食物
this.initFood()
// 这里应该再添加统计历史最高分的函数
}