美术(战斗区背景入包批): 三关背景与共用地面终稿入包 game/assets/art/scene/——作者选定 dungeon v10c/underdark v10c/deep_underdark v10c/ground v12b;背景 1280×252 不透明 32 色(实测平均 L 0.0148/0.0132/0.0111),地面 1280×100 顶缘透明 32 色,按作者裁保留原亮度(不透明域 L≈0.132,低于 §2 世界中层带 0.22–0.45,登记为作者例外);art-bible v3.29→v3.30:§6.1 新增「B 区舞台背景与共用地面的交付绑定」条(尺寸/色数/alpha/读数/例外指向)+ground_h 终稿高 100 回填句+资产渠道句现状化;art-status-checklist 增交付行、art-assets-checklist 现状句换代、asset-path-map scene 行区分「战斗背景已入包/营地仍登记超前」;battle-stage-prompts v1.7→v1.8 状态句换代;待办清单实况记选定与读数并保留 STAGE_BG 随代码批消化;入包对应代码侧需求卡片在册(board_type 选图/共用地面层/ground_h 落表/四柱光柱与 STAGE_BG 退役待迭代编排);验证=path_check 0 问题+pipeline_gate PASS+文档域闸全绿

This commit is contained in:
DKChan committed 2026-10-31 06:47:29 +08:00
1 parent 770bfe62ae
commit e153e8a3c3
7 files changed
+464 -9

No files matched your search

@@ -0,0 +1,453 @@
# 需求卡片:战斗区背景替换——B 区舞台插画与连续地面层
> 日期:2026-10-31
> 性质:需求改动实现批卡片;零待裁点,开工门=U0。
> 来源:待办清单「战斗区背景图替换——B 区舞台插画 + 临时光柱退役」条(唯一事实源:[art-bible](../design/art/art-bible.md) §6.1 v3.28 与 [battle-stage-prompts](../design/art/battle-stage-prompts.md) v1.7;候选样张过审 2026-10-31,候选与推荐套见 `artwork/2026-10-30-战斗区背景/候选保存清单-2026-10-31.md`)。
> 估时:T0–T5 ≈ **3.75~4.5 个工作日**;切分预案见第十三节。
## 一、设计事实源
1. [art-bible](../design/art/art-bible.md) §6.1 v3.28:B 区舞台场景构成、图层归属与资产契约——背景层三关变体(按 `board_type` 选图、不画光柱、不走 tint)、独立连续地面层(三关共用、不吃 tint、高度读 `ground_h`)、小石台保留并叠在连续地面之上;`ground_h` 字段由本实装批新增并回填。
2. [art-bible](../design/art/art-bible.md) §4.1 换色合并登记③(现行工作区 v3.29 行):`STAGE_BG`(原舞台底)随 §6.1 舞台背景插画批一并处置——背景资产接管绘制面时源常量退役或改指,禁单独为改值出批。本卡按其口径退役源常量,平色缺图回退改指 `UiKit.SLOT_BACKDROP`(#3E362C,合并目标)。
3. [battle-stage-prompts](../design/art/battle-stage-prompts.md) v1.7:三张背景与一张共用地面的画布尺寸、分层要求、否定后缀与验收;终稿尺寸 = 基准屏宽 × `stage_h`/基准屏宽 × `ground_h`。
4. 候选过审:2026-10-31 用户确认三关背景各 3 张全部可用、共用地面前后两轮修正后 v12 系列可用;遴选与后续替换/编辑由作者另行安排,不阻塞本卡。
本卡只实现上述设计,不改设计。艺术资产的最终遴选、编辑与入包走美术素材直改通道(asset-ingest),不属本卡写面。
## 二、目标与完成定义
本批把 B 区舞台从「程序化平色底+四柱光柱层」临时占位,换成「三关背景变体+共用连续地面层+保留小石台」的正式呈现,并把选图接到真实装板链上。
完成定义:
1. B 区背景按 `board_type` 选图:`dungeon` / `underdark` / `deep_underdark` 三值分别命中 `scene_stage_bg_<board_type>.png`;空串与未知值回落 `dungeon`;目标变体缺图时先回落 `dungeon`,仍缺则保留平色底 `UiKit.SLOT_BACKDROP`(#3E362C,原舞台底合并目标)。
2. B 区底部新增共用连续地面层 `scene_stage_ground.png`,底边贴 B 区底、全宽、高度读布局表 `ground_h`;三关共用,不按 `board_type` 换图。
3. 布局表新增 `ground_h` 字段(本卡回填 100)并带加载期校验;`tools/layout_config.py` 同步读取该字段。
4. 四柱光柱程序层退役:删除光柱绘制层与 `UiKit.BEAM_LIGHT`,任何缺图态也不出现光柱;舞台底源常量 `UiKit.STAGE_BG` 随背景接管退役,平色回退改指 `UiKit.SLOT_BACKDROP`(#3E362C,换色合并③目标);背景与地面均不引用 `wall_ambient` tint(现行代码本就无该路径)。
5. 现有小石台 `scene_stage_plaza.png` 原样保留,叠在连续地面之上;不改地台件与 `standee_body` 的地台绘制。
6. 装板真实链路(`board_changed` 与调试对局就绪)把当前板 `board_type` 同步到舞台;连续一层未知或空串时不崩、不刷错误。
7. 既有战斗屏呈现回归全绿:站桩、排播、明细带、三区几何、文字对比、明度三档带、棋盘/菜单/关卡 golden 零变化;渲染闸全绿。
8. 独立验收审计通过;反哺点清单覆盖第六节全部目标;本批不写 `design/` 与根规则文件。
## 三、现状事实
1. `BattleStageView._init(db_ref, layout)` 以 `layout.stage_h` 设置 B 区最小高度,随后建背景、世界、文本半区、伴随件层:[battle_stage_view.gd:27](../game/presentation/views/battle_stage_view.gd#L27)。
2. 背景现行=`Panel` 平色底 `UiKit.panel_flat(UiKit.STAGE_BG, UiKit.PANEL_BORDER, 0, 1)`,随后调用光柱层:[battle_stage_view.gd:37](../game/presentation/views/battle_stage_view.gd#L37)、[:44](../game/presentation/views/battle_stage_view.gd#L44)。
3. 光柱层为全幅 `Control`,绘制四柱(x 基准 110/900/1055/1210@1280,60 段,α26→0):[battle_stage_view.gd:50](../game/presentation/views/battle_stage_view.gd#L50)、[:145](../game/presentation/views/battle_stage_view.gd#L145)。
4. `UiKit.STAGE_BG = Color8(62,52,42)`、`UiKit.BEAM_LIGHT = Color8(255,236,200)`:[ui_kit.gd:185](../game/presentation/views/ui_kit.gd#L185)、[:186](../game/presentation/views/ui_kit.gd#L186)。
5. `UiKit.TEX_STAGE_PLAZA` 是现有唯一场景件常量;`UiKit.load_tex()` 以 `ResourceLoader.exists` 守卫缺图:[ui_kit.gd:250](../game/presentation/views/ui_kit.gd#L250)、[:290](../game/presentation/views/ui_kit.gd#L290)。
6. `game/assets/art/scene/` 现只有 `scene_stage_plaza.png`;三张背景与地面尚未入包(素材目录不入 git,工作区需同步素材)。
7. 布局表 schema 现五字段:`stage_h` / `info_panel_w` / `ap_bar_h` / `log_band_h_dig` / `log_band_h_settle`;`validate()` 已检查域与两处跨字段:[battle_layout_table.gd:7](../game/data/schemas/battle_layout_table.gd#L7)、[:14](../game/data/schemas/battle_layout_table.gd#L14)。无 `ground_h`。
8. 布局表值:`stage_h=252`、`info_panel_w=240`、`ap_bar_h=44`、`log_band_h_dig=24`、`log_band_h_settle=84`:[battle_layout.tres:7](../game/data/tables/battle_layout.tres#L7)。
9. `ConfigDB` 的 manifest 已登记 `battle_layout`,加载后装配到 `presentation.battle_layout`:[config_db.gd:32](../game/core/config_db.gd#L32)、[:151](../game/core/config_db.gd#L151)。
10. `BoardData.board_type` 为图类型标签(`dungeon` / `underdark` / `deep_underdark`):[board_data.gd:19](../game/core/board_data.gd#L19)。
11. 棋盘视图 `rebuild()` 已按 `board_type` 装载瓦片套,空串回落 `dungeon`:[board_view.gd:257](../game/presentation/views/board_view.gd#L257)。
12. 装板成功即发 `board_changed`:[battle_orchestrator.gd:406](../game/core/battle_orchestrator.gd#L406);主场景处理点重建棋盘视图:[main.gd:361](../game/presentation/main.gd#L361)、[:367](../game/presentation/main.gd#L367)。
13. 调试对局就绪路径直接重建棋盘视图,不经过主场景处理点:[main_debug_flow.gd:101](../game/presentation/main_debug_flow.gd#L101)、[:103](../game/presentation/main_debug_flow.gd#L103)。
14. 舞台当前没有任何接收 `board_type` 的入口,也没有背景/地面纹理常量(全仓 grep 零命中)。
15. 舞台世界为透明 SubViewport;站桩、地台、落影都在世界内绘制:[battle_stage_view.gd:60](../game/presentation/views/battle_stage_view.gd#L60)、[:71](../game/presentation/views/battle_stage_view.gd#L71);小石台绘制在站桩底:[standee_body.gd:367](../game/presentation/views/standee_body.gd#L367),台面矩形 `_pedestal_rect()` 在 [standee_body.gd:312](../game/presentation/views/standee_body.gd#L312)。
16. 舞台由装配器一次性构造(冒险屏 `_ready` 时):[ui_assembler.gd:27](../game/presentation/ui_assembler.gd#L27)、[adventure_screen.gd:28](../game/presentation/scenes/adventure_screen.gd#L28);背景/地面只能在建件后按板同步,不能重建整屏。
17. 布局表读取工具 `FIELDS` 现五字段,无 `ground_h`:[layout_config.py:12](../tools/layout_config.py#L12)。
18. 渲染闸 `shot_checker` 对战斗屏判 C 区文字、明细带提示、明度三档带(信息面 > 世界中 > 世界底):[shot_checker.py:143](../tools/shot_checker.py#L143);golden 仅棋盘三张+菜单+关卡,不覆盖 B 区舞台。
19. `theme_projection_test` 的光柱断言对象是 `UiKit._beams_rect()`(菜单斜光带),不是舞台四柱层:[theme_projection_test.gd:628](../game/tests/unit/presentation/theme_projection_test.gd#L628);本批退役舞台层不影响该断言。
20. 全仓代码无 `wall_ambient` 标识符;仅 `ui_kit.gd:249` 有注释说明小石台不吃该 tint,内容不构成本批改动。
21. 现有地台件入包与尺寸断言:[standee_present_values_test.gd:76](../game/tests/unit/presentation/standee_present_values_test.gd#L76)。
22. 布局探针已从真实选路入口进战斗屏并逐档检查三区几何:[layout_probe.gd:31](../game/probe/layout_probe.gd#L31)、[:55](../game/probe/layout_probe.gd#L55)。
23. `STAGE_BG` 现行四处引用:`ui_kit.gd:185` 常量、`battle_stage_view.gd:39` 绘制点、`theme_projection_test.gd:669`、`ui_contrast_probe.gd:30`;art-bible §4.1 换色合并③(工作区 v3.29 行)要求随本批退役或改指,禁单独改值出批。
## 四、设计契约
- 🔴 **C1 选图口径**:背景只按 `board_type` 三值选图;空串与未知值回落 `dungeon`;不得按关卡序号、节点深度或 `board_variants` 另造第二套选择逻辑。
- 🔴 **C2 背景尺寸**:背景纹理源 = 1280 × `stage_h`,基准档显示 1×;三张文件名必须带 `_dungeon` / `_underdark` / `_deep_underdark` 后缀,禁止同一张图换色或换 tint。
- 🔴 **C3 地面层**:连续地面层源 = 1280 × `ground_h`,三关共用、文件名不带 `board_type` 后缀;底边贴 B 区底、全宽;顶缘即与远景的分隔带;禁横向拉伸(基准档 1×)。
- 🔴 **C4 图层序**:背景 < 连续地面 < 世界站桩/小石台 < 文本半区 < 壳层伴随件。小石台必须在连续地面之上;禁把地面画进背景、禁把地台并进地面件。
- 🔴 **C5 光柱退役**:四柱程序层与 `UiKit.BEAM_LIGHT` 全删;任何缺图态、任何 `board_type` 下都不得再出现光柱/光带/光晕;菜单斜光带 `UiKit._beams_rect()` 不在退役面。
- 🔴 **C6 `ground_h` 单源**:`ground_h` 只存布局表,经 `ConfigDb.presentation.battle_layout` 读取;视图层零 `ground_h` 数值字面量。schema 校验不得放行「地面层被收起态明细带整条盖住」与「地面层超过 B 区一半」。
- 🔴 **C7 缺图回退**:目标背景缺图 → 回 `dungeon` 背景 → 再缺 → 保留平色底 `UiKit.SLOT_BACKDROP`(#3E362C,原舞台底合并目标);地面缺图 → 地面层隐藏、背景仍显示。任何回退都不得崩溃、不得刷脚本错误、不得出现光柱。
- 🔴 **C8 接板真实入口**:`board_changed` 与调试就绪两条现有入口都在重建棋盘后同步舞台 `board_type`;禁另立轮询、定时器或第二套装板通知。
- 🔴 **C9 tint 口径**:背景三张各自带关卡色族、连续地面三关恒定,二者均不引用 `wall_ambient` 槽;不得给舞台加第二层 tint 或乘色。
- 🔴 **C10 呈现回归**:渲染闸全绿——B 区文字对比、明细带纹理幅度、明度三档带(信息面 > 世界中 > 世界底)判据不变;棋盘三张、菜单、关卡 golden 零改动。判据若需改动=停卡呈报,禁调阈值换绿。
- 🔴 **C11 结构预算**:`battle_stage_view.gd` 类变量 ≤15、公开方法 ≤20、函数长 ≤50 行、单函数分支 ≤8;`battle_layout_table.gd` 的 `validate()` 不新增分支(地面校验拆私有辅助);S13 基线外零新增、存量键只降不升。
- 🔴 **C12 写面**:实现批只写 `game/` 与 `reports/`;禁写 `design/`、`roadmap.md`、`待办清单.md`、`体验验证清单.md`、`game/tests/README.md`;文档同步只列反哺点。
- 🔴 **C13 禁凑计数袋**:不得为凑「类变量数」把背景/地面状态塞进无关容器;不得为凑「方法数」把选图与地面几何强行合并成一个无职责函数;拆分单元须有可陈述职责。
- 🔴 **C14 舞台底换色合并**:`UiKit.STAGE_BG` 源常量随本批退役;平色缺图回退改指 `UiKit.SLOT_BACKDROP`(#3E362C,art-bible §4.1 换色合并③目标);`theme_projection_test` 与 `ui_contrast_probe` 的舞台底对比锚同步改读合并目标,阈值、判据与覆盖不变。
## 五、范围边界
做:
1. `UiKit` 增三关背景路径格式常量与共用地贴路径常量。
2. `BattleStageView` 增背景纹理层、连续地面层、`set_board_type()`、缺图回退与测试用取纹理单点。
3. 布局表增 `ground_h=100`、schema 校验与 `tools/layout_config.py` 读取字段。
4. `main.gd` 与 `main_debug_flow.gd` 在既有棋盘重建点同步舞台 `board_type`。
5. 删四柱光柱层、`_draw_light_beams` 与 `UiKit.BEAM_LIGHT`;退役 `UiKit.STAGE_BG` 源常量,平色回退改指 `UiKit.SLOT_BACKDROP`;同步改读两处对比锚。
6. 新增单元套件、扩充布局探针断言、登记 `run_all.gd`。
7. 实现报告、代拍板追认单、反哺点清单与独立验收审计。
不做:
1. 不选图、不修图、不生成新图、不入包素材——本卡开工前置是四件终稿已在 `game/assets/art/scene/`;遴选与编辑归作者/asset-ingest。
2. 不改 `scene_stage_plaza.png`、不改 `standee_body` 的地台绘制与落影。
3. 不改棋盘瓦片、数字、图标、文字排版、明细带内容。
4. 不改样张工具 `render_sample_sheet*.py` 的光柱绘制与注释;不更新任何 golden。
5. 不跑 MC;不做数值调参。
6. 不新增 UI 组件、不新增场景文件、不新增 ConfigDB 容器。
7. 不把「背景/地面」做成可按 `wall_ambient` 换色的通用槽。
## 六、关联文档同步面
| 文档 | 关联点 | 同步义务 |
|---|---|---|
| [art-bible](../design/art/art-bible.md) §6.1 | 「程序化平色+光柱现行使用=占位」「`ground_h` 由实装批新增并回填」「资产到位后四柱直接退役」三句改为实装事实;回填 `ground_h=100` | 实现批禁写;逐条落 `reports/iter<N>-反哺点-<日期>.md`,用户裁决后文档批落文 |
| [art-bible](../design/art/art-bible.md) §4.1 换色合并登记③ | `STAGE_BG` 由「随舞台背景插画批处置」改为已退役、平色回退改指 `SLOT_BACKDROP`(#3E362C) | 同上 |
| [art-assets-checklist](../design/art/art-assets-checklist.md) §4 | 三张背景与地面「已出候选 v10」状态句——更新为候选 v12 过审、终稿入包状态;小石台保留句核对 | 同上 |
| [battle-stage-prompts](../design/art/battle-stage-prompts.md) §4/§5 | `ground_h` 由「待实装批回填」改为已回填 100;档 6「四柱退役(代码批)」改为已退役 | 同上 |
| [battle.md](../design/gdd/ux/battle.md) :118、:155 | 布局字段清单补 `ground_h`;「现行溢出区为临时光柱氛围层,正式背景到位后该层退役」改为已退役、判定不变 | 同上 |
| [HUD框架.md](../design/gdd/systems/表现与支撑/HUD框架.md) :60、:247 | B 区内容补「三关背景+连续地面层」;布局几何清单补地面层高 | 同上 |
| [数据配置.md](../design/gdd/systems/表现与支撑/数据配置.md) :73 | 布局表用途句补「地面层高度」 | 同上 |
| [体验验证清单.md](../体验验证清单.md) | 三关背景可辨、无光柱、地面非瓷砖/非亮面、结算带压底带等目检项如要转正式条目 | 实现批禁写;实现报告登记,转条目走反哺点 |
| [game/tests/README.md](../game/tests/README.md) | 新增「B 区舞台背景三关变体与连续地面层」能力行与覆盖域表 | 写卡段已入表;实现批只核对名实,不再修改 |
| [architecture.md](../design/engineering/architecture/architecture.md) | 无字段级陈述需要改;本批不新增容器/类,仅舞台视图内部图层 | 无同步义务 |
## 七、落位与可复用性预检
### 7.1 新增件与新增成员
| 新增件/成员 | 复用面查询结论 | 唯一面 | 分层与交互路径 |
|---|---|---|---|
| `UiKit.TEX_STAGE_BG_FMT` | 全仓无背景路径常量;`UiKit` 已是场景件/角色件/图标路径的唯一装载单点(`TEX_STAGE_PLAZA` 先例),不新建路径件 | 背景路径格式只在 `ui_kit.gd` 一处 | 舞台视图经 `UiKit.load_tex` 装载;不直连 ResourceLoader |
| `UiKit.TEX_STAGE_GROUND` | 同上;地面是唯一共用场景件 | 地面路径只此一处 | 同上 |
| `BattleStageView.set_board_type()` | 舞台无任何板类型入口;棋盘视图的 `tile_palette.load_board_tiles` 只管瓦片,不复用其选择逻辑(职责不同) | 舞台选图只在这一方法 | 组合根在 `board_changed` 后调用;舞台不反向读结算内部 |
| `BattleStageView.bg_texture` / `ground_layer` | 舞台现无背景纹理层与地面层;不复用 `Panel` 平色底(平色底保留为回退) | 两层各一枚,几何只由布局表与舞台锚点决定 | 都是舞台子 Control,位于世界 SubViewport 之下 |
| `BattleStageView._load_stage_texture()` | 现有 `UiKit.load_tex` 是公共单点;此私有薄封装只服务缺图回退的可测性,不复制资源路径 | 背景与地面装载都经此一处 | 只被本件 `set_board_type`/`_build_ground` 调用 |
| `BattleLayoutTable.ground_h` + `_ground_field_errors()` | 布局表是分区几何唯一事实源;不把地面高塞进 `BattleStageView` 常量 | `ground_h` 只在布局表;校验只在此 schema | ConfigDB 加载期 `validate()` 调用;视图经容器读取 |
| `tools/layout_config.py` FIELDS 补 `ground_h` | 工具读取单点已存在;只补字段,不新建读取器 | 工具侧字段清单只此一处 | 样张工具与游戏侧同源读表 |
| `stage_background_test.gd` | 现有 `standee_present_values_test` 是「战斗一屏样张批 V5–V9」专用套件;`layout_probe` 是场景探针。两者职责都不覆盖「背景选图/地面几何/缺图回退」单元面 | 舞台背景与地面层单元断言唯一落点 | `run_all.gd` 单元入口;舞台直建,不起完整存档 |
| `layout_probe.gd` 追加断言 | 已有真实选路进战斗屏的探针,不新建第二探针 | 真实入口接线断言唯一落点 | `probe_gate.sh` 默认段;读 `main.ui.battle.stage` |
### 7.2 唯一性核查
- 背景路径、地面路径、`ground_h`、`board_type` 归一化规则各只有一处定义:`ui_kit.gd` 两常量、`battle_layout_table.gd` 一字段、`BattleStageView.set_board_type()` 一方法。
- 舞台接板同步只在 `main.gd:_on_board_changed` 与 `main_debug_flow.gd:_on_debug_battle_ready` 两个既有重建点各加一行;不新增第三通知源。
- 小石台绘制保持 `standee_body.gd` 唯一落点;地面层不重画地台,不复制 `_pedestal_rect`。
- 缺图回退只走 `_load_stage_texture` → `UiKit.load_tex` 一条链,不另建资源检查器。
### 7.3 分层与跨层出口
- Core 零改动:`BoardData.board_type` 只读;舞台不导入 core 内部,只接组合根传入的字符串。
- 呈现层内部:布局值经 `ConfigDb.presentation.battle_layout` 单点;纹理装载经 `UiKit.load_tex`;世界内站桩/地台不动。
- 测试面:单元套件直建 `BattleStageView`(与 `pacing_queue_test` 的 `FakeStage` 同型手法);真实入口由 `layout_probe` 从选路按钮进入。
## 八、实现规范预算
| 触面 | 预算 | 结论 |
|---|---|---|
| [battle_stage_view.gd](../game/presentation/views/battle_stage_view.gd) | 类变量 11→14(+`bg_texture`/`ground_layer`/`_bg_board_type`,≤15);公开方法 12→13(+`set_board_type`,≤20);新增私有 `_build_ground`、`_load_stage_texture`;函数长 ≤50、分支 ≤8;文件长 394→目标 ≤470(gdstyle 现无该件基线键) | 通过;T4 后光柱删除会回收约 15 行 |
| [ui_kit.gd](../game/presentation/views/ui_kit.gd) | 加 2 条 const、删 `BEAM_LIGHT` 与 `STAGE_BG`(净 0);不新增变量/方法 | 通过 |
| [battle_layout_table.gd](../game/data/schemas/battle_layout_table.gd) | 类变量 5→6;公开方法仍 1(`validate`);`validate` 现有 7 个 if 不再增分支,地面校验拆 `_ground_field_errors()`(2 个 if、返回 2 次) | 通过;避免 `validate` 9 分支越默认 8 |
| [main.gd](../game/presentation/main.gd) | 既有 `_on_board_changed` 内加局部变量与 2 行守卫同步;不增成员 | 通过;文件无 S13 基线键 |
| [main_debug_flow.gd](../game/presentation/main_debug_flow.gd) | 既有就绪函数内加局部变量与 2 行守卫同步;不增成员 | 通过 |
| [layout_config.py](../tools/layout_config.py) | `FIELDS` +1 字符串 | 通过 |
| [stage_background_test.gd](../game/tests/unit/presentation/stage_background_test.gd) | 新件;公开函数 0(仅 `_init` 与私有测试函数)、类变量 0;预计 ≤220 行 | 通过 |
| 迁移函数 | 本批无函数自存量文件迁入;无 `gdstyle_baseline.txt` 同名函数键 | 通过 |
| 存量触面 | 所有被改 `.gd` 的 S13 键只降不升;超出即停卡 | 通过 |
## 九、文件结构图
| 文件 | 职责 | 改动类型 | 验收行 |
|---|---|---|---|
| [ui_kit.gd](../game/presentation/views/ui_kit.gd) | 背景路径格式常量、共用地贴常量;退役 `BEAM_LIGHT` 与 `STAGE_BG` | 行为改动 | V2/V3/V5 |
| [battle_stage_view.gd](../game/presentation/views/battle_stage_view.gd) | 背景纹理层、连续地面层、`set_board_type()`、缺图回退;平色回退改指 `SLOT_BACKDROP`;退役四柱层 | 行为改动 | V2/V3/V4/V5 |
| [battle_layout_table.gd](../game/data/schemas/battle_layout_table.gd) | 新增 `ground_h` 字段与地面校验辅助 | 行为改动(加载期校验) | V1 |
| [battle_layout.tres](../game/data/tables/battle_layout.tres) | 回填 `ground_h = 100` | 行为改动(数据表) | V1/V4 |
| [layout_config.py](../tools/layout_config.py) | 工具读取字段补 `ground_h` | 非游戏行为(工具维护) | V1 |
| [main.gd](../game/presentation/main.gd) | `_on_board_changed` 重建棋盘后同步舞台板型 | 行为改动 | V6 |
| [main_debug_flow.gd](../game/presentation/main_debug_flow.gd) | 调试对局就绪同步舞台板型 | 行为改动 | V6 |
| [layout_probe.gd](../game/probe/layout_probe.gd) | 真实入口追加背景/地面装载断言 | 非行为改动(探针断言) | V6/V7 |
| [theme_projection_test.gd](../game/tests/unit/presentation/theme_projection_test.gd) | `STAGE_BG` 对比锚改读 `SLOT_BACKDROP`(合并目标,阈值不变) | 非行为改动(测试改读) | V5 |
| [ui_contrast_probe.gd](../game/probe/ui_contrast_probe.gd) | 舞台底对比锚改读 `SLOT_BACKDROP`(合并目标,阈值不变) | 非行为改动(探针改读) | V5/V7 |
| [stage_background_test.gd](../game/tests/unit/presentation/stage_background_test.gd) | 新建单元套件:字段/选图/回退/地面几何/光柱退役 | 非行为改动 | V1–V5/V8 |
| [run_all.gd](../game/tests/run_all.gd) | 登记新套件 | 非行为改动 | V8 |
| [README.md](../game/tests/README.md) | 能力行与覆盖域表 | 非行为改动;**写卡段已入表** | V8 |
| `game/assets/art/scene/scene_stage_bg_*.png` ×3、`scene_stage_ground.png` | 开工前置资产,非本批写面;实现期只读装载 | 输入件 | V2/V3/V4 |
## 十、任务卡
### T0 开工基线与资产前置(0.25d)
取用:
- 待办清单条目状态=美术设计已闭合+已写卡;本卡路径。
- 候选过审记录:`artwork/2026-10-30-战斗区背景/候选保存清单-2026-10-31.md`(工作区文件,不入 git)。
步骤:
- [ ] 读 `game/tests/.gates/ci-status.json`;CI 红未修复即停本卡,禁开新批。
- [ ] 核对四件终稿已在包:`game/assets/art/scene/scene_stage_bg_dungeon.png`、`scene_stage_bg_underdark.png`、`scene_stage_bg_deep_underdark.png`、`scene_stage_ground.png`;用 PIL 读数:三张背景恰为 `(1280, stage_h)`、地面恰为 `(1280, ground_h=100)`。缺位或尺寸不符=L3 停卡,退回 asset-ingest;禁在实现期自行裁图/缩图。
- [ ] 复核第三节 1–22 行的 file:line 与实数;漂移先停卡核对,不靠猜行号施工。
- [ ] 跑 `python tools/gdstyle_gate.py` 记录本批触面当前读数;另记录 `battle_stage_view.gd` 行数/类变量/公开方法数、`battle_layout_table.validate()` 分支数。
- [ ] `grep -rn "STAGE_BG" game` 记录四处现行引用:`ui_kit.gd` 常量、`battle_stage_view.gd` 绘制点、`theme_projection_test.gd:669`、`ui_contrast_probe.gd:30`;T4 收口时四处全部处置。
- [ ] 写开工闸记录:基线 commit、既有红项、资产四件尺寸读数、S13 读数。
产出:资产齐盘、代码事实无漂移、预算基线可对账。
### T1 布局字段 `ground_h` 与读表口径(0.5d)
取用:T0 确认的表结构;`ConfigDb` manifest 已登记 `battle_layout`。
接口块:
```gdscript
@export var ground_h: int = 100
func validate() -> Array
func _ground_field_errors() -> Array
```
步骤:
- [ ] 在 [battle_layout_table.gd:7](../game/data/schemas/battle_layout_table.gd#L7) 的 `stage_h` 后新增 `@export var ground_h: int = 100`,注释写「B 区连续地面层高(源 = 基准屏宽 × 本值)」。
- [ ] 在 [battle_layout_table.gd:14](../game/data/schemas/battle_layout_table.gd#L14) 的 `validate()` 末尾追加 `errs.append_array(_ground_field_errors())`;不把两个新 if 直接塞进 `validate()`(保持分支 ≤8)。
- [ ] 新增私有 `_ground_field_errors() -> Array`:`ground_h < 16 or ground_h > stage_h / 2` 报 `domain`;`ground_h <= log_band_h_dig` 报 `cross_field`(地面层不得被收起态明细带整条盖住)。消息含字段名与实际值。
- [ ] 在 [battle_layout.tres:7](../game/data/tables/battle_layout.tres#L7) 的 `stage_h = 252` 后写 `ground_h = 100`;其余五值不动。
- [ ] 在 [layout_config.py:12](../tools/layout_config.py#L12) 的 `FIELDS` 元组中 `stage_h` 后加 `"ground_h"`。
- [ ] 新建 [stage_background_test.gd](../game/tests/unit/presentation/stage_background_test.gd),先写 `_test_layout_ground_field()`:
1. `load("res://data/tables/battle_layout.tres")`,断言 `ground_h == 100` 且 `validate()` 为空。
2. 用 `BattleLayoutTable.new()` 三态:`ground_h=20`(≤log_band_h_dig=24)、`ground_h=200`(>252/2)、`ground_h=100`;断言前两态各返回一条含 `ground_h` 的错误,第三态无 ground 相关错误。
- [ ] 在 [run_all.gd:191](../game/tests/run_all.gd#L191) 邻近 presentation 区追加:
`{"path": "res://tests/unit/presentation/stage_background_test.gd", "expect": 0}`
- [ ] 验证步骤:
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/unit/presentation/stage_background_test.gd`
`python -c "from tools.layout_config import load; print(load()['ground_h'])"` → 必须输出 `100`。
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/unit/data_config/config_db_test.gd` → 绿。
验收:布局表单源有 `ground_h`,校验拒绝越域与「被收起带整条盖住」,游戏侧与工具侧读同值。
产出:`ground_h` 字段、schema 校验、工具读取与 `_test_layout_ground_field`。
### T2 背景层与 `board_type` 选图(1.0d)
取用:T1 的布局表;`UiKit.load_tex`;`BoardData.board_type`;`board_changed` 信号。
接口块:
```gdscript
const TEX_STAGE_BG_FMT := "res://assets/art/scene/scene_stage_bg_%s.png"
var bg_texture: TextureRect
func set_board_type(board_type: String) -> void
func _load_stage_texture(path: String) -> Texture2D
```
步骤:
- [ ] 在 [ui_kit.gd:250](../game/presentation/views/ui_kit.gd#L250) 邻近 `TEX_STAGE_PLAZA` 新增 `TEX_STAGE_BG_FMT`;注释写「三关背景按 board_type 选图,不走 tint」。
- [ ] 在 [battle_stage_view.gd:14](../game/presentation/views/battle_stage_view.gd#L14) 成员区新增 `var bg_texture: TextureRect` 与 `var _bg_board_type := ""`。
- [ ] 在 [battle_stage_view.gd:37](../game/presentation/views/battle_stage_view.gd#L37) 的 `_build_backdrop()` 中,平色 Panel 之后新增全幅 `TextureRect`:`set_anchors_preset(PRESET_FULL_RECT)`、`expand_mode=EXPAND_IGNORE_SIZE`、`stretch_mode=STRETCH_SCALE`、`mouse_filter=IGNORE`、初始 `visible=false`;随后调用 `set_board_type("dungeon")`。
- [ ] 新增 `set_board_type(board_type: String) -> void`:
- 空串归一为 `"dungeon"`;与 `_bg_board_type` 相同则直接返回。
- 先取 `UiKit.TEX_STAGE_BG_FMT % bt`;为目标缺图且 `bt != "dungeon"` 时再取 `dungeon` 路径;两取都经 `_load_stage_texture`。
- 写入 `bg_texture.texture`;`visible = texture != null`;不得在缺图时抛错或打印产品日志。
- [ ] 新增私有 `_load_stage_texture(path: String) -> Texture2D`,只返回 `UiKit.load_tex(path)`;作为缺图回退的可测单点。
- [ ] 在 [main.gd:367](../game/presentation/main.gd#L367) 前后:把 `current_board()` 存局部变量,`board_view.rebuild(board, ...)` 后加 `if board != null: ui.battle.stage.set_board_type(String(board.board_type))`;不改信号连接与重建顺序。
- [ ] 在 [main_debug_flow.gd:103](../game/presentation/main_debug_flow.gd#L103) 同型:存局部变量、重建后同两行同步;不新增第三个通知源。
- [ ] 在 `stage_background_test.gd` 写 `_test_background_selection()`:
1. 直建 `BattleStageView.new(null, load("res://data/tables/battle_layout.tres"))`;默认应已装载 dungeon 背景,纹理非空且尺寸 1280×`stage_h`。
2. 依次 `set_board_type("underdark")`、`"deep_underdark"`、`"dungeon"`;每次断言 `bg_texture.texture.resource_path` 以对应 `_<board_type>.png` 结尾,且尺寸不变。
3. 断言 `bg_texture.get_index()` 小于 `world.get_parent().get_parent().get_index()`(背景在世界之下)。
- [ ] 写 `_test_background_fallback()`:用 `class MissingUnderdarkStage extends BattleStageView` 覆写 `_load_stage_texture`——`underdark` 路径返回 null、其余走 `UiKit.load_tex`;断言 `set_board_type("underdark")` 后纹理路径为 dungeon。再用全 null 子类断言 `set_board_type("dungeon")` 后 `bg_texture.texture == null` 且 `visible == false`,无异常。
- [ ] 在 [layout_probe.gd:55](../game/probe/layout_probe.gd#L55) 的 `_check_one()` 内追加:`stage.bg_texture` 非空、纹理非空、`resource_path` 以 `_dungeon.png` 结尾(L1 真实入口);记录 `label` 便于两档定位。
- [ ] 窄测:
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/unit/presentation/stage_background_test.gd`
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game res://probe/layout_probe.tscn`
验收:三值各命中对应文件;未知/空串→dungeon;目标缺图→dungeon→平色;真实选路进 L1 后背景为 dungeon。
产出:`TEX_STAGE_BG_FMT`、`bg_texture`、`set_board_type`、两处接板同步、背景选图/回退断言。
### T3 连续地面层与几何(0.75d)
取用:T1 的 `ground_h`;T2 的舞台图层序与 `_load_stage_texture`;T0 已入包的地面件。
接口块:
```gdscript
const TEX_STAGE_GROUND := "res://assets/art/scene/scene_stage_ground.png"
var ground_layer: TextureRect
func _build_ground(layout: BattleLayoutTable) -> void
```
步骤:
- [ ] 在 [ui_kit.gd:250](../game/presentation/views/ui_kit.gd#L250) 新增 `TEX_STAGE_GROUND`;注释写「三关共用、无 board_type 后缀、不吃 tint」。
- [ ] 在 [battle_stage_view.gd:14](../game/presentation/views/battle_stage_view.gd#L14) 成员区新增 `var ground_layer: TextureRect`。
- [ ] 在 [battle_stage_view.gd:27](../game/presentation/views/battle_stage_view.gd#L27) 的 `_init` 中,`_build_backdrop()` 之后、`_build_world_stage()` 之前调用 `_build_ground(layout)`。
- [ ] 新增 `_build_ground(layout)`:全幅 `TextureRect`,`set_anchors_preset(PRESET_BOTTOM_WIDE)` 后四 offset 归零再把 `offset_top = -float(layout.ground_h)`;`expand_mode=EXPAND_IGNORE_SIZE`、`stretch_mode=STRETCH_SCALE`、`mouse_filter=IGNORE`;`texture = _load_stage_texture(UiKit.TEX_STAGE_GROUND)`;`visible = texture != null`。
- [ ] 不修改 `standee_body.gd`;小石台仍在世界内站桩底绘制,天然位于地面层之上。
- [ ] 在 `stage_background_test.gd` 写 `_test_ground_layer_geometry()`:
1. 地面纹理可加载且尺寸 `(1280, layout.ground_h)`。
2. `ground_layer.anchor_left==0`、`anchor_top==1`、`anchor_right==1`、`anchor_bottom==1`;`offset_left==0`、`offset_right==0`、`offset_bottom==0`、`offset_top == -layout.ground_h`。
3. 把 stage 尺寸设为 `Vector2(1280, layout.stage_h)` 并加树一帧后,`ground_layer.size == Vector2(1280, layout.ground_h)`、`ground_layer.position.y == layout.stage_h - layout.ground_h`。
4. `ground_layer.get_index()` 大于 `bg_texture.get_index()`、小于 `world.get_parent().get_parent().get_index()`。
- [ ] 在 [layout_probe.gd:55](../game/probe/layout_probe.gd#L55) 追加:`ground_layer` 可见、`ground_layer.size.y == layout.ground_h`(两档都成立;宽度随档位变化不判)。
- [ ] 窄测:
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/unit/presentation/stage_background_test.gd`
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game res://probe/layout_probe.tscn`
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/unit/presentation/standee_present_values_test.gd`(地台件 V9 不动)。
验收:地面层底边贴 B 区底、高读表、全宽、位于背景与世界之间;小石台仍在其上;缺图时地面隐藏不崩。
产出:`TEX_STAGE_GROUND`、`ground_layer`、`_build_ground`、地面几何断言。
### T4 四柱光柱与舞台底源常量退役(0.5d)
取用:T2/T3 已完成的舞台图层;现有 `UiKit._beams_rect()` 菜单斜光带不在退役面;art-bible §4.1 换色合并③。
步骤:
- [ ] 删除 [battle_stage_view.gd:44](../game/presentation/views/battle_stage_view.gd#L44) 的 `_build_beams_layer()` 调用。
- [ ] 删除 [battle_stage_view.gd:50](../game/presentation/views/battle_stage_view.gd#L50) 的 `_build_beams_layer()` 与 [battle_stage_view.gd:145](../game/presentation/views/battle_stage_view.gd#L145) 的 `_draw_light_beams()`。
- [ ] 删除 [ui_kit.gd:186](../game/presentation/views/ui_kit.gd#L186) 的 `BEAM_LIGHT` 常量;平色回退能力由下一步改指 `SLOT_BACKDROP` 承接。
- [ ] 按 art-bible §4.1 换色合并③:把 [battle_stage_view.gd:39](../game/presentation/views/battle_stage_view.gd#L39) 的 `UiKit.STAGE_BG` 改指 `UiKit.SLOT_BACKDROP`(#3E362C,合并目标);删除 [ui_kit.gd:185](../game/presentation/views/ui_kit.gd#L185) 的 `STAGE_BG` 常量。
- [ ] 把 [theme_projection_test.gd:669](../game/tests/unit/presentation/theme_projection_test.gd#L669) 的 `uikit_s.STAGE_BG` 改读 `uikit_s.SLOT_BACKDROP`;把 [ui_contrast_probe.gd:30](../game/probe/ui_contrast_probe.gd#L30) 的 `UiKit.STAGE_BG` 改读 `UiKit.SLOT_BACKDROP`;两处阈值与断言文案不变,标签可注「合并目标」。
- [ ] 更新 `battle_stage_view.gd` 顶注与 `_build_backdrop()` 注释:去掉「四柱/光柱氛围层」表述,写明「背景三关变体→连续地面→世界站桩;光柱层已退役,不迁入背景;平色回退走合并目标 `SLOT_BACKDROP`」。
- [ ] 在 `stage_background_test.gd` 写 `_test_beams_retired()`:
1. 读 `res://presentation/views/battle_stage_view.gd` 源码,断言不含 `_build_beams_layer`、`_draw_light_beams`、`BEAM_LIGHT`,且含 `UiKit.SLOT_BACKDROP`。
2. `load("res://presentation/views/ui_kit.gd").get_script_constant_map()` 不含 `BEAM_LIGHT` 与 `STAGE_BG`。
3. 断言菜单 `_beams_rect()` 仍在(`haskey("_beams_rect")` 或调用返回 TextureRect),防止误删菜单斜光带。
- [ ] 静态核实全仓代码 `wall_ambient` 仅 `ui_kit.gd:249` 注释一处;不新增该标识符。
- [ ] 窄测:
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/unit/presentation/stage_background_test.gd`
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/unit/presentation/theme_projection_test.gd`
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game res://probe/ui_contrast_probe.tscn`
验收:舞台无光柱层与相关常量;舞台底源常量退场、回退改指合并目标;菜单斜光带与两处对比锚仍绿;缺图态仍无光柱。
产出:光柱层退役、`_test_beams_retired`、注释口径更新。
### T5 回归、渲染闸与产出物(0.75d)
取用:T0–T4 全部产物;`tools/run_all_gates.sh` 为唯一闸入口;独立验收审计未参与实现。
步骤:
- [ ] 运行开发期关联窄测:
`D:/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path game --script res://tests/run_all.gd -- --only=stage_background|standee_present_values|standee_fx_sweep|pacing_queue|theme_projection|config_db`
- [ ] 出红只做红件最小单元复跑;禁在波内追加全量档。
- [ ] 里程碑出口跑一次代码域全套闸:
`bash tools/run_all_gates.sh --code`
- [ ] 回执必须 `all_green=true`、`dirty_game=false`;重点读 `05 渲染闸`:`shot_checker` 的 C 区文字 WCAG ≥4.5、纹理幅度 ≤18、明度三档带 `info>world>bottom` 全过;棋盘三张、菜单、关卡 golden 零变化。任何新增红停卡,禁带红合回。
- [ ] 独立验收审计由未参与实现的会话或子代理执行,产出 `reports/iter<N>-验收审计-<日期>.md`;未过禁合并。
- [ ] 轻闸全绿、合并前写齐三份:
1. `reports/iter<N>-实现报告-<日期>.md`
2. `reports/iter<N>-代拍板追认单-<日期>.md`
3. `reports/iter<N>-反哺点-<日期>.md`
- [ ] 实现报告须含:T0–T5 状态、V1–V8 实跑读数、S13 前后数、资产四件尺寸、渲染闸逐项读数、玩家目检总清单(登记不阻塞:三关背景可辨、无光柱、远景有纵深、地面为泥土非瓷砖且不亮、结算带压住地面底带、站桩踩在连续地面/小石台上)。
- [ ] 反哺点逐条覆盖第六节九个目标;每条写文件、节、原句、拟改句、依据,并明确「实现批未写 design/、未写根流程清单、未写 game/tests/README.md」。
- [ ] 本批不新增 golden、不改 `shot_checker` 阈值、不删既有断言。
完成定义:三份产出物齐全+代码域闸全绿+验收审计通过,才进入合回;合回后按项目现行机制由本地 CI 复验。
## 十一、验证闸:改动—验收对照表
| 需求点 | 改动(文件/行为) | 验收测试(名称+落点) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|---|---|---|---|---|---|---|
| V1 `ground_h` 字段与校验 | schema 加字段+地面校验辅助;表回填 100;工具读取 | `stage_background_test.gd:_test_layout_ground_field`;`config_db_test.gd:_test_manifest_dir_sync` | 单元 | `BattleLayoutTable.validate()`;`ConfigDB.load_tables()` | 表值=100;默认表 validate 空;`ground_h=20` 与 `=200` 各得一条含 `ground_h` 的错误;工具 load() 得 100 | 新增:B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) |
| V2 背景按 board_type 选图 | `TEX_STAGE_BG_FMT`+`set_board_type`+两处接板同步 | `stage_background_test.gd:_test_background_selection`;`layout_probe.gd:_check_one` | 单元+探针 | `BattleStageView.set_board_type()`;`level_screen.press_candidate(0)`→`board_changed` | 三值纹理路径逐值对应且尺寸 1280×252;L1 真实进入后路径以 `_dungeon.png` 结尾 | 新增:B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) |
| V3 缺图回退 | `_load_stage_texture`+回退链 | `stage_background_test.gd:_test_background_fallback` | 单元 | `BattleStageView.set_board_type("underdark")`(子类缺图) | 目标缺→dungeon 路径;全缺→`texture=null`、`visible=false`、无异常 | 新增:B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) |
| V4 连续地面层几何 | `TEX_STAGE_GROUND`+`_build_ground` | `stage_background_test.gd:_test_ground_layer_geometry`;`layout_probe.gd:_check_one` | 单元+探针 | 舞台构造+真实进战斗屏 | 纹理 1280×100;anchor 0/1/1/1;`offset_top=-100`;1280 档 `size.y=100`;图层序 bg<ground<world;探针两档 `size.y=ground_h` | 新增:B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) |
| V5 四柱光柱与舞台底源常量退役 | 删舞台光柱层、`BEAM_LIGHT`、`STAGE_BG`;回退改指 `SLOT_BACKDROP` | `stage_background_test.gd:_test_beams_retired`;`theme_projection_test.gd:_smoke_contrast_inks`;`ui_contrast_probe.gd:_ready` | 单元+探针 | `BattleStageView` 构造+`UiKit` 常量表;`ui_contrast_probe.tscn` | 舞台源码零 `_build_beams_layer`/`_draw_light_beams`/`BEAM_LIGHT` 且含 `UiKit.SLOT_BACKDROP`;UiKit 常量表无 `BEAM_LIGHT`/`STAGE_BG`;菜单 `_beams_rect` 仍在;两处舞台底对比锚读合并目标且阈值不变 | 新增:B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) |
| V6 接板真实链路 | main 与调试就绪两处同步 board_type | `layout_probe.gd:_check_one`;`stage_background_test.gd:_test_background_selection` 的源码锚 | 探针+单元 | `level_screen.press_candidate(0)`→`board_changed` | L1 舞台背景路径为 `_dungeon.png`;源码锚 `main.gd` 与 `main_debug_flow.gd` 均含 `stage.set_board_type(` | 新增:B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) |
| V7 既有呈现回归 | 不改站桩/明细/棋盘;只换舞台底图 | `standee_present_values_test.gd:_init`;`standee_fx_sweep_test.gd:_init`;`pacing_queue_test.gd:_init`;`layout_probe.gd:_check_one` | 单元+集成+探针 | 现有各套件真实入口 | 地台 48×12、站桩几何、排播、三区几何全绿;渲染闸 shot_checker 三项与明度带全过;棋盘/菜单/关卡 golden 零变化 | 既有:站桩敌人呈现与结算演出落点;既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
| V8 能力行名实与套件登记 | `run_all.gd` 登记;README 写卡段入表 | `run_all.gd` manifest 与整套 `stage_background_test.gd` | 单元 | `res://tests/run_all.gd` | 套件在 manifest 且 exit 0;能力行代表用例与函数名逐字一致;`capability_audit` 零红 | 新增:B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) |
落点集中:V1 归 T1;V2/V3/V6 归 T2;V4 归 T3;V5 归 T4;V7/V8 归 T5。全表名实核对归 T5 与独立审计。
## 十二、测试方式与测试削弱申报
自动验证:
- V1–V6 全部从真实入口或舞台直建公共面驱动;缺图路径用子类覆写 `_load_stage_texture` 构造观测,不改包内资产、不注入破坏。
- 真实接板链路只认 `board_changed` 与调试就绪两条既有入口;不建后门 API、不在产品码写测试专用分支。
- 渲染闸为窗口化实跑;`shot_checker` 阈值与 golden 不因本批改动。
真人目检(登记不阻塞,写入实现报告):
- 三关背景可辨为不同洞窟(地精暖石/卓尔冷蓝灰/灰矮人灰黑),远景有纵深、非贴墙、无孤立圆柱贴顶。
- 背景无光柱/光带/光源实体;任何缺图态也不出现光柱。
- 连续地面读作泥土/碎石,不是瓷砖/石板;全幅只零星小石、不成排成堆;中低明度不刺眼。
- 站桩与小石台踩在连续地面上;结算期明细带压住地面底带,不出现半截地台/悬空。
- B 区文字(轮次牌、演出提示、明细带)对背景/地面可读,无字压纹理。
测试削弱申报:
- 零删除、零放宽、零换下层直调。唯一允许的改读:`theme_projection_test.gd:669` 与 `ui_contrast_probe.gd:30` 的舞台底对比锚由 `STAGE_BG` 改读 `SLOT_BACKDROP`(art-bible §4.1 换色合并③,目标色 #3E362C);阈值、断言文案与覆盖不变。
- 舞台四柱层退役不涉任何现存断言(全仓核实:光柱断言只针对菜单 `UiKit._beams_rect`)。
- `layout_probe` 只追加背景/地面断言,不改既有三区几何判据。
- 若实现期发现任何既有断言因换图而红,先停卡呈报并列入本表,禁静默删/改阈值。
## 十三、估时与切分预案
| 卡 | T0 | T1 | T2 | T3 | T4 | T5 | 合计 |
|---|---:|---:|---:|---:|---:|---:|---:|
| 工作日 | 0.25 | 0.5 | 1.0 | 0.75 | 0.5 | 0.75 | **3.75d** |
浮动 ±0.75d(渲染闸首跑与两档探针等待占大头)。
切分预案:若 T2/T3 超软盒,段一=T0–T2(资产前置、布局字段、背景选图,约 1.75d);段二=T3–T5(地面层、光柱退役、闸与产出物,约 2.0d)。两段各自可测;段一合回前必须保证光柱层仍在时背景已正确显示(不半删),段二再退役光柱。禁在段一合回。
## 十四、异常分级
L1(自救一次):
- 编译错误、签名拼写、`run_all.gd` 登记遗漏、测试 helper 顺序。
- 注释措辞与私有局部变量命名。
L2(记录继续;同一红连续三次升 L3):
- 与本批无关的存量红,先按回执归因并留档。
- 行数较 T0 预期漂移但 S13 键不升。
L3(立即停卡写报告):
- CI 状态红未修。
- 四件资产缺位或尺寸不符(停卡退回 asset-ingest;禁实现期裁图代偿)。
- 机检键/计数与卡片契约互斥;**上游缺陷停卡退回写卡段,禁为凑绿保留无效成员或造第三条路**。
- `battle_stage_view` 类变量 >15、公开方法 >20,或 S13 基线外新增键无法在不改契约下消除。
- `ground_h` 校验与既有跨字段校验冲突,或必须改 `log_band_h_*` 才能成立。
- 渲染闸新增红(文字对比、纹理幅度、明度三档带、golden)且不属于可归因的既有存量红。
- 任何验收行无法从真实入口绑定特有可观测提交面。
- 必须改 `design/`、根流程清单或 `game/tests/README.md` 才能过关。
## 十五、代拍板白名单
允许实现期自行拍板:
1. 私有函数在指定文件内的顺序、局部变量名;签名与行为不变。
2. 测试 helper 的顺序与断言消息措辞;不得改判据值、阈值与层级。
3. 注释与日志文案;不得引入「光柱仍在」类误导表述,不得写变更历史。
4. `TextureRect` 的 `expand_mode`/`stretch_mode` 写法细节,只要满足基准档 1×、全幅锚点与尺寸判据。
5. B 区 1px 面板描边的可见性处理(被背景覆盖或另加描边薄层均可);不得为描边缩放/裁切纹理,且不得新增类变量。
6. 既有错误扫描暴露的本文件纯格式问题,在不改语义范围内一次修净。
超出必须呈报:
- 任何资产尺寸、`ground_h` 取值、`board_type` 词表、回退链顺序、图层序、文件职责、T 卡验收落点。
- 任何对 `shot_checker`、golden、既有断言或探针判据的改动。
- 任何新增 ConfigDB 容器、Core 字段、UI 组件或第二套板类型选择逻辑。
## 十六、待裁点与开工门
待裁点:**零**。
卡内 provisional(不是设计待裁):
- `ground_h = 100`——按候选出图 1280×100 工艺回填;作者后续可直接调表值,不重开设计。
- 背景/地面文件名与路径格式——art-bible/asset-path-map 已定,本卡只落常量。
- 缺图回退链顺序——dungeon → 平色,按 C7 执行。
开工门:
1. 四件终稿已入包且尺寸对(T0 实读);缺位退 asset-ingest。
2. 待办清单条目状态=美术设计已闭合+已写卡,实况载本卡路径。
3. 经 iter-plan 编入迭代后由 `/iter` 发令开工;本卡无迭代外执行通道。
4. CI 绿、T0 基线无漂移。
5. 本卡估时 3.75~4.5 个工作日;是否单独成批或与邻卡凑迭代归 iter-plan,本卡不代裁。