贪吃蛇是一款益智小游戏,通过点击上下左右四个按键控制蛇头移动。
主要是设计蛇的身体和移动方法。将蛇的身体设置成一个数组,数组里存放蛇身每一节的xy坐标。游戏开始后,蛇头(数组第0位)会随着时间不断地移动,也就是x+1
或x-1
或y+1
或y-1
,当蛇头移动了,身体的每一节xy将等于移动前它们的前一节,也就是说,第二节的位置将变成移动前蛇头的位置,依次变化就形成了蛇身的移动效果。当蛇吃到了食物的时候,则在数组里push蛇身移动前最后一节的xy值。
<canvas id="canvas" width="500" height="300" style="border:5px solid #2f0606;">canvas>
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d")
ctx.fillStyle = "#c0b4b4";
ctx.fillRect(0, 0, 500, 300);
画布的长宽是500 * 300
function Snake(x, y) {
this.body = [[x, y]] // 蛇的身体
this.direction = 'right' // 初始方向
this.time = null // 定时器
this.move = function() {
}
this.eat = function() {
}
this.stop = function() {
}
}
创建了一个叫Snake的构造函数。其中,xy
是蛇头的初始位置;body
是蛇的身体,是一个二维数组;direction
代表移动方向,有right
、left
、top
、bottom
四个参数;time
是一个定时器;move
是一个方法,控制蛇身的移动,这是整个贪吃蛇的核心;eat
是吃的函数;stop
停止移动。
可以直接new
一个Snake
对象。
snake = new Snake(data.x, data.y)
data.x
和data.y
是初始位置。
这是贪吃蛇的核心,通过定时器让贪吃蛇动起来。先从蛇的最后一节移动,每一节等一它的前一节,当身体部分移动完了再通过direction
参数判断蛇头该怎么移动。
this.move = function() {
var _this = this
this.time = setInterval(function () {
var last = [].concat(_this.body[_this.body.length - 1]);
for (var i = _this.body.length-1;i>=1;i--) {
_this.body[i][0] = _this.body[i-1][0]
_this.body[i][1] = _this.body[i-1][1]
}
switch (_this.direction) {
case 'right':
_this.body[0][0] += 1
break
case 'bottom':
_this.body[0][1] -= 1
break
case 'left':
_this.body[0][0] -= 1
break
case 'top':
_this.body[0][1] += 1
break
}
// 检查是否遇到食物
if (_this.body[0][0] === food.x && _this.body[0][1] === food.y) {
_this.eat(last)
}
// 检查是否遇到自己身体
var index = _this.body.findIndex(function(e, i) {
return i !== 0 && (_this.body[0][0] === e[0] && _this.body[0][1] === e[1])
})
if (index !== -1 || (_this.body[0][0] === last[0] && _this.body[0][1] === last[1] )) {
alert('你撞到自己了')
_this.stop()
}
// 检查是否撞墙
if (_this.body[0][0] < 0 || _this.body[0][0] > 49 ||_this.body[0][1] < 0 ||_this.body[0][1] > 29) {
alert('你撞墙了')
_this.stop()
}
}, data.timeout)
}
通过document.onkeydown
来监听键盘点击事件。
function getKey() {
document.onkeydown=function(event){
var e = event || window.event || arguments.callee.caller.arguments[0];
if(e && e.keyCode==38){//下
if (snake.direction !== 'top')
snake.direction = 'bottom'
}
if(e && e.keyCode==37){//左
if (snake.direction !== 'right')
snake.direction = 'left'
}
if(e && e.keyCode==39){//右
if (snake.direction !== 'left')
snake.direction = 'right'
}
if(e && e.keyCode==40){//上
if (snake.direction !== 'bottom')
snake.direction = 'top'
}
};
}
snake
是之前new
的蛇对象。
function Food() {
this.x = Math.floor(Math.random() * 50)
this.y = Math.floor(Math.random() * 30)
}
食物有xy
轴坐标,通过new Food()
来创建食物。
然后为蛇添加吃的函数功能
this.eat = function(last) {
this.body.push(last)
score += 1;
food = new Food()
}
last
是蛇移动前的最后一节位置坐标[x, y]
。每次蛇吃了食物之后会增长,然后创建新的食物。
for (var i = 0; i< snake.body.length; i++) {
ctx.save()
ctx.translate(snake.body[i][0] * data.size, snake.body[i][1] * data.size);
if (i === 0) {
ctx.fillStyle = "DarkGreen";
} else {
ctx.fillStyle = "green";
}
ctx.fillRect(0, 0, data.size, data.size);
ctx.restore()
}
ctx.save()
ctx.translate(food.x * data.size, food.y * data.size);
ctx.fillStyle = "OrangeRed";
ctx.fillRect(0, 0, data.size, data.size);
ctx.restore()
画布可以通过requestAnimationFrame
更新。
只需要调用snake.move()
函数就能让蛇移动,这个过程会创建一个定时器time
。
想让蛇停止只需要清除定时器。
this.stop = function() {
clearInterval(this.time)
}
调用snake.stop()
就能让蛇停止移动。
博客地址:http://www.iwowen.cn/2019/10/02/ck2xdq5s60002g4bh04as88ra.html