Files
gplan-2/docs/architecture/board-node2d-migration-plan.md
T

7.4 KiB
Raw Blame History

战斗棋盘 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 四区栅格,结构冻结不动)
├── A 关卡进度条 ................ Control(不动)
├── B 战斗画面(Phase B 改造,本批不动)
│   ├── Node2D 舞台壳:主角/敌人站桩、意图动画、演出(后续批)
│   └── Control 半区:结算明细带、回合指示、战斗日志(永久 Control)
├── C 角色信息 .................. Control(不动)
└── D 扫雷图
    ├── AP 条、按钮组、toast .... Control(不动)
    └── BoardView(本批改造对象)
        └── SubViewportContainer(Control 壳,参与布局)
            └── SubViewport(逻辑分辨率 = 格边长 × 板尺寸)
                └── BoardWorld(Node2D)
                    └── CellUnit × N(Node2D,每格一个)

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 各验)。