<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas {
display: block;
margin: 0 auto;
background-color: #33cc99;
}
</style>
</head>
<body>
<canvas id="canvas" width="600" height="600"></canvas>
<script>
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
// 食物的默认位置
var x = Math.floor(Math.random() * 20) * 30
var y = Math.floor(Math.random() * 20) * 30
// 蛇的默认位置
var snake = [{ x: 3, y: 0 }, { x: 2, y: 0 }, { x: 1, y: 0 }]
//食物是否被吃掉
var isEated = false
// 游戏是否结束
var isGameOver = false
// 蛇的方向
var directionX = 1
var directionY = 0
document.addEventListener('keydown', function (e) {//监听键盘按下行为
if (e.keyCode === 37) {//左
directionX = -1
directionY = 0
} else if (e.keyCode === 38) {//上
directionX = 0
directionY = -1
} else if (e.keyCode === 39) {//右
directionX = 1
directionY = 0
} else if (e.keyCode === 40) {//下
directionX = 0
directionY = 1
}
})
// 让贪吃蛇动起来,原理就是不断擦除,然后不断重绘
setInterval(function () {
if (isGameOver) {//游戏结束
return
}
// 擦除
ctx.clearRect(0, 0, 600, 600)
// 随机生成食物的位置
if (isEated) {//食物被吃掉后就重新绘制食物
x = Math.floor(Math.random() * 20) * 30
y = Math.floor(Math.random() * 20) * 30
}
// 绘制食物
ctx.fillStyle = '#cccc00'
ctx.fillRect(x, y, 30, 30)
var oldHead = snake[0]
var newHead = {
x: oldHead.x + directionX,
y: oldHead.y + directionY
}
if (
newHead.y < 0 ||
newHead.x < 0 ||
newHead.x * 30 >= 600 ||
newHead.y * 30 >= 600
) {//游戏结束的判断
isGameOver = true
} else {
snake.unshift(newHead)
/* 蛇吃食物的分析:当蛇头的坐标和食物的坐标重合的时候,就表示食物被吃掉了,此时应该做两件事
1.让isEated变为true,表示食物被吃掉
2.让蛇增加一节长度
*/
// 蛇动起来分析:删除最后一节,然后在最前面添加一个新节,通过定时器不断的执行这个操作就有一个蛇动起来的效果
if (snake[0].x * 30 === x && snake[0].y * 30 === y) {//食物被吃掉,重新生成一个食物,并在蛇头添加一个新节
isEated = true
} else {//食物没有被吃掉,移除最后一节,在蛇头添加一个新节
isEated = false
snake.pop()
}
}
// 绘制蛇
for (var i = 0; i < snake.length; i++) {
if (i === 0) {//舌头
ctx.fillStyle = '#ff0033'
} else {//蛇身
ctx.fillStyle = '#333399'
}
ctx.fillRect(snake[i].x * 30, snake[i].y * 30, 30, 30)
}
for (var i = 1; i < 20; i++) {//绘制网格
// 水平线
ctx.moveTo(0, i * 30 + 0.5)
ctx.lineTo(600, i * 30 + 0.5)
// 垂直线
ctx.moveTo(i * 30 + 0.5, 0)
ctx.lineTo(i * 30 + 0.5, 600)
}
ctx.strokeStyle = 'white'
ctx.stroke()
}, 1000 / 4)
</script>
</body>
</html>
效果图 (直接复制代码可以看效果)
![]()