首页
/ Web-Dev-For-Beginners 太空游戏系列第 4 课作业实践:用矩形相交原理打造自定义碰撞小游戏

Web-Dev-For-Beginners 太空游戏系列第 4 课作业实践:用矩形相交原理打造自定义碰撞小游戏

2026-09-07 12:50:01作者:蔡怀权

本篇技术指南围绕微软开源教程 Web-Dev-For-Beginners「太空游戏」系列第 4 课的课后作业「Explore Collisions」(碰撞探测探索)展开,任务是让学习者运用本课讲解的矩形相交碰撞检测原理,自行创作一个展示多种物体交互方式的迷你游戏。文章将完整拆解作业目标、验收标准与评分细则,并借助本课课程文档与其参考答案源码,给出可复现、可对照评分的设计实现方案,帮助你真正掌握碰撞检测、事件驱动输入与对象生命周期管理。

作业定位:它属于「太空游戏」系列的第 4 课

本仓库是微软发起、面向零基础学习者的 24 课 Web 开发课程。碰撞探测作业位于「构建太空游戏(Build a Space Game)」系列(6-space-game)的第 4 课之后,前置内容依次是画布入门、让元素移动、在画布上绘制物体。第 4 课课程本身(README.md)会带领学习者为飞船加入激光武器并实现完整的碰撞系统,而本作业则要求你脱离示例代码,独立设计一个你自己的碰撞小游戏,用创造性的方式迁移这些知识。

配套工程代码就在本课目录下:

目录 说明
your-work 学习者起点代码:只含画布与基本的 GameObject/Hero/Enemy 类,尚无碰撞逻辑,等待你动手实现
solution 参考答案:完整实现激光射击、碰撞检测、计分与胜负判定

提示:两个工程目录的 package.json 都以 npm start 启动本地服务器,游戏画布尺寸为 1024×768(见 solution/index.html)。

作业要求全解析

作业正文(assignment.md)的核心是:将你在碰撞检测课上学到的知识应用于实践,创建一款自定义迷你游戏,展示不同类型的物体交互方式,通过创造性实现与反复实验来理解碰撞机制。官方给出的评分维度是下面的三件事。

必做:交互式小游戏应当包含四要素

要求 具体说明
多个可移动物体 可通过键盘或鼠标控制
碰撞检测系统 必须采用本课的**矩形相交(rectangle intersection)**原理
视觉反馈 碰撞发生时要有对象销毁、变色、特效等可感知反馈
游戏规则 让碰撞结果对玩法有意义、有吸引力(胜负、得失分)

官方创意方向(五选一或自拟)

  • 小行星带(Asteroid field):驾驶飞船穿越危险的太空碎片;
  • 碰碰车(Bumper cars):创建一个基于物理的碰撞竞技场;
  • 陨石防御(Meteor defense):保护地球免受来袭太空岩石的撞击;
  • 收集游戏(Collection game):一边收集道具一边躲避障碍;
  • 领土控制(Territory control):互相竞争的物体争夺空间。

加分挑战(Bonus challenges)

在完成基础版本后,可逐步加入:碰撞时的粒子特效、不同碰撞类型的音效、基于碰撞结果的计分系统多种碰撞类型与差异化行为、随时间递增的难度曲线。下文第五、六节会给出这些机制与参考源码的对应实现,可作为迁移蓝本。

评分细则(Rubric):官方到底在考什么

作业文档给出了明确的四级评分表,理解它可以指导你的设计取舍:

标准 优秀(Exemplary) 合格(Adequate) 需改进(Needs Improvement)
碰撞检测 精确实现基于矩形的碰撞检测,支持多种对象类型与高级交互规则 基础碰撞检测正确,仅支持简单对象交互 碰撞检测存在问题或表现不稳定
代码质量 代码干净、组织良好,类结构合理,变量命名有意义,注释得当 代码可运行但组织和文档化有待提高 代码难以理解或结构混乱
用户交互 控制响应灵敏、玩法流畅、视觉反馈清晰、机制有吸引力 基础控制可用,反馈足够 控制不灵敏或令人困惑
创造力 原创概念、独特功能、视觉打磨与创新的碰撞行为 标准实现中加入了一些创意元素 仅基本功能,无创意增强

结合评分表可以反推出设计策略:想拿高分,至少要保证多对象类型共存类封装清晰即时且醒目的碰撞反馈,并用加分挑战里的机制凸显原创性。

核心技术一:矩形边界与相交判定(碰撞检测的数学基础)

作业明确要求使用本课的「矩形相交」原理。课程文档把碰撞检测的核心思想拆成两步,这也是你设计任意迷你游戏前必须吃透的数学地基。

1. 用位置 + 尺寸表达边界

每个游戏对象都被视为一个轴对齐矩形(AABB)。只需记录左上角坐标 (x, y) 与宽高,即可推导出四条边。课程给出的标准方法(在 solution/app.js 中即为 GameObject.rectFromGameObject() 的真实实现):

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

2. 分离轴判定:四个「不相交」条件取反

判断两个矩形是否重叠,与其计算重叠区域,不如反证其是否分离:只要矩形 2 完全位于矩形 1 的右侧、左侧、下方或上方任一情形成立,二者必不相交;否则必然碰撞。课程算法(同见 solution/app.js):

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

这条 O(1) 判定只有四次数值比较,非常适合在主循环中对大量对象做实时检测,也是作业中要求掌握的高效实现方式。

核心技术二:对象生命周期管理——「标记删除」而非「即时删除」

作业的「技术实现」要点里包含对象生命周期管理(创建与销毁)。太空游戏示例把这条经验体现得尤为关键:当激光命中敌机、敌机撞上英雄时,双方都需要被移除;但若在遍历数组的循环体中直接删除元素,会导致索引错位甚至崩溃(对应课程自测题「如果立刻删除对象会发生什么」的答案:遍历中途删除会引发崩溃或跳过对象)。

正确范式分两步(参照 solution/app.jsupdateGameObjects()):

// 第 1 步:碰撞发生时只做「标记」
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
  first.dead = true;
  second.dead = true;
  hero.incrementPoints();   // 参考答案额外实现了计分
});

// 第 2 步:本帧结束后统一过滤,安全地在帧间清理
gameObjects = gameObjects.filter((go) => !go.dead);

这种模式让当前帧安全跑完,同时避免死亡对象持续堆积造成内存膨胀。激光到达屏幕顶端时也同样走这条路径:在 solution/app.jsLaser 类中,当 this.y <= 0 时置 this.dead = true 并清除自身的 setInterval

核心技术三:事件驱动输入与对象类设计

作业要求「基于事件的用户输入编程」与「干净的、具备合理类结构的代码组织」。参考答案提供了可直接借鉴的架构范本:

  • 事件总线:轻量 EventEmitter(见 solution/app.js),通过 on/emit 解耦输入、碰撞与渲染逻辑;
  • 消息常量Messages 对象统一管理事件名(如 KEY_EVENT_SPACECOLLISION_ENEMY_LASERCOLLISION_ENEMY_HERO),避免字符串散落各处导致拼写错误;
  • 输入监听:键盘 keyup 事件把「按键事实」转为语义化事件发出(solution/app.js),同时用 keydown 拦截空格与方向键的默认滚动行为;
  • 类层次GameObject 基类承载位置、尺寸、贴图与边界计算,HeroEnemyLaser 各自继承并扩展专属行为(solution/app.js)。你在作业中的代码只要按「基类公共能力 + 子类差异化行为」组织,即符合「干净的类结构」要求。

参考实现还示范了用冷却系统限制开火频率、保持操作手感:Hero.fire() 将激光加入 gameObjects 并把 cooldown 置为 500,由定时器逐步递减到 0canFire() 仅在冷却归零时返回 truesolution/app.js)。这一设计思想可以直接复用到你的游戏里——比如「陨石防御」需要限制投弹频率,「碰碰车」需要限制加速次数。

实战推演:如何按官方标准做出一款「陨石防御」作业

把上面的机制拼装起来,即可落地为作业要求的完整小游戏。以官方创意方向之一的「陨石防御:保护地球免受来袭太空岩石撞击」为例,逐步设计:

  1. 对象建模:定义 Earth(静态目标,宽度可参考示例中的 99px 量级)、Meteor(自上而下匀速下降,尺寸、速度随机)、Cannon(键盘 ←/→ 控制、可在底部平移)三类,全部继承一个 GameObject 基类,每个对象实现 rectFromGameObject()
  2. 主循环:以 setInterval(参考示例使用 100ms)驱动每帧 updateGameObjects() + 绘制;updateGameObjects() 中按类型过滤出陨石列表与炮弹列表,两两调用 intersectRect() 做矩形相交测试;
  3. 碰撞事件与规则:炮弹命中陨石 → 双方标记 dead 并加 100 分;陨石触底(bottom >= canvas.height)→ 地球生命值减一;生命归零 → 触发失败并结束游戏。注意:陨石与地球也互为碰撞对象,这正好覆盖了评分表中「多种对象类型与高级交互规则」这一优秀档要求;
  4. 视觉反馈:命中瞬间用粒子残影或变色闪烁表现销毁,触底时用红色警示色表现损伤,保证反馈清晰可见;
  5. 难度曲线:随存活时间逐步缩短陨石生成间隔或加快下落速度,对应加分挑战中的「渐进式难度」;
  6. 流程闭环:参照参考答案的 endGame(win)resetGame()solution/app.js),在胜利/失败后显示提示并可重新开局。

完成主体后,参照作业加分项逐条检查:粒子特效可用短生命周期粒子数组实现,同样走「标记删除 + 帧间过滤」;计分系统只需在事件监听器里维护分数变量并绘制文本(参考答案的 drawPoints() 即为现成范式,见 solution/app.js)。

上手与验证:起点代码、运行与调试

想以仓库提供的骨架快速开始,可按下面步骤操作(以本课 your-work 目录为准):

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

随后在浏览器打开 http://localhost:5000,可看到尚未具备碰撞逻辑的初始画布。参考答案位于同级 solution 目录(命令一致,端口同为 5000),可运行对照观察最终行为。

开发过程中的自检清单(对应课程文档的调试建议):

  • 打开浏览器 DevTools,在 intersectRectupdateGameObjects 处打断点,观察每帧的矩形坐标比较;
  • 修改激光速度(示例为每 100ms 上移 15px)或陨石下落步长,观察碰撞窗口的变化;
  • 调整冷却值(示例为 500ms)与递减节奏(每 200ms 减 100),验证射击手感;
  • console.log 实时打印碰撞事件,确认事件确实发出且对象被正确标记删除。

仓库为只读示例工程,练习时请复制到本地或 fork 后自行修改运行,文章中所有路径均可直接对照仓库查看源码与素材(游戏贴图位于 solution/assetsyour-work/assets)。

结论

本作业的真正价值不在于「再写一遍太空游戏」,而在于验证你是否把矩形相交检测从『看得懂』变成了『用得出』。对照评分表自测:碰撞判定是否对多种对象稳定生效?类是否职责分明?操控与反馈是否即时清晰?概念是否有原创亮点?只要用本课提供的 rectFromGameObject() + intersectRect() 分离轴判定范式,配合「标记删除」的生命周期管理、事件驱动输入与类继承结构,再叠加粒子、音效、计分与渐进难度等加分项,你就能交出一份达优秀档的作品——而这些原理同样是你在真实 Web 游戏、交互式可视化乃至前端拖拽交互中长期受用的核心技能。

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

项目优选

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