<!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>
效果图 (直接复制代码可以看效果)