利用Canvas+js实现贪吃蛇(3)

Author Avatar
Peipei Wong 6月 23, 2016
  • 在其它设备中阅读本文章

想了想,蛇向下走的时候按上键,如果直接将蛇头变蛇身,好像不符合常理,所以处理这种情况,应当做蛇头碰到蛇身。。
另外,实现蛇头碰蛇身的功能
界面就不美化了。。。
下一步就是封装成面向对象的插件了。。。

```js
window.onload = function() {
var canvas = document.getElementById(‘myCanvas’),
span_score = document.getElementById(‘score’),
context = canvas.getContext(‘2d’),
maxNumber = 630, // 最大长宽,这里的画布是正方形
stride = 15, //每个小方块的长宽,
snakeLength = 1, //蛇身长度
snake = new Array(), //蛇身数组
speed = 300, // 移动速度
direct = 37, //移动方向
food_x = 31, //食物的坐标 可以改为object对象
food_y = 121,
score = 0, // 得分
timer; //setInterval

init();
update();

document.onkeydown=function(event) {
clearInterval(timer);
// 37:左 38:上 39:右 40:下
// 改为以下 内容 ,处理反方向的bug
var newDir = (event.keyCode > 36 && event.keyCode < 41) ? event.keyCode : 40;
// 处理反方向
if(Math.abs(direct - newDir) == 2) {
alert(“头碰到身体了,Game over!”);
} else {
direct = newDir;
update();
}
}
// 随机生成食物
function randFood() {
do{
food_x = Math.ceil(Math.random() 40 + 2) 15 + 1;
food_y = Math.ceil(Math.random() 40 + 2) 15 + 1;
}while(isBody(food_x,food_y));

}
// 判断食物是否在蛇的身体上
function isBody(param_x,param_y) {
// 判断蛇头是否碰到了蛇身
for (var i = 0; i < snakeLength - 1; i++) {
if(snake[i].x === param_x && snake[i].y === param_y) {
return true;
}
}
// 判断食物是否在蛇的身体上
var snakeLast = snake[snakeLength-1];
if(snakeLast) {
if(snakeLast.x === param_x && snakeLast.y === param_y) {
return true;
}
}
return false;
}
// 定时更新画面
function update() {
timer = setInterval(function() {
// 到达边界
if(snake[0].x < 1 || snake[0].y < 1 || snake[0].x > maxNumber || snake[0].y > maxNumber) {
clearInterval(timer);
alert(‘出边界了,Game over!’);
} else {
// 重新绘制贪吃蛇
drawSnake();

          // 检测是否吃到食物
          checkFood();
      }
  },speed)

}

// 绘制贪吃蛇
function drawSnake() {
// 擦出蛇尾巴
var snakeLast = snake[snakeLength-1],
snakeHead = snake[0];
clear(snakeLast.x,snakeLast.y);

  // 删除尾巴
  snake.pop();
  // 增加头
  addHead(snakeHead.x,snakeHead.y);

}
// 增加头
function addHead(param_x,param_y) {
var newX,newY;
// 37:左 38:上 39:右 40:下
switch (direct) {
case 37:
newX = param_x - stride;
newY = param_y;
break;
case 38:
newY = param_y - stride;
newX = param_x;
break;
case 39:
newX = param_x + stride;
newY = param_y;
break;
case 40:
newY = param_y + stride;
newX = param_x;
break;
}

  // 增加蛇头
  // 检测头是否 碰到身体
  if(snakeLength > 3 && isBody(newX,newY)) {
      clearInterval(timer);
      alert("头碰到身体了,Game over!");
  } else {
      snake.unshift({x:newX,y:newY});
      draw(snake[0].x,snake[0].y);
  }

}

// 检测是否吃到食物
function checkFood() {
if(snake[0].x === food_x && snake[0].y === food_y) {
// 增加头
snakeLength += 1;
addHead(food_x,food_y);
// 改变分数
score += 10;
span_score.innerHTML = score;
// 改变速度
speed = (speed > 100) ? (speed - 20) : speed;
randFood();
draw(food_x,food_y);
}
}

// 清除
function clear(param_x,param_y) {
context.clearRect(param_x,param_y,stride - 2,stride - 2);
}
// 画小方块
function draw(param_x,param_y) {
context.fillRect(param_x,param_y,stride - 2,stride - 2);
}
// 初始化函数
function init() {
context.lineWidth = 1;
context.fillStyle = ‘#69D69E’;
context.strokeStyle=”#89EFA3”;
var i = 0;
while(i <= maxNumber) {
context.moveTo(0, i);
context.lineTo(maxNumber,i);
context.stroke();

      context.moveTo(i,0);
      context.lineTo(i,maxNumber);
      context.stroke();
      i += stride;
  }
  snake.push({x:31,y:61});
  randFood();
  draw(food_x,food_y);
  draw(snake[0].x,snake[0].y);

}
}

ps:所有测试都是在最新版本的谷歌浏览器下进行