Files
gplan-2/design/dev/architecture/adr-0003-scene-structure-and-board-rendering.md
T

9.3 KiB
Raw Blame History

ADR-0003: 场景结构与棋盘渲染(Scene Structure & Board Rendering)

Status

Accepted(2026-09-12,solo 模式用户授权代决;迭代期可推翻重议) 部分修订(2026-09-23):Decision 3 棋盘渲染形态条款由 ADR-0006 部分取代——棋盘本体定向迁 Node2D 渲染(D 区 Phase A 先行,B 区舞台后续批),「禁盲目迁移」条款解除,其登记的探针耦合成本转为迁移批义务(实证收敛为 _cells 键面 + click_cell + cell_size 三点,公共面契约保持即可零改造)。Alternative 2(逐格 Node2D)的否决理由「无必要」因表现层升级需求不再成立;autoload 清单、类形态、CJK 字体前置等其余条款不变。

Date

2026-09-12

Engine Compatibility

Field Value
Engine Godot 4.7.2-stable
Domain Core / Scripting + UI
Knowledge Risk LOW-MEDIUM(结构决策 LOW;渲染呈现项 MEDIUM——CanvasItem 线条 AA 羽化移除已核实,godot-specialist 校验含 2 项实质修正后通过)
References Consulted docs/engine-reference/godot/(四文件);godotengine/godot#6360(--script 无 autoload)
Post-Cutoff APIs Used None
Verification Required CJK 字体随包发行的显示核对(首次正式导出 checklist 增补项);D1 正式化时若执行 _draw 迁移则另核命中测试/无障碍

ADR Dependencies

Field Value
Depends On ADR-0001(组合根接线纪律)、ADR-0002(project.godot 基线同批落盘)
Enables 正式工程骨架搭建;D1 正式化
Blocks ADR-0004 扫描域(引用本 ADR 的 core 隔离规则)
Ordering Note 棋盘渲染形态裁决(本 ADR §Decision 3)与 ADR-0004 探针耦合——见 Decision 3 的迁移工作项

Context

Problem Statement

正式工程骨架需要定稿:autoload 清单、core/presentation 的类形态与目录结构、棋盘渲染的实现路径。切片已验证一套形态,但初稿 ADR 把"自绘 _draw()"当作切片事实——godot-specialist 校验发现切片 BoardView 实为 GridContainer + 逐格常驻控件,本 ADR 按校验修正。

Constraints

  • Core 层零 UI 依赖、headless 可跑(D2 Rule 7);--script 模式下 core 禁裸引用 autoload 全局标识符(编译期即炸——见 ADR-0004)
  • 同屏 draw calls < 200;棋盘 ≤12×12(MVP 量级)+数字/小人/旗/变异多层叠加(视觉锚绘制优先级栈)
  • 领域命名规范(docs/code-conventions.md:禁 ID 前缀、头注溯源)

Requirements

  • 切片验证过的结构不推倒(用户拍板"按常规老路子")
  • 呈现层与核心的写边界:核心写调用唯一发生在组合根
  • 中文文案可显示(运行时默认字体无 CJK 字形——specialist 核实)

Decision

1. autoload 清单 = {ConfigDB, RngService}(定名锁定),仅此两个。 战斗编排器等核心类为普通类、由组合根按局实例化——非 autoload、非场景节点。

2. 类形态与目录结构:core/ 纯逻辑类 = RefCounted;ConfigDB/RngService = autoload Node 单例(引擎约束:autoload 脚本必须 extends Node);presentation/ = Control 派生视图单元。

res://
├── core/            # RefCounted 纯逻辑(board_generator / minesweeper_rules /
│                    #   action_economy / battle_orchestrator / unit_container /
│                    #   status_container / reward_economy / level_runner / 数据类)
│                    #   —— 零 Control 引用、零 .tscn preload、零 autoload 全局标识符裸引用
├── data/
│   ├── schemas/     # D2 schema 类(Resource 派生——D2 体系,非本 ADR 变更项)
│   └── tables/      # .tres 数值表(单一事实源)
├── presentation/
│   ├── views/       # 九单元:BoardView / HUDView / BattleLogView / ItemWindowOverlay /
│   │                #   NodeOverlay / LevelStripView / TunePanel / UiKit
│   ├── hud_presenter.gd
│   └── main.tscn + main.gd   # 组合根:模式流转 + 信号接线 + 核心写调用唯一落点
├── smoke/           # 冒烟脚本 + 探针场景(ADR-0004)
└── docs/architecture/

3. 棋盘渲染形态:MVP 沿用切片已验证形态——GridContainer + 逐格常驻控件(BoardView 持 _cells,refresh 内逐格更新);自绘 _draw() 迁移登记为 D1 正式化候选工作项(非本 ADR 承诺)。

  • specialist 校验事实:切片 BoardView = GridContainer + 逐格 Button(_paint_cell 逐格更新),三探针与该形态耦合(ui_probe 断言 _cells 非空、click_probe 依赖 click_cell 入口)。初稿"_draw 是切片形态的正式化"不成立,按事实修正。
  • 形态对比留档:逐格控件(现状)= 命中测试/悬停/焦点由引擎承担、探针兼容;代价 = 控件树随格数增长(12×12=144 控件,实测无压力)。_draw() = 单 draw call、绘制优先级栈完全可控;代价 = 自建命中测试/悬停 + 三个探针改造(_cells 断言与 click_cell 入口失效)+ 无障碍面缺失 + 需补 Viewport.push_input 端到端输入探针。
  • 裁决:D1 正式化 GDD 评审时按当时视觉需求(biome 色板、雾纹理、动效复杂度)二选一;在此之前禁盲目迁移(探针改造是隐藏成本)。任一形态下 CanvasItem 线条 AA 羽化移除(4.7)需注意——格边框用填充 draw_rect 不受影响。

4. CJK 字体前置(specialist 补登,两种形态都受影响):Godot 运行时默认字体不含 CJK 字形——全部中文文案(按钮/标签/结算明细)必须随包发行 CJK 字体并设为 theme 默认字体。登记为 D1 正式化硬性前置项 + 首次导出 checklist 项。

Architecture Diagram

见 docs/architecture/architecture.md System Layer Map + Module Ownership(本 ADR 是其工程形态落点)。

Key Interfaces

  • 组合根 = 唯一核心写调用落点(settle_batch / submit_window_selection / runner 推进)——切片纪律转正
  • 视图单元 = 信号外发 + setter 只读注入(BoardView 只读 A2、动作信号外发不碰核心写)

Alternatives Considered

Alternative 1: 战斗编排器设为 autoload

  • Cons: 编排器持有跨局状态却永生——生命周期与战斗域契约冲突(Uninit/BattleOver 状态机要求按局重建);与"autoload = 全局基础设施"边界冲突。
  • Rejection Reason: 切片形态(按局实例化)已验证且语义正确。

Alternative 2: 棋盘 = 每格一个 Node2D

  • Pros: 独立节点动画/模组方便。
  • Cons: 每节点处理开销与 Control/Node2D 混管复杂度;无必要(specialist 指出 2D 同材质有批处理,draw call 论据最弱,但节点开销与混管论据成立)。
  • Rejection Reason: 逐格控件已覆盖需求且已验证。

Alternative 3: TileMapLayer 承载棋盘

  • Cons: 4.5 物理分块默认变更(纯视觉不踩,但物理用途即触);瓦片语义与"变体标记/数字/旗多层叠加"不匹配。
  • Rejection Reason: 语义不匹配是硬伤;现形态无此问题。

Consequences

Positive

  • 结构与切片零迁移成本;core 隔离规则可静态扫描(ADR-0004)
  • 棋盘形态留有 D1 期复议空间且复议成本已如实登记

Negative

  • 逐格控件形态在 D1 需要高表现力时可能仍需迁移 _draw(成本已登记:探针改造 + 命中测试自建 + push_input 端到端探针)
  • CJK 字体为新增资产义务(发行体积 +)

Risks

  • D1 正式化时遗漏"探针与形态耦合"约束 → 缓解:本 ADR Decision 3 + ADR-0004 探针节双登记
  • core 类被随手加 autoload 裸引用 → 缓解:ADR-0004 静态扫描(parse 期即炸的事实使该风险自暴露)

GDD Requirements Addressed

GDD System Requirement How This ADR Addresses It
d2-data-config.md Rule 7 零 UI 依赖;Rule 2 单点访问 core 隔离规则 + autoload 清单固化(ConfigDB/RngService 定名)
game-concept.md 视觉锚(绘制优先级栈、双通道) 棋盘形态两案对比留档,D1 正式化按锚需求裁决
b1-settlement.md Core Rule 1 编排器按局生命周期 编排器非 autoload、组合根按局实例化
docs/code-conventions.md 领域命名 / 组合根纪律 目录结构与 Key Interfaces 转正

Performance Implications

  • CPU: 144 常驻控件逐格更新——切片实测无压力;_draw 迁移后更优(单 draw call)
  • Memory: 可忽略
  • Load Time: CJK 字体载入一次性成本
  • Network: 不适用

Migration Plan

切片即目标形态(结构零迁移);CJK 字体接入与 _draw 复议归 D1 正式化批次。

Validation Criteria

  • 冒烟 88/88 + 三探针在正式工程维持全绿
  • 静态扫描:core/ 零 Control extends / 零 .tscn preload / 零 autoload 全局标识符裸引用(ADR-0004 域)
  • 中文文案在导出包内显示正常(导出 checklist)
  • ADR-0001(接线纪律)、ADR-0002(渲染器与窗口键)、ADR-0004(扫描域与探针)
  • docs/architecture/architecture.md(Module Ownership / Required ADRs——本 ADR 落定后其 §Required ADRs 第 3 项闭合)