103 lines
9.5 KiB
Markdown
103 lines
9.5 KiB
Markdown
# 战斗棋盘 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 各验)。
|