用原生JS手搓一个Flappy Bird小游戏(附完整源码和碰撞检测详解)
2026/6/10 17:12:06 网站建设 项目流程

用原生JS手搓一个Flappy Bird小游戏(附完整源码和碰撞检测详解)

在移动互联网时代,Flappy Bird以其简单的玩法和极高的难度成为现象级游戏。作为前端开发者,用原生JavaScript复刻这款经典游戏,不仅能深入理解游戏开发的基本原理,还能掌握Canvas绘图、游戏循环、碰撞检测等核心技能。本文将带你从零开始,仅用原生JS和Canvas API实现一个完整的Flappy Bird游戏,特别聚焦于矩形碰撞检测算法的实现细节。

1. 游戏基础架构设计

任何游戏的核心都离不开三个基本要素:游戏对象游戏循环用户输入。对于我们的Flappy Bird来说,需要特别关注以下几个关键组件:

  • 小鸟对象:负责位置更新、重力模拟和碰撞检测
  • 管道障碍物:随机生成上下管道,形成可穿越的间隙
  • 计分系统:记录玩家通过的管道数量
  • 游戏区域:使用Canvas绘制所有游戏元素
// 游戏主对象结构示例 const Game = { canvas: null, ctx: null, bird: null, pipes: [], score: 0, frameCount: 0, isGameOver: false };

提示:使用对象字面量组织游戏状态比全局变量更易于维护,也减少了命名冲突的风险。

2. 实现游戏核心机制

2.1 小鸟的物理模拟

Flappy Bird的核心玩法在于控制小鸟飞行高度,避开障碍物。我们需要模拟两个关键物理效果:

  1. 重力加速度:小鸟会持续下落
  2. 点击升力:玩家点击时给小鸟一个向上的速度
class Bird { constructor(x, y) { this.x = x; this.y = y; this.width = 30; this.height = 30; this.velocity = 0; this.gravity = 0.5; this.lift = -10; } update() { this.velocity += this.gravity; this.y += this.velocity; // 防止飞出屏幕顶部 if (this.y < 0) { this.y = 0; this.velocity = 0; } } flap() { this.velocity = this.lift; } }

2.2 管道生成算法

管道需要成对出现(上下管道),中间留有供小鸟穿过的间隙。关键参数包括:

参数说明典型值
gapHeight上下管道间的间隙150px
pipeWidth管道宽度80px
pipeSpeed管道移动速度2px/帧
spawnInterval新管道生成间隔150帧
function generatePipe() { const gapStart = Math.random() * (canvas.height - gapHeight); const topPipe = { x: canvas.width, y: 0, width: pipeWidth, height: gapStart }; const bottomPipe = { x: canvas.width, y: gapStart + gapHeight, width: pipeWidth, height: canvas.height - gapStart - gapHeight }; Game.pipes.push(topPipe, bottomPipe); }

3. 精确碰撞检测实现

碰撞检测是游戏开发中的关键算法。对于Flappy Bird这类2D游戏,我们采用**轴对齐边界框(AABB)**检测方法,这是最简单高效的2D碰撞检测技术。

3.1 AABB碰撞原理

AABB检测基于一个简单原则:如果两个矩形在x轴和y轴上的投影都重叠,则它们发生碰撞。具体需要检查四个边界条件:

  1. 物体A的右边界 > 物体B的左边界
  2. 物体A的左边界 < 物体B的右边界
  3. 物体A的底边界 > 物体B的顶边界
  4. 物体A的顶边界 < 物体B的底边界
function checkCollision(rect1, rect2) { return ( rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y ); }

3.2 应用到游戏场景

在游戏循环中,我们需要检测小鸟与每个管道的碰撞情况:

function updateGame() { // 更新小鸟位置 Game.bird.update(); // 检测碰撞 for (const pipe of Game.pipes) { if (checkCollision(Game.bird, pipe)) { endGame(); return; } } // 检测是否撞到地面 if (Game.bird.y + Game.bird.height > canvas.height) { endGame(); } }

4. 完整游戏循环实现

游戏循环是驱动游戏运行的核心机制,通常包含以下步骤:

  1. 清除画布:擦除上一帧的内容
  2. 更新游戏状态:计算所有对象的新位置
  3. 渲染对象:绘制所有游戏元素到画布
  4. 请求下一帧:继续循环
function gameLoop() { if (Game.isGameOver) return; // 1. 清除画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 2. 更新游戏状态 updateGame(); // 3. 渲染所有对象 drawBird(); drawPipes(); drawScore(); // 4. 继续循环 requestAnimationFrame(gameLoop); } // 启动游戏 function startGame() { Game.bird = new Bird(100, canvas.height / 2); Game.pipes = []; Game.score = 0; Game.isGameOver = false; gameLoop(); }

注意:现代浏览器推荐使用requestAnimationFrame而非setInterval来实现游戏循环,它能更好地与浏览器刷新率同步。

5. 性能优化与进阶技巧

当游戏复杂度增加时,需要考虑以下优化策略:

  • 对象池模式:复用管道对象而非频繁创建销毁
  • 视口剔除:不渲染屏幕外的对象
  • 碰撞检测优化:空间分区算法如四叉树
// 对象池示例 const pipePool = []; function getPipe() { if (pipePool.length > 0) { return pipePool.pop(); } return { x: 0, y: 0, width: 0, height: 0 }; } function recyclePipe(pipe) { pipePool.push(pipe); }

6. 完整源码解析

以下是游戏的核心代码结构:

<!DOCTYPE html> <html> <head> <title>Flappy Bird with Vanilla JS</title> <style> canvas { background: skyblue; display: block; margin: 0 auto; } </style> </head> <body> <canvas id="gameCanvas" width="400" height="600"></canvas> <script> // 完整游戏实现代码... // 包含上述所有功能模块 </script> </body> </html>

实现过程中有几个关键点值得注意:

  • 游戏状态管理:清晰区分游戏运行、暂停和结束状态
  • 难度曲线:随着分数增加,可以适当提高管道移动速度或减小间隙
  • 用户体验:添加游戏开始/结束界面,增加视觉反馈效果

在调试碰撞检测时,一个实用的技巧是临时添加可视化碰撞框:

function drawDebugCollisionBox() { ctx.strokeStyle = 'red'; ctx.strokeRect( Game.bird.x, Game.bird.y, Game.bird.width, Game.bird.height ); }

从项目实践来看,最大的挑战往往不在于代码实现本身,而在于参数调优。比如重力大小、升力强度、管道移动速度等参数的微小变化会极大影响游戏体验。建议将这些参数提取为配置对象,方便快速调整:

const Config = { gravity: 0.5, lift: -10, pipeSpeed: 2, gapHeight: 150, spawnRate: 150 };

最后要强调的是,虽然这个实现只用了不到200行代码,但它完整呈现了一个游戏的核心架构。以此为起点,你可以进一步扩展功能,比如添加背景滚动、粒子特效、音效支持等,逐步构建更丰富的游戏体验。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询