在小程序上做一个贪食蛇小游戏主要是使用到了 Canvas 画布。所以要对里面几个主要的属性要有一个了解即 bindtouchstart(手指触摸动作开始) 、bindtouchmove(手指触摸后移动)、bindtouchend(手指触摸动作结束),这几个属性实现了对贪食蛇的控制。蛇动画使用 RequestAnimationFrame 生成。
布局
<canvas style="width:100%;height:100%;background:#ccc;" canvas-id='snake' bindtouchstart='TouchStart'
bindtouchmove='TouchMove' bindtouchend='TouchEnd'></canvas>
控制与动画
- 定义蛇头
var snake = {
x:0,
y:0,
color:'red',
w:10,
h:10
}
w、h 为头的长宽。
- 利用 bindtouchstart 获取手指刚触碰时的坐标
TouchStart:function(e){
StartX = e.touches[0].x;//手指刚开始触碰时的X
StartY = e.touches[0].y;
}
- 利用 bindtouchmove 获取手指移动时的坐标并判断出相对位置
TouchMove:function(e){
moveX = e.touches[0].x;
moveY = e.touches[0].y;
//移动位置与初始触碰位置差值
absX = moveX - StartX;
absY = moveY - StartY;
//当 X 轴坐标 > Y 轴坐标且大于0时,手指相对初始触碰点往右移动
if (Math.abs(absX) > Math.abs(absY) && absX > 0 ){
dircetion = 'right';
flag = 2;
console.log('右移');
}
if (Math.abs(absX) > Math.abs(absY) && absX < 0 && flag != 2){
dircetion = 'left';
console.log('左移');
flag = 0;
}
}
设立 Flag 标记用于判断上次操作与本次操作是否是两个方向相反的移动操作,当操作刚好为一组相反方向时不能对蛇头进行操作。
- bindtouchend 获取最终移动方向
TouchEnd:function(){
sdircetion = dircetion;
}
手指离开屏幕时触发,获取最终方向
- 获取蛇头移动坐标
switch (sdircetion) {
case 'right': snake.x += snake.w;
break;
case 'left': snake.x -= snake.w;
break;
case 'top': snake.y -= snake.h;
break;
case 'bottom': snake.y += snake.h;
break;
}
X 轴移就是在初始位置上 + 蛇头宽,Y 轴移动就是初始 + 蛇头高。
- 动画描绘
function drawSnake(obj) {
context.setFillStyle(obj.color);
context.beginPath();
context.rect(obj.x, obj.y, obj.w, obj.h);
context.closePath();
context.fill();
}
- 获取蛇身
snakeBodys.push({
x: snake.x,
y: snake.y,
w: 10,
h: 10,
color: 'blue'
})
if (snakeBodys.length > 4) {
snakeBodys.shift();//蛇身大于4时,移出一个位置
}
将蛇头移动前的一个坐标赋给蛇身,初始蛇身长度不超过4个。
- 在屏幕上随机生成食物
function rand(Max,Min){
return parseInt(Math.random()*Max-Min)+Min;
}
function Food(){
this.x = rand(windowsWidth-20,0);
this.y = rand(windowsHeight-20,0);
this.w = 10;
this.h = 10;
this.color = "rgb(" + rand(255, 0) + "," + rand(255, 0) + "," + rand(255, 0)+")";
}
- 判断是否与食物进行了碰撞
TBLR 分别指的是上下左右四个坐标,Y 轴向下为 + ; X 轴向右为 +
当满足 L1 < R2 && R1 > L2 && B1 > T2 && T1 < B2 蛇头与食物碰撞
function collision(Obj1,Obj2){
var left1 = Obj1.x;
var right1 = Obj1.x+Obj1.w;
var top1 = Obj1.y;
var bottom1 = Obj1.y+Obj1.h;
var left2 = Obj2.x;
var right2 = Obj2.x + Obj2.w;
var top2 = Obj2.y;
var bottom2 = Obj2.y + Obj2.h;
if(right1 > left2 && left1 < right2 && bottom1 > top2 && top1 < bottom2){
return true;
}
}
当碰撞到食物时 - 1,蛇身 + 1
if (collision(snake,food)){
collisionFlag = 0;
console.log('撞上');
foods.splice(i,1);
}
if (snakeBodys.length > 4) {
if (collisionFlag){
snakeBodys.shift();//蛇身碰到食物时不移除,否则移出每次移出一个保持长度不变
}