贪吃蛇游戏
游戏说明
点击”开始游戏”按钮开始
使用键盘方向键控制蛇的移动方向
吃到红色食物可以得分,速度会逐渐加快
撞到墙壁或自己的身体游戏结束
可以随时暂停/继续游戏
canvas上面最好不要加width和height,用css控制能够更好的动态控制宽高
技术实现 这个游戏主要使用了以下技术:
HTML5 Canvas:用于游戏画面的渲染
JavaScript:实现游戏逻辑
CSS:页面样式和布局
游戏的核心功能包括:
蛇的移动控制
碰撞检测
食物生成
速度控制
游戏状态管理
代码详解 让我们详细解释游戏的核心代码实现:
1. 基础设置和变量 1 2 3 4 5 const canvas = document .getElementById ('gameCanvas' );const box = 20 ; let drawInterval = null ; let defaultSpeed = 500 ; let drawProcess = false ;
这些是游戏的基本配置。我们使用 20x20 像素的网格作为基本单位,defaultSpeed 控制游戏速度,初始设置为 500 毫秒更新一次。
2. Canvas 初始化 1 2 3 4 5 6 function initCanvas ( ) { canvas.width = canvas.offsetWidth ; canvas.height = 400 ; gridWidth = Math .floor (canvas.width / box); gridHeight = Math .floor (canvas.height / box); }
这个函数负责初始化 Canvas 的尺寸。它会:
根据容器宽度设置 Canvas 的实际像素宽度
设置固定的高度(400像素)
计算网格的行数和列数
3. 蛇和食物的数据结构
这里蛇需要理解,上下左右给蛇加个新头,然后去掉尾巴,就能够完成蛇的移动了,这是个关键因素。
1 2 3 let snake = [{ x : Math .floor (gridWidth / 2 ) * box, y : Math .floor (gridHeight / 2 ) * box }];let food;let direction = null ;
蛇被表示为一个对象数组,每个对象包含 x 和 y 坐标
初始时蛇只有一个节点,位于画布中心
direction 表示蛇的移动方向(UP、DOWN、LEFT、RIGHT)
4. 食物生成 1 2 3 4 5 6 7 8 9 function generateFood ( ) { do { food = { x : Math .floor (Math .random () * gridWidth) * box, y : Math .floor (Math .random () * gridHeight) * box }; } while (snake.some (seg => seg.x === food.x && seg.y === food.y ) && isPointWithinBoundary (food.x , food.y , 50 )); }
这个函数负责在随机位置生成食物:
使用 do-while 循环确保食物不会生成在蛇身上
isPointWithinBoundary 函数确保食物不会太靠近边界
5. 游戏主循环 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 function draw ( ) { if (drawProcess) return ; drawProcess = true ; ctx.fillStyle = '#000' ; ctx.fillRect (0 , 0 , canvas.width , canvas.height ); ctx.fillStyle = 'red' ; ctx.fillRect (food.x , food.y , box, box); for (let i = 0 ; i < snake.length ; i++) { ctx.fillStyle = i === 0 ? 'green' : 'lightgreen' ; ctx.fillRect (snake[i].x , snake[i].y , box, box); } if (direction) { let head = { ...snake[0 ] }; if (direction === 'UP' ) head.y -= box; if (direction === 'DOWN' ) head.y += box; if (direction === 'LEFT' ) head.x -= box; if (direction === 'RIGHT' ) head.x += box; if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height || snake.some (seg => seg.x === head.x && seg.y === head.y )) { clearInterval (drawInterval); alert ('Game Over!' ); restartGame (); drawProcess = false ; return ; } if (head.x === food.x && head.y === food.y ) { defaultSpeed = Math .max (100 , defaultSpeed - 50 ); generateFood (); startDraw (); } else { snake.pop (); } snake.unshift (head); } drawProcess = false ; }
游戏主循环是最复杂的部分,它负责:
清空并重绘画布
绘制食物和蛇
根据方向移动蛇
处理碰撞检测
处理食物收集
控制游戏速度
6. 游戏控制函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 function startDraw ( ) { if (drawInterval) clearInterval (drawInterval); drawInterval = setInterval (draw, defaultSpeed); } function restartGame ( ) { clearInterval (drawInterval); defaultSpeed = 500 ; snake = [{ x : Math .floor (gridWidth / 2 ) * box, y : Math .floor (gridHeight / 2 ) * box }]; generateFood (); direction = null ; startDraw (); } function pauseGame ( ) { if (drawInterval) { clearInterval (drawInterval); drawInterval = null ; } else { startDraw (); } } function startGame ( ) { if (!direction) { direction = 'LEFT' ; } if (!drawInterval) { startDraw (); } }
这些函数处理游戏的各种状态:
startDraw: 启动游戏循环
restartGame: 重置游戏状态
pauseGame: 暂停/继续游戏
startGame: 开始新游戏
7. 事件监听 1 2 3 4 5 6 7 8 9 10 11 window .addEventListener ('resize' , () => { initCanvas (); restartGame (); }); document .addEventListener ('keydown' , event => { if (event.key === 'ArrowUp' && direction !== 'DOWN' ) direction = 'UP' ; if (event.key === 'ArrowDown' && direction !== 'UP' ) direction = 'DOWN' ; if (event.key === 'ArrowLeft' && direction !== 'RIGHT' ) direction = 'LEFT' ; if (event.key === 'ArrowRight' && direction !== 'LEFT' ) direction = 'RIGHT' ; });
事件监听器处理:
窗口大小改变时重置游戏
键盘输入控制蛇的方向(确保蛇不能直接掉头)