# GameBase Lesson 02：Game、Level、Camera、Fx 的边界

在线课件：https://deepnight.47-103-217-57.nip.io/02-GameBase/Lesson-02-Systems-Boundaries/

## 动手实验

1. 在练习场 A 向右开火。Level 碰撞查询到靶子，Entity 的 HP 扣除 20；Camera 发生视觉震动，Fx 请求粒子。下方调用追踪直接读取这一次操作的结果，不是另一个模拟器。
2. 关闭 Camera 与 Fx 反馈后再向右开火，目标仍然掉 20 HP。两项属于表现反馈，不应该影响命中。
3. 切换到关卡 B，初始实心墙挡住右向射线，HP 不变；打开通道后命中。墙会影响 **Level 数据**，不是是否有特效决定了命中。
4. 切 A/B，复盘 Game 编排：旧 Level、清 Fx、释放旧 Entity、新建关卡、调整 Camera、更新 Hud。
5. 开关墙体后观察 dirty 和静态地图重建次数；只是射击不需要重新创建整张地形。
6. 观察本课 64 槽粒子池的请求、成功、拒绝、复用、槽扫描数字。原版 Fx 是 2048 容量，且用不同的 SpriteBatch 组织效果。

## 源码事实（本地固定快照）

上游：deepnight/gameBase，提交 a7af1d70dbbf62d7fc09cb05431ced606e0ed809。

- Game.hx：构造时拥有 scroller、Fx、Camera、Hud；startLevel 先销毁旧关卡、fx.clear()、遍历 Entity.ALL 调用 destroy 并 garbageCollectEntities()，再 new Level、camera.centerOnTarget、hud.onLevelStart。源码中明确备注：销毁所有实体是模板方案，未来可保留玩家。
- Level.hx：接收 LDtk World_Level，生成 cWid/cHei、MarkerMap；hasCollision 越界为 true，否则查 M_Coll_Wall；invalidate 只标记，postUpdate 时才 render。当前 render 使用 root.removeChildren 和新 TileGroup，频繁重复重建会有实际成本。
- Camera.hx：跟随 target，处理 rawFocus/clampedFocus、边界、zoom、bump、shake 和 Game.scroller 变换。Camera 能访问 Game.level；Camera 改变的是视口，不应该反向覆盖物理位置。
- Fx.hx：创建 ParticlePool(Assets.tiles.tile,2048,Const.FPS)，四个 SpriteBatch（前后 × Normal/Add），并在 update() 中调用 pool.update(game.tmod)；可通过 level.hasCollision 查询粒子与关卡是否接触。这说明四个系统不是完全零依赖。

## 本课与真实源码的差异

课程的开火射线、目标伤害、轨迹和依赖追踪，都是我们独立编写的教学模型；并非 gameBase 原版提供通用 Game 事件总线。原版还存在实体直接调用 fx、camera 等方式，Game 负责持有并调度系统而非代理所有动作事件。

课程使用一张离屏 Canvas 缓存静态地形，切换墙体时按 dirty 重建；原版使用 LDtk TileGroup 及无效化标记，不使用我们的 Canvas 缓存。

课程的粒子池一共 64 槽，每帧扫描全部槽位，发射时扫描寻找空槽。实际成本随容量变化；原版是另一种 HParticle/ParticlePool 实现，不能直接用本课程耗时预测它。Renderer/GPU 仍需考虑 SpriteBatch、透明覆盖与批次。

为了让实验直接，角色枪口始终朝场景右侧发射射线，无复杂武器朝向、弹道或伤害类型计算。若角色移动到了目标右边，射线自然无法再击中左侧目标。

## 性能与职责判定

- 碰撞/场景事实属于 Level 提供的权威数据；Entity 或战斗系统更新目标 HP。
- Camera 视觉变换与 Fx 粒子不决定真实命中、死亡和游戏胜负。
- Game 统一管理生命周期、关卡切换和系统更新，但并不代表其必须接管每条具体战斗指令。
- Level 的 dirty 机制减少无谓重建，但如果频繁 invalidate 也仍会重复构造 TileGroup。
- Fx 粒子池减少分配不等于每帧零遍历，也不等于没有 GPU overdraw。

## 从 Unity 类比

Game 类似场景级编排；Level 类似 LDtk 关卡数据加 Tilemap/Collision 数据服务；Camera 类似 Cinemachine 加视口渲染变换；Fx 类似粒子池/VFX 服务。只是概念近似，不能对应到一组完全相同的 Unity API。

## 自测目标

为什么关闭特效不该影响伤害？为什么关卡墙体改变之后碰撞结果会变化？为什么关卡切换要集中释放多种系统资源？为什么 Camera/Fx 能访问 Level 却仍需要维持各自职责？如果想让玩家跨关卡保留角色，应该改造 Game.startLevel 的哪部分？