首页
/ Web-Dev-For-Beginners 太空游戏碰撞检测实战:用矩形相交原理打造你的自定义迷你游戏

Web-Dev-For-Beginners 太空游戏碰撞检测实战:用矩形相交原理打造你的自定义迷你游戏

2026-09-10 23:27:10作者:舒璇辛Bertina

本篇技术指南围绕 Web-Dev-For-Beginners 课程「太空游戏」第 4 课《Adding A Laser and Detect Collisions》的课后作业展开,核心任务是在理解矩形边界与相交判定算法的基础上,独立设计并实现一个包含多种对象交互、具备完整游戏规则的自定义碰撞检测迷你游戏。读完本文,你将掌握基于 rectFromGameObject / intersectRect 的矩形碰撞检测落地方法、事件驱动输入架构、对象生命周期管理(标记删除),并能参照仓库中的官方参考实现完成从需求分析、代码组织到评分自查的全流程实践。

一、作业背景:从理论到创作的实践闭环

本作业承接第 4 课的核心知识——在太空游戏中为英雄飞船添加激光武器并实现碰撞检测。课程用矩形近似所有游戏对象(类似空管系统用简化几何形状追踪飞机),通过「分离测试」判断两个矩形是否相交,这套算法同样被广泛用于物理模拟与交互式 Web 界面。

本课完整的讲义内容位于 6-space-game/4-collision-detection/README.md,英文原版作业见 6-space-game/4-collision-detection/assignment.md。作业要求你把学到的碰撞检测知识迁移到全新场景:不局限于太空射击,而是创造性地实现一个展示不同类型对象交互的迷你游戏,通过亲自动手加深对碰撞机制的理解。

二、核心原理回顾:两个你必须吃透的函数

动手创作前,先复习第 4 课的两个核心算法,它们是你作业的技术基石。

1. 用矩形边界描述游戏对象

每个游戏对象只需四组数据即可定义碰撞区域:位置 (x, y) 与尺寸 (width, height),由此推导出四条边:

rectFromGameObject() {
  return {
    top: this.y,
    left: this.x,
    bottom: this.y + this.height,
    right: this.x + this.width,
  };
}
  • Top 上边:对象的起始纵坐标 y
  • Left 左边:起始横坐标 x
  • Bottom 下边y + height
  • Right 右边x + width

该方法的官方实现位于 6-space-game/4-collision-detection/solution/app.js,作为 GameObject 基类方法,所有子类(Hero、Enemy、Laser)都能复用这套标准化接口。

2. 分离测试判定相交

判断两个矩形是否相交,不需要计算重叠面积,只需检查四种「分离」条件是否成立:

function intersectRect(r1, r2) {
  return !(
    r2.left > r1.right ||
    r2.right < r1.left ||
    r2.top > r1.bottom ||
    r2.bottom < r1.top
  );
}

四种分离情形分别是:矩形 2 完全在矩形 1 的右边、左边、下边或上边。只要其中任意一种成立,两者必然不相交;反之(取反后返回 true)即发生碰撞。相比直接计算交叠区域,分离测试只需最多 4 次比较,性能优异,是实时游戏循环中的高效选择(参考实现见 solution/app.js)。

三、项目需求:四项硬性要求

作业要求创建一个小型交互式游戏,必须满足:

  1. 多个可移动对象:支持通过键盘或鼠标控制(移动的对象不必全部可操控,但至少核心角色要能响应输入);
  2. 碰撞检测系统:使用本课矩形相交原理实现;
  3. 碰撞时的视觉反馈:对象销毁、颜色变化、特效等,让玩家「看见」碰撞发生;
  4. 游戏规则:让碰撞产生意义——比如击中得分、碰到扣命、碰撞导致失败等,使玩法有目标、有张力。

四、创作方向建议:五个可直接开局的场景

如果你缺少灵感,作业提供了五个经过验证的场景原型,任选其一即可快速起步:

场景 核心玩法 碰撞双方
小行星带(Asteroid field) 驾驶飞船穿越危险太空碎片 飞船 ↔ 小行星
碰碰车(Bumper cars) 基于物理的碰撞竞技场 车辆 ↔ 车辆
陨石防御(Meteor defense) 保护地球免受太空岩石袭击 炮弹 ↔ 陨石
收集游戏(Collection game) 收集物品同时躲避障碍 玩家 ↔ 道具 / 玩家 ↔ 障碍
领土控制(Territory control) 竞争对象争夺空间地盘 对象 ↔ 对象

这些场景的共同点在于:都能充分展现「不同类型的对象交互」,且规则设计天然围绕碰撞展开。建议优先选择你能完整实现四项需求、又留有创意发挥空间的方案。

五、技术实现要求:作业评分的技术基线

作业明确要求解决方案必须体现以下四项技术能力,这也是评审「技术分」的衡量标准:

  • 正确使用基于矩形的碰撞检测:所有碰撞判定都应通过 intersectRect 完成,而不是依赖像素级检测或距离估算;
  • 事件驱动编程处理用户输入:键盘/鼠标事件应通过事件系统分发,而不是在游戏主循环里轮询按键状态;
  • 对象生命周期管理(创建与销毁):对象创建(如发射子弹、生成敌人)与销毁(碰撞后移除)都要安全、可追踪;
  • 清晰的代码组织与合适的类结构:建议采用基类 + 子类的继承设计,职责分明。

源码佐证:官方实现中的事件驱动架构

仓库官方参考实现 solution/app.js 展示了这套架构的标准写法,你可直接借鉴:

① 轻量事件总线 EventEmitterapp.js):用 on() 注册监听器、emit() 触发事件,实现输入、碰撞、游戏状态之间的解耦通信。

② 按键输入通过 keyup 事件发射消息app.js):方向键对应 KEY_EVENT_UP/DOWN/LEFT/RIGHT,空格键(keyCode === 32)对应 KEY_EVENT_SPACE,回车键对应 KEY_EVENT_ENTER。注意 keydown 阶段用 preventDefault() 阻止方向键与空格滚动页面(app.js),这是浏览器游戏必备的细节。

initGame() 中注册各类事件监听器app.js):例如空格键事件中先调用 hero.canFire() 检查冷却,满足条件才执行 hero.fire();激光命中敌人的事件中,将两个对象同时标记为 dead = true 并加分。

④ 主循环调用 updateGameObjects() 完成碰撞检测与对象清理app.js):先按类型过滤出 Enemy 与 Laser 列表,再做两两相交测试,命中即发射事件,最后统一 filter 掉死亡对象。

生命周期管理:先标记、后删除

作业特别强调对象销毁的安全性。官方实现的正确姿势是:碰撞发生时只把对象的 dead 标记为 true,不在循环遍历中途直接删除数组元素(否则可能导致遍历错乱甚至崩溃);待本帧碰撞测试全部结束后,再用 gameObjects = gameObjects.filter(go => !go.dead) 一次性剔除死亡对象。这样既保证当前帧稳定完成,又防止死亡对象长期驻留内存造成膨胀。Laser 类中 this.dead = true; clearInterval(id); 的写法(app.js)是「飞出屏幕自动销毁」的典型实现,你的迷你游戏同样需要这类边界处理(如障碍出界回收)。

六、加分挑战:让作品从合格走向优秀

完成基础需求后,作业给出了五个可选的增强方向,每一项都能显著提升作品完成度:

  1. 粒子特效:碰撞发生时迸发粒子爆炸效果;
  2. 音效:为不同类型的碰撞配上不同的声音反馈;
  3. 计分系统:基于碰撞结果(击中/躲避/占领)累加分数;
  4. 多类型碰撞:不同对象对碰撞做出差异化响应(如道具加血、障碍扣命);
  5. 渐进难度:难度随时间提升(对象速度加快、生成频率提高、障碍增多)。

这些增强点与评分标准中「Exemplary(优秀)」档的描述一一对应:精细的交互规则、清晰的视觉反馈、创新的碰撞行为,都是拉开差距的关键。

七、评分标准(Rubric):逐项对照自查

作业附带的评分表是官方评审依据,建议开发过程中对照自查:

标准 优秀(Exemplary) 合格(Adequate) 需改进(Needs Improvement)
碰撞检测 对多种对象类型实现精确的基于矩形的碰撞检测,并配有精细的交互规则 基础碰撞检测正常工作,对象交互简单 碰撞检测存在问题或运行不稳定
代码质量 代码整洁、组织良好,类结构合理、变量命名有意义、注释得当 代码可运行,但组织或注释可以更好 代码难以理解或结构混乱
用户交互 控件响应灵敏,游戏体验流畅,视觉反馈清晰,机制有趣 基础操控可用,反馈尚可 控件无响应或令人困惑
创造力 概念原创、特色鲜明,视觉精致,碰撞行为有创新 实现常规,带有部分创意元素 仅有基础功能,无创意增强

对照上表可以设计出你的验收清单:碰撞是否覆盖了至少两类对象组合?代码是否分层(渲染、逻辑、输入分离)?控制是否流畅且带反馈?玩法是否有让人眼前一亮的创意点?

八、参考实现的运行与演练路径

仓库同时提供了练习起点与完整答案,适合边做边对照:

两者 package.json 均以 npx http-server -c-1 -p 5000 启动本地服务(见 solution/package.json)。运行方式:

cd 6-space-game/4-collision-detection/solution   # 或 your-work
npm start

然后浏览器访问 http://localhost:5000 即可体验:方向键移动英雄,空格键发射激光,激光命中敌机双方销毁并加分;敌机与英雄相撞时敌机销毁、英雄损失一条生命(decrementLife),生命归零即失败。这段可玩性验证流程同样适用于你的自定义迷你游戏——先用官方答案跑通「碰撞产生 → 事件触发 → 对象清理 → 状态更新」的完整链路,再迁移到你自己的场景中。

九、总结

本次作业的真正价值不在于复刻某个模板,而在于完成一次「原理 → 设计 → 实现 → 验收」的完整工程演练:用矩形边界与分离测试解决碰撞判定,用事件驱动解耦输入与响应,用「标记后删除」保障生命周期安全,再用评分表量化质量。完成它之后,这些碰撞检测技能可以直接迁移到交互式界面、拖拽操作、触摸手势识别乃至机器人路径规划等更广阔的领域——这也是 Web-Dev-For-Beginners 太空游戏系列(总览见 6-space-game/README.md)想传递的核心能力。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
34
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.16 K
2.78 K
docsdocs
暂无描述
Markdown
904
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
936
1.86 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
862
1.36 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
535
606
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.38 K
1.47 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
4.02 K
1.03 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
549
400
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.07 K
538