merge: 棋盘 Node2D 迁移批起草——ADR-0006 新立+ADR-0003 部分取代注记+Phase A 方案(用户拍板只迁棋盘+战斗屏进度条退场+LevelStripView 退役不迁移,2026-09-23,台账 140)

This commit is contained in:
DKChan committed 2026-09-23 23:56:41 +08:00
commit ce56e27e1d
3 files changed
+244

No files matched your search

@@ -2,6 +2,7 @@
## Status
Accepted(2026-09-12,solo 模式用户授权代决;迭代期可推翻重议)
**部分修订(2026-09-23)**:Decision 3 棋盘渲染形态条款由 [ADR-0006](adr-0006-board-node2d-rendering.md) 部分取代——棋盘本体定向迁 Node2D 渲染(D 区 Phase A 先行,B 区舞台后续批),「禁盲目迁移」条款解除,其登记的探针耦合成本转为迁移批义务(实证收敛为 `_cells` 键面 + `click_cell` + `cell_size` 三点,公共面契约保持即可零改造)。Alternative 2(逐格 Node2D)的否决理由「无必要」因表现层升级需求不再成立;autoload 清单、类形态、CJK 字体前置等其余条款不变。
## Date
2026-09-12
@@ -0,0 +1,141 @@
# ADR-0006: 战斗棋盘 Node2D 渲染迁移(Board Node2D Rendering Migration)
## Status
Accepted(2026-09-23 用户拍板方向;本 ADR 落文。Phase A 棋盘实施另批执行;B 区舞台迁移为后续批,本 ADR 只定分工不排期)
部分取代 ADR-0003 Decision 3(形态条款定向 Node2D,「禁盲目迁移」解除;autoload 清单 / 类形态 / CJK 字体前置等其余条款不变)
## Date
2026-09-23
## Engine Compatibility
| Field | Value |
|-------|-------|
| **Engine** | Godot 4.7.2-stable |
| **Domain** | UI / 棋盘渲染 |
| **Knowledge Risk** | MEDIUM(SubViewport 内 theme 传播与像素缩放纹路两项待实施批实证;其余为已验证引擎面) |
| **References Consulted** | `docs/engine-reference/godot/`;ADR-0003 Decision 3 形态对比留档;art-bible §8.2 画布暂定档 |
| **Post-Cutoff APIs Used** | None |
| **Verification Required** | SubViewport 内 CJK 字体显式注入核对(实施批);分辨率两档装板校验(实施批) |
## ADR Dependencies
| Field | Value |
|-------|-------|
| **Depends On** | ADR-0001(组合根接线纪律)、ADR-0002(渲染器与窗口键)、ADR-0003(场景结构与渲染形态——本 ADR 修订其 Decision 3) |
| **Enables** | 表现层升级(B 区站桩 / 意图三档动画 / P3 演出需要 Node2D 载体);美术终稿资产 1:1 换入的槽位体系 |
| **Blocks** | 无(B 区舞台迁移为本 ADR 分工内的后续批,不阻塞他批) |
| **Amends** | ADR-0003 Decision 3(逐格控件形态维持条款)与 Alternative 2(逐格 Node2D 否决——否决理由「无必要」因表现层升级需求不再成立,节点开销论据维持有效) |
## Context
### Problem Statement
ADR-0003 Decision 3 将棋盘渲染冻结为「GridContainer + 逐格常驻控件」,并登记 _draw/自绘迁移为 D1 正式化候选、迁移前禁盲目动手(探针耦合是登记成本)。2026-09-23 用户拍板:表现层走 Node2D 重构,**只迁战斗棋盘**,开始菜单(ui_assembler build_start_overlay)与各覆盖层保持 Control——分工不是替换。原「禁盲目迁移」条款与现行裁决冲突,需要新 ADR 定向解禁并落分工边界。
### Constraints
- 战斗屏四区布局与分区尺寸是 HUD框架 结构冻结项——本迁移只换渲染技术,四区结构、双舞台常驻、尺寸表零改动(战斗屏进度条退场与四区→三区重排由停点前移批按文档修订流程另行落地,与本批解耦)
- 组合根纪律(ADR-0001):核心写调用唯一落点不变;BoardView 信号外发 + 只读注入模式不变
- 性能预算(HUD框架 引用值):同屏 draw calls < 200;进入战斗屏 500ms 内首格可点
- 美术终稿资产全部缺位(样张批未跑)——迁移必须以程序化占位服役为前提,不新增素材前置
- core/ 零 UI 依赖(D2 Rule 7)——本迁移全部发生在 presentation/,逻辑层零接触
### Requirements
- B 区战斗画面(站桩立绘、意图三档动画、受击/死亡演出)的后续迁移不被本批堵死——骨架同构可复制
- 分辨率两档(1280×800 / 1920×1080,2026-09-22 定案)与「格边长按分辨率档位计算」口径(2026-09-18 拍板,推翻两档定值冻结)继续成立
- 三探针(ui_probe / ui_click_probe / ui_layout_probe)与冒烟全量基线不破
## Decision
**1. D 区棋盘本体迁 Node2D 渲染,BoardView 类名与公共面契约保持不变。**
BoardView(`presentation/views/board_view.gd`,现 extends Control + 内部 GridContainer)重构为:Control 壳参与屏幕栅格布局不变,壳内经 **SubViewportContainer + SubViewport + Node2D 世界**(BoardWorld)渲染棋盘。对外契约逐项保持:
| 契约面 | 消费方 | 保持方式 |
|---|---|---|
| 类名 `BoardView` / extends Control | ui_assembler 组装、屏幕栅格布局 | 不变 |
| 信号 `action_requested` / `hover_forbidden` / `chord_attempted` | 组合根动作通道 | 不变 |
| `click_cell(cell, button)` 公共入口 | ui_click_probe 直调路径(ui_click_probe.gd:257–277) | 不变 |
| `_cells` 字典(Vector2i → 格单元) | ui_probe `_cells.is_empty()/.size()` 断言(ui_probe.gd:73/187)、ui_click_probe.gd:97 | 键面不变,值 Button → 格单元 Node2D |
| `board()` / `set_desaturated()` / `set_identity_resolver()` / `set_variant_mask_resolver()` / `set_cell_area()` / `rebuild()` / `refresh()` | 组合根与探针 | 不变 |
| `cell_size` 只读属性 | ui_layout_probe `get("cell_size")`(现返回 null——`_cell` 为私有名) | 增补只读属性,顺手修正 |
**2. 渲染技术分工表(本 ADR 核心裁决——「三块模型」)。**
战斗屏渲染技术按内容形态切分,与屏幕布局正交。**战斗屏目标形态 = B/C/D 三区**(2026-09-23 用户裁定:战斗画面不再保留关卡进度条——战斗结束后返回关卡画面,节点链进度只留关卡画面):
| 内容 | 渲染技术 | 批次 |
|---|---|---|
| D 区棋盘本体(格面/数字/旗/徽章/变异纹带/高亮/微光) | **Node2D**(本 ADR) | Phase A(本批立项) |
| B 区战斗舞台(主角/敌人站桩、意图三档动画、受击/死亡演出、FX) | **Node2D** | Phase B(后续批,本 ADR 只定分工) |
| A 区关卡进度条 | Control | **战斗屏退场且代码退役**(裁定见下;退场落地随停点前移批——流程未倒置前 A 区仍是战斗中唯一节点链可视面,先删致盲,本批不动其现状) |
| C 区角色信息(数据框/状态槽/立绘) | Control | 不动 |
| D 区 AP 条、按钮组、toast 槽 | Control | 不动 |
| B 区结算明细带、回合阶段指示、战斗日志 | Control(文本件) | 不动(Phase B 时留 B 区 Control 半区) |
| 全部弹层(选路/节点/结算/图例/营地/开始菜单) | Control | 不动(2026-09-23 用户拍板) |
**A 区退场形态(2026-09-23 追问裁定)**:LevelStripView **退役,不迁移**;关卡画面**不重新实现**——由 RouteOverlay(整幅节点图选路层,节点态色板语义与压缩条同族、候选按钮与放弃入口在役)升级为常驻页面承接。压缩条唯一存在理由(战斗屏无整图时的常显替代面)随零进度裁定消亡,无独有资产流失;唯一继承面 = 逻辑层节点数据面(runner 只读出口零改动)。退役删除面清单见迁移方案 §1。
**3. 命中测试 = 板级公式换算单点,非逐格 Area2D。**
鼠标输入经 BoardView 壳层 `_gui_input` 接收(Control 已有的矩形命中),格坐标 = `floor(local_pos / 格边长)` 单点公式换算——悬停/点选/双击 chord/长按全部复用现有逻辑入口。不为 144 格建 Area2D(节点开销无必要,Alternative 2 论据沿用);ADR-0003 登记的「自建命中测试」成本由此收敛为一个公式函数。无障碍面缺失为接受后果(沿 ADR-0003 Decision 3 已登记口径,键盘寻格体系延后)。
**4. 素材槽位按圣经 §8.2 暂定档预留,程序化占位继续服役。**
格单元内部为固定叠层序的精灵槽位(砖面 < 变异纹带 < 数字/徽章 < 旗 < 焦点高亮),本批全部槽位由程序化绘制填充(现行占位等价平移);终稿纹理(格面 32×32 暂定档)到位后 1:1 换入,零结构返工。**美术缺口不阻塞本迁移**——样张批终值(格边长×格源占比摩擦,v1.9 待决注记①路线)只换 `set_cell_area` 单点数值,不动架构。
**5. SubViewport 模式为两舞台统一骨架,Phase B 复制不返工。**
Phase B 届时将 BattleStageView 同构改造(PanelContainer → Control 壳 + SubViewport 舞台 + 结算明细带 Control 半区)。本批在 ui_assembler 组装侧不引入「单舞台」写死假设,SubViewport 内 theme/字体注入做成可复用挂点(两舞台共用)。
## Alternatives Considered
### Alternative 1: 维持逐格控件形态(ADR-0003 现行)
- **Cons**: 表现层升级(站桩动画/演出/FX)在 Control 树内无载体,最终仍需二次迁移;两次改造总成本高于一次定向。
- **Rejection Reason**: 2026-09-23 用户已定向 Node2D;本 ADR 职责是把方向落为工程边界。
### Alternative 2: 直挂 Node2D(Control 壳内手挂 Node2D,无 SubViewport)
- **Cons**: 屏幕坐标↔棋盘坐标换算、缩放纪律、两档分辨率适配全部自建;布局联动手工维护。
- **Rejection Reason**: SubViewportContainer 是 Control——容器栅格布局引擎原生参与,鼠标坐标引擎换算,内部分辨率固定使像素缩放纪律有单点可管。
### Alternative 3: 逐格 Area2D 承载命中
- **Cons**: 144 个 Area2D 节点开销与信号接线量;命中语义(相邻约束/chord/长按)仍要自建。
- **Rejection Reason**: 板级公式换算单点已覆盖全部交互语义,物理命中是纯开销。
### Alternative 4: TileMapLayer 承载棋盘
- **Rejection Reason**: ADR-0003 已否(瓦片语义与变体标记/数字/旗多层叠加不匹配),维持。
### Alternative 5: B 区与棋盘同批迁移
- **Cons**: B 区站桩形态绑美术样张批(剪影/动画方案未冻结),混批互卡。
- **Rejection Reason**: 2026-09-23 用户拍板分批——先只迁棋盘,战斗画面 Node 后续完成。
## Consequences
### Positive
- 表现层升级获得渲染载体;棋盘先行验证 SubViewport 骨架,B 区复制模式即可
- BoardView 公共面契约保持——三探针与组合根零改造(实证耦合面仅 `_cells` 键面/`click_cell`/`cell_size`,全部保留)
- 素材终稿 1:1 换入,样张批与渲染批解耦,互不阻塞
- 逻辑层(core/)零接触——MC/模拟试玩/verifier 读数面零影响
### Negative
- Node2D 世界内 theme 不自动继承主场景 Control 主题——CJK 字体与 ui_kit 样式需显式注入(实施批义务,ADR-0003 Decision 4 关联)
- 键盘寻格/无障碍面缺失口径延续(已登记接受)
- 非整数缩放的像素纹路风险(45/36px 锚点 × 32px 格源非整倍)——沿 §8.2 路线归样张批定终值,架构只保证 `set_cell_area` 单点可调
### Risks
- SubViewport 渲染目标在低端机的显存/带宽开销 → 缓解:棋盘区逻辑分辨率小(≤ 12×12×36px 量级),实施批实测帧预算
- 输入路径改 `_gui_input` 后现探针全走 `click_cell` 直调,公式换算无自动化覆盖 → 缓解:实施批增补 push_input 端到端输入探针(ADR-0003 已登记项,本批转义务)
## Migration Plan
Phase A(棋盘,实施另批):BoardView 内部重构 + 探针增补 + 冒烟全量回归 + 文档随批(HUD框架渲染注记/battle.md 实现注记/architecture.md 模块归属行)。Phase B(B 区舞台,后续批):同构复制 + 站桩精灵迁移 + 意图动画承载;开工前置 = 样张批冻结剪影与动画方案。战斗屏进度条退场的 GDD 修订面(HUD框架 四区表、关卡节点地图 节点链常显条款、battle.md 像素布局表与 28px 纵向空间再分配)随停点前移批(关卡画面成为常驻枢纽)落地,不随本批。工程细节见同目录 `board-node2d-migration-plan.md`。
## Validation Criteria
- 冒烟全量绿(现行基线不破);三探针(ui / ui_click / ui_layout)绿
- 新增 push_input 端到端输入探针绿(悬停/左键/右键/chord 各一case)
- 功能等价清单:数字/旗/徽章/危险红/变异纹带/呼吸微光/悬停/路径预览/灰化(set_desaturated)/出生展开区 R₀ 豁免,逐项可点可验
- 性能预算:同屏 draw calls < 200;进入战斗屏 500ms 内首格可点
- 分辨率两档(1280×800 / 1920×1080)装板校验通过(12×12 与 10×10 板各验)
## Related Decisions
- ADR-0003(本 ADR 部分取代其 Decision 3;Alternative 2 否决理由更新)
- ADR-0001(组合根纪律——BoardView 信号外发模式沿袭)
- art-bible §8.2(画布暂定档与缩放纪律)、HUD框架(四区结构冻结与性能预算引用值)、battle.md(格尺寸公式锚点)
@@ -0,0 +1,102 @@
# 战斗棋盘 Node2D 渲染迁移方案(Phase A:仅棋盘)
> 状态:**草稿待审**(2026-09-23 起草,board-node2d-plan-20260923 worktree)。
> 上位裁决:ADR-0006(分工与形态)、用户 2026-09-23 拍板「Node2D 重构只迁战斗棋盘,开始菜单/各覆盖层保持 Control;战斗画面 Node 后续批完成」。
> 本文档是 Phase A 实施批的工程方案;批准后实施批从本文开工,不再另起炉灶。
## 0. 一句话
把 D 区棋盘本体从「GridContainer + 逐格 Button」换成「Control 壳 + SubViewport + Node2D 世界」,BoardView 类名与公共面契约逐项保持——探针与组合根零改造,素材终稿到位后 1:1 换图零返工。
## 1. 目标形态(已与用户确认的三块模型)
战斗屏 = 两块 Node2D 舞台 + 一层 Control 面板。术语校准:Godot 没有「Canvas」节点——面板层是 Control 树(常驻顶层与弹层经 CanvasLayer,现状已如此);Node2D 不参与 Control 容器布局,所以每块舞台包一个 Control 壳(SubViewportContainer)参与屏幕栅格布局,壳内才是 Node2D 世界。
```
BattleScreen(Control 栅格;目标形态 = B/C/D 三区——进度条退场裁定见下)
├── B 战斗画面(Phase B 改造,本批不动)
│ ├── Node2D 舞台壳:主角/敌人站桩、意图动画、演出(后续批)
│ └── Control 半区:结算明细带、回合指示、战斗日志(永久 Control)
├── C 角色信息 .................. Control(不动)
└── D 扫雷图
├── AP 条、按钮组、toast .... Control(不动)
└── BoardView(本批改造对象)
└── SubViewportContainer(Control 壳,参与布局)
└── SubViewport(逻辑分辨率 = 格边长 × 板尺寸)
└── BoardWorld(Node2D)
└── CellUnit × N(Node2D,每格一个)
```
**进度条退场裁定(2026-09-23 用户)**:战斗画面不再有关卡进度条——战斗结束后返回关卡画面,节点链进度只留关卡画面。
**A 区代码命运(2026-09-23 追问裁定):退役,不迁移。关卡画面不重新实现。**
- **关卡画面 = RouteOverlay 升级**:现役选路覆盖层已是整幅节点图 + 全套节点态语义(暗金已过/金当前/暗未达/亮金候选通道/旗朱 Boss 边,与压缩条同一组 UiKit token)+ 候选按钮 + 放弃入口。停点前移批只改开合时机(关卡开始即开、战后返回即开)与流程接线(选路确认不再经兑付停点绕行),渲染本体零重写。
- **LevelStripView 不迁移的理由**:它唯一的存在理由 = 战斗屏上看不到整图时的 28px 压缩常显替代面。地图页上压缩条冗余(整图即进度),战斗屏又已裁定零进度显示——迁过去没有消费者。其语义无独有资产(色板/节点态与 RouteOverlay 同族),单链退化渲染(全链横条)被整图布局天然取代。
- **唯一继承面 = 逻辑层数据面**:runner 只读出口(`nodes()` / `visited_ids()` / 节点编号空间 / `next_candidates()`)零改动——压缩条与整图本来就消费同一份数据,这正是"退役不迁移"成立的根据。
排程事实与修订面:
1. **A 区现状代码继续服役**:当前流程尚未倒置(冒险开局直进战斗,节点图是战后弹层),A 区顶栏是战斗过程中唯一的节点链可视面——先删会致盲。退场落地 = 停点前移批,届时四区→三区。
2. **停点前移批的删除面清单**(退役随该批执行):`LevelStripView` 类、ui_assembler 组装行(:28)、main.gd `strip_view` 引用(:52 等)、ui_probe 两处断言(:77–78 节点条构建检查、:188 报告行)、battle.md A 区条款。
3. **该批的 GDD 修订面**:HUD框架.md 四区结构表(含 B/C/D 是否重新编字母)、关卡节点地图.md 节点链常显条款(常显载体随进度条退役,由关卡画面本体承接)、battle.md 像素布局表(28px 纵向空间再分配)。
## 2. Phase A 范围(本批做)
1. **BoardView 内部重构**(`presentation/views/board_view.gd`):
- 根仍是 Control(类名/extends 不变),子结构 GridContainer → SubViewportContainer + SubViewport + BoardWorld。
- `_cells`:Vector2i → CellUnit(Node2D)字典,键面与现 Dict 同构(探针断言面,见 §4)。
- CellUnit 内部固定叠层序:砖面底 < 变异纹带 < 数字/徽章 < 旗 < 焦点高亮——本批全程序化绘制(`_draw`),等价平移现行视觉;每个叠层留 `texture` 槽位(§8.2 暂定档 32×32),终稿纹理换入即用。
- 现有行为逐项平移:呼吸微光(StyleBoxFlat 边框 → `_draw` 边框)、悬停反白、路径预览、危险红、双击 chord 检测、`set_desaturated`(ShaderMaterial 挂 BoardWorld 材质)。
2. **输入换板**:BoardView 壳层 `_gui_input` 接鼠标 → 格坐标单点公式 `floor(local_pos / cell_edge)` → 复用现有 hover/click/chord/长按逻辑;`action_requested` 信号链不变。
3. **`cell_size` 只读属性增补**:现私有名 `_cell`,ui_layout_probe `get("cell_size")` 读到 null——补只读属性,顺手修正。
4. **push_input 端到端输入探针**(新增,ADR-0003 登记项转义务):合成鼠标事件经真实输入路径打 SubViewportContainer,验悬停/左键/右键/chord 四 case——现探针全走 `click_cell` 直调,公式换算无覆盖,这是唯一新增自动化面。
5. **冒烟全量回归 + 文档随批**:HUD框架.md 渲染技术注记(v0.x 版本行)、battle.md 实现注记(格尺寸公式锚点不动)、architecture.md BoardView 形态行、ui_kit 同步面清点。
**不做**(明确出批):B 区舞台任何改动;素材终稿接入;格边长数值调整(归样张批);键盘寻格/无障碍(沿 ADR-0003 已接受口径)。
## 3. Phase B 预留(后续批,本批只保证不堵死)
- BattleStageView 同构改造:PanelContainer → Control 壳(Node2D 舞台 + Control 文本半区),站桩 StandeeView 从 Control 迁 Node2D 精灵——意图三档动画/受击/死亡演出的载体。
- 本批交付的两个可复用挂点:SubViewport 内 theme/字体显式注入挂点(CJK 字体义务,ADR-0003 Decision 4 关联)、CellUnit 叠层槽位模式(B 区站桩底座同构)。
- Phase B 开工硬前置 = 样张批冻结剪影与动画方案(清单 §1.2 联动条款),与本批无相互阻塞。
## 4. 探针与测量面(实证清单)
| 探针/工具 | 耦合点(实证) | Phase A 处置 |
|---|---|---|
| ui_probe | `board_view._cells.is_empty()`(:73)、`_cells.size()` 对板宽高(:187)、`board()`/`set_desaturated()` | `_cells` 键面同构即绿,零改 |
| ui_click_probe | `click_cell(cell, button)` 直调(:257–277)、`_cells.is_empty()`(:97);**无合成鼠标事件**(grep parse_input_event/push_input 零命中) | 公共方法保留即绿,零改 |
| ui_layout_probe | `get("cell_size")`(:39,现读 null)、`board()` | 增补只读属性(§2.3) |
| smoke 行协议同步闸 | 战斗日志 9 类行格式化(smoke_all.gd:3325+)——**是日志行不是棋盘** | 零影响,全量回归覆盖 |
| MC / 模拟试玩 / verifier | core/ 逻辑层 | 零接触零影响 |
## 5. 性能与预算
- draw calls:CellUnit 同材质 `_draw` 走 2D 批处理,144 格占位态预计个位数批次;预算 < 200 维持(HUD框架 引用值),实施批用 RenderingServer 实测数回填。
- 进入战斗屏 500ms 可交互:SubViewport 创建在 `_ready` 一次完成,无逐帧重建;`set_cell_area`/`rebuild` 只重排子节点。
- SubViewport 逻辑分辨率 = 格边长 × 板尺寸(≤ 36px × 14 格量级),渲染目标显存占用可忽略;低端机帧预算实施批实测。
## 6. 风险与对策
| 风险 | 对策 |
|---|---|
| SubViewport 内 Label 不继承主场景主题(数字/中文渲染空白或字体错) | 实施批第一小步先做 theme/字体显式注入挂点并用 CJK 冒烟验证——ADR-0006 Verification Required 项 |
| 45/36px 锚点 × 32px 格源非整倍缩放出现像素纹路 | 架构只保证 `set_cell_area` 单点可调;数值归样张批(圣经 §8.2 v1.9 注记①路线),本批不裁决 |
| `_gui_input` 与 toast/AP 条控件输入抢占 | D 区内部布局不变(Control 兄弟件照旧),棋盘壳是叶节点,抢占面与现 GridContainer 相同;探针四 case 覆盖 |
| 改造期行为漂移(呼吸微光/chord 时序等隐性手感) | 功能等价清单(ADR-0006 Validation)逐项人工核对 + 探针自动化面 |
## 7. 排期与依赖
| 项 | 估时 | 依赖 |
|---|---|---|
| 本起草批(ADR-0006 + 本方案 + ADR-0003 注记) | 已完成,待审 | 无 |
| Phase A 实施批 | 1–2 天(含探针增补 + 冒烟回归 + 文档随批) | 本方案批准 |
| 样张批(素材侧,另线) | 未排 | 主角候选表态 + 复用批审阅 |
| Phase B 实施批 | 未排(同构复制,估时随 Phase A 实测修正) | Phase A 落地 + 样张批冻结 |
与在飞批的关系:曲线调参双刀扫描(worktree hp-bonus-scan-20260923)与本批文件集零交集;UI 复用候选审阅是素材侧独立线,互不阻塞。
## 8. 验收(实施批完成定义)
ADR-0006 Validation Criteria 全项:冒烟全量绿 + 三探针绿 + 新增 push_input 探针绿 + 功能等价清单逐项可验 + draw calls < 200 实测回填 + 两档分辨率装板校验(12×12 与 10×10 各验)。