From d97145ee21aad0a46a1373f52c932c4bd8a9c6e4 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 10 Nov 2026 03:54:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A3=8B=E7=9B=98=E6=9D=90=E8=B4=A8=E8=BF=87?= =?UTF-8?q?=E5=AE=A1=E4=B8=8E=E5=8D=A1=E7=89=87=E6=94=B6=E5=8F=A3:=20512?= =?UTF-8?q?=C3=97512=20=E4=B8=89=E5=85=B3=E5=B2=A9=E9=A1=B6/=E5=9C=B0?= =?UTF-8?q?=E9=9D=A2=E5=AE=9A=E7=A8=BF=E3=80=81=E8=96=84=E8=BE=B9=E4=B8=8E?= =?UTF-8?q?=E6=96=AD=E7=BB=AD=E5=B2=A9=E5=9D=97=E5=8F=A3=E5=BE=84=E8=90=BD?= =?UTF-8?q?=E6=96=87=E2=80=94=E2=80=94art-bible=20v3.53(=C2=A73.2=20?= =?UTF-8?q?=E5=8F=97=E5=85=89/=E5=B4=96=E9=9D=A2/=E6=9D=90=E8=B4=A8/?= =?UTF-8?q?=E6=8A=95=E5=BD=B1=E3=80=81=C2=A78.1=20=E8=BF=87=E5=AE=A1?= =?UTF-8?q?=E8=B5=84=E4=BA=A7=E8=A7=84=E6=A0=BC=E3=80=81=C2=A78.5=20?= =?UTF-8?q?=E5=9C=B0=E5=BD=A2=E7=BB=93=E6=9E=84=E4=BE=8B=E5=A4=96)?= =?UTF-8?q?=E3=80=81battle.md=20=E5=86=85=E5=B5=8C=E4=B8=89=E5=85=B3?= =?UTF-8?q?=E8=BF=87=E5=AE=A1=E5=AE=9E=E5=9B=BE=E4=B8=8E=E5=83=8F=E7=B4=A0?= =?UTF-8?q?=E5=88=A4=E6=8D=AE=E3=80=81asset-path-map/=E4=B8=A4=E6=B8=85?= =?UTF-8?q?=E5=8D=95/=E5=BE=85=E5=8A=9E=E5=AE=9E=E5=86=B5=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=EF=BC=9B=E9=9C=80=E6=B1=82=E5=8D=A1=E7=89=87=20T-A=20?= =?UTF-8?q?=E5=85=AD=E9=A1=B9=E5=AE=8C=E6=88=90=E3=80=81=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=AE=9A=E4=B9=893/9=E4=B8=8ET3/T4/T7/=C2=A712=20=E5=85=A8?= =?UTF-8?q?=E8=A1=A820=E7=BB=84=E5=86=85=E5=AE=B9=E9=94=9A=E6=94=B6?= =?UTF-8?q?=E5=8F=A3=E3=80=81=C2=A716=20=E7=AC=AC=E4=B9=9D=E8=BD=AE14?= =?UTF-8?q?=E6=9D=A1=E7=8B=AC=E7=AB=8B=E5=A4=8D=E6=A0=B8=E5=85=A8=E5=A4=84?= =?UTF-8?q?=E7=BD=AE=E5=B9=B6=E5=A4=8D=E9=AA=8C=E9=80=9A=E8=BF=87=EF=BC=9B?= =?UTF-8?q?7=E5=BC=A0=E6=9D=90=E8=B4=A8=E8=BF=87=E5=AE=A1=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E9=94=9A=E4=B8=8E=E7=94=9F=E6=88=90=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E7=99=BB=E8=AE=B0=20golden/README(=E9=9D=9E=E5=BC=95=E6=93=8E?= =?UTF-8?q?=E5=B8=A7,=E4=B8=8D=E6=9B=BF=E4=BB=A3=20board=5FL*)=EF=BC=9B?= =?UTF-8?q?=E5=87=AD=E6=8D=AE:=20path=5Fcheck=200=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=81pipeline=5Fgate=20PASS(32/58/7/9)=E3=80=81=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=9F=9F=E9=97=B8=E9=AA=8C=E6=94=B6=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E6=97=A0=E6=96=B0=E5=A2=9E=E7=BA=A2=E3=80=81=E5=85=AD=E6=9D=90?= =?UTF-8?q?=E8=B4=A8512=C3=97512=E4=B8=949/6=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/art/art-assets-checklist.md | 10 +- design/art/art-bible.md | 17 +- design/art/art-status-checklist.md | 1 + design/art/asset-path-map.md | 2 +- design/gdd/08-Alpha版本标准.md | 2 +- design/ux/battle.md | 26 ++- game/tests/golden/README.md | 6 + game/tests/golden/board_material_L1.png | Bin 0 -> 23007 bytes .../tests/golden/board_material_L1_digit6.png | Bin 0 -> 4411 bytes game/tests/golden/board_material_L1_hero4.png | Bin 0 -> 4166 bytes game/tests/golden/board_material_L1_top4.png | Bin 0 -> 6709 bytes game/tests/golden/board_material_L1_zoom2.png | Bin 0 -> 9418 bytes game/tests/golden/board_material_L2.png | Bin 0 -> 22930 bytes game/tests/golden/board_material_L3.png | Bin 0 -> 22366 bytes reports/2026-11-09-棋盘材质预览-v2.html | 18 +++ ...‚卡片-棋盘瓦片与立体表现重做批-2026-11-07.md | 153 +++++++++++------- 待办清单.md | 2 +- 17 files changed, 155 insertions(+), 82 deletions(-) create mode 100644 game/tests/golden/board_material_L1.png create mode 100644 game/tests/golden/board_material_L1_digit6.png create mode 100644 game/tests/golden/board_material_L1_hero4.png create mode 100644 game/tests/golden/board_material_L1_top4.png create mode 100644 game/tests/golden/board_material_L1_zoom2.png create mode 100644 game/tests/golden/board_material_L2.png create mode 100644 game/tests/golden/board_material_L3.png create mode 100644 reports/2026-11-09-棋盘材质预览-v2.html diff --git a/design/art/art-assets-checklist.md b/design/art/art-assets-checklist.md index a6a724f1..1bbcde07 100644 --- a/design/art/art-assets-checklist.md +++ b/design/art/art-assets-checklist.md @@ -119,10 +119,10 @@ - **封印印记改为参数化绘制**:形 = 环+十字法阵,由着色器按格边实时画(环径 82% 格宽+环外一圈压暗光),形与定值见 art-bible §3.2 与 §8.2「封印印记参数表」;贴图件仅战末金蜡封徽记继续使用。本节余下面 = 雷格纹样与数字格面。 -- **要什么**:格子样张通过后按冻结参数出全套砖面资产(含图类型换色板组)。 -- **来源**:⚙ 脚本管线自产——未开/已开/危险格/变异纹带是扫雷专属语义(角嵌纹样已不存在),素材站没有对的;砖面**纹理底噪**可 ♻ 用 CC0 无缝石/土纹理作脚本管线的纹理输入,量化到色板(混合路线)。 -- **前置**:§1.1 格子样张通过(**未跑**)。 -- **现状**:程序化绘制,可读性达标(对比硬指标已是现行实现依据),观感待升级。 +- **要什么**:雷格巢穴纹与已开格结果所需的格面语义纹样;棋盘岩顶/地面 6 张材质已由棋盘重做批单独交付,本条不再出逐格墙/地砖面。 +- **来源**:⚙ 格面语义纹样按 art-bible §3.2 与结果整格表达自产,纹样底噪复用已录入的岩顶/地面材质;不另出逐格瓦片。 +- **前置**:格形与三关八色已冻结;6 张材质已于 2026-11-09 录入。 +- **现状**:棋盘地形已改「岩顶/地面=512×512 无缝贴图+崖面/边缘/投影=程序化」,三关 6 张于 2026-11-09 用户目检通过并录入,旧逐格砖面资产套退役;本条不再按逐格砖面出图,雷格纹样/数字格面按 art-bible §3.2 退役后口径处理。 ### 3.4 增益状态效果图标 9 枚 ♻优先/⚙兜底 @@ -204,7 +204,7 @@ | Kenney 全系(ui-pack/fantasy-ui-borders/game-icons/board-game-icons/kenney-fonts/roguelike 系/tiny-dungeon/tiny-town) | CC0 | 无 | ui-reuse 待审;tiny-dungeon 终局否决(架构不适配);余顺带否决;kenney-fonts 拉丁字候选退役(全局字体定稿 Fusion Pixel 单套,不再接入) | | OGA Pixel UI 750(Kenney 作) / PixUI(CamTatz) / Handpainted stone | CC0 | 无 | ui-reuse 待审 | | DENZI public domain art | CC0 | 无 | 否决 | -| beast-cave(OGA) | CC0 | 无 | **已退役**(源包归档;地砖随 2026-11-07 棋盘地形重做退役——棋盘改程序化材质) | +| beast-cave(OGA) | CC0 | 无 | **已退役**(源包归档;地砖随 2026-11-07 棋盘地形重做退役——棋盘改贴图材质) | | JaggedStone / Screaming Brain / ExileGL / Corey Archer(OGA) | CC0 | 无 | 否决 | | Calciumtrice / Buch / bart cobblestone(OGA) | CC-BY 3.0 | **需署名** | 否决 | | LD rogue / Evert cave / poikilos underworld(OGA) | OGA-BY 3.0 | **需署名** | 否决 | diff --git a/design/art/art-bible.md b/design/art/art-bible.md index 2e2ee732..eb9fdf76 100644 --- a/design/art/art-bible.md +++ b/design/art/art-bible.md @@ -1,6 +1,6 @@ # 美术圣经(Art Bible)— Dungeon Sweeper -> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.51,历次修订明细见 git 提交史 +> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.53,历次修订明细见 git 提交史 > > **Art Director Sign-Off(AD-ART-BIBLE)**:历次批均未签核——此为 Lean/Solo 模式(非 PHASE-GATE)下的现行治理状态;full 门禁签核时机待用户表态。 > 风格基调:地牢题材但**非暗黑风**——轻快明亮的幻想冒险风,全年龄;像素风;角色 2~3 头身。 @@ -55,7 +55,7 @@ 3. **焦点预算成立(§3.4)**:任意一格至多一个信息完整凸形(浮空数字/小人/封印印记);岩体为连续地形,不作单格凸形计;数字所在格无第二信息焦点。验收:目检〈任一格至多一个信息完整凸形,数字所在格无第二焦点〉 4. **图类型换皮抽测(§4.3)**:变体组中浮空数字字芯/描边、封印黑、危险红、奖励金、小人蓝、类型微光五组恒定不动;变体岩顶/地面底仍过第 1、2 项指标。验收:机检〈换皮后不变槽色值恒定,变体岩顶/地面底仍过第 1、2 项〉 -**判定与回退**:第 1 项不过时按原则二设计测试回退——先调岩顶/地面明度档,禁止使用数字底牌;浮空字描边是唯一可读性装置,禁止缩字号换字形逃避;第 2–4 项不过时修形不修数。样张通过 = 棋盘地形形态与色板冻结;新增图类型/变异色板须重跑本测试(§4.3)。执行时机:正式地形资产或程序化材质开工前;《HUD框架》以本节为引用依据。验收:机检〈样张机检断言集全绿后方可冻结地形形态与色板〉 +**判定与回退**:第 1 项不过时按原则二设计测试回退——先调岩顶/地面明度档,禁止使用数字底牌;浮空字描边是唯一可读性装置,禁止缩字号换字形逃避;第 2–4 项不过时修形不修数。样张通过 = 棋盘地形形态与色板冻结;新增图类型/变异色板须重跑本测试(§4.3)。执行时机:正式地形贴图资产开工前;《HUD框架》以本节为引用依据。验收:机检〈样张机检断言集全绿后方可冻结地形形态与色板〉 **整屏样张闸**:格子样张验"格",整屏样张验"屏"——战斗屏/关卡屏/菜单屏/营地屏各出一张整屏样张,验收四项:①全部文字(含菜单/说明/tooltip/按钮)对其直接背景 ≥4.5:1(WCAG AA),大字(≥18px 或加粗档)底线 3:1、目标 4.5:1;②明度分层三档带成立(信息面层 > 世界中层 > 世界底层,层间灰度可分);③整屏焦点预算(§3.4:首焦唯一——数字区/立绘/主按钮,无第二焦点竞争;负空间服务焦点,不属空窗);④文字禁直接压纹理底(垫容器或罩层)。**浮空数字为描边字,按 §1.4 第一验收项的复合对比判据,不套本条文字直画 4.5:1 口径。** 验收顺序 = **方向稿目检先行**(防"机检过闸但气质否决"式返工),目检过后机检冻结。执行时机 = 屏级视觉落码开工前;过闸前一切屏级视觉为占位临时态(§7.1 完成条款)。**样张判定物的产出手段与素材输入级别不进圣经定值**——圣经只定样张要验什么,不定样张以何种手段产出、也不定它取哪一级别素材输入。验收:机检〈整屏样张四项断言全绿,且目检先行过审〉 @@ -169,9 +169,9 @@ - **岩体**:圆角岩体堆叠/合并,禁尖刺装饰——尖刺专属危险语义,装饰禁止伪装逻辑差异。验收:目检〈岩体无尖刺装饰〉 ←原三 - **棋盘地形体系|术语与定义**:未开格 = **抬升岩体**——连通的未开格(四邻:上下左右;斜角不连)合并为一块岩体,共享一块岩顶与连续崖面;已开格 = **连续地面**。素材语义名——岩顶材质 = **大岩板**,南/东崖面材质 = **崖面**,已开地面 = **地面**;**不做逐格自含瓦片**,Tiny Dungeon 拼块套与逐格 16+5 墙/地瓦片套均退役(2026-11-07 用户裁)。验收:目检〈连通未开格共享一块岩顶与连续崖面,无逐格拼缝〉 ←原三 - **棋盘地形体系|投影与搭接**:整块岩顶向北偏西抬升——LIFT = round(格边 × 0.435)(46 格 20px、26 格 11px,下限 1),ESHIFT = round(格边 × 0.109)(46 格 5px、26 格 3px,下限 1);南/东崖面沉在岩体格内(南面高 = LIFT,东面宽 = ESHIFT,东面高 = 格边 + LIFT),不侵下一行地面;相邻岩体的岩顶按 2px 互相搭接盖住格缝;板边岩顶向外延伸 ESHIFT 铺到板缘。单个墙格的**顶面 rect** = 格矩形左上偏移 (−ESHIFT, −LIFT)、边长 = 格边;**整格视觉 rect** = 顶面 rect 向右补 ESHIFT、向下补 LIFT。验收:机检〈LIFT/ESHIFT 比例与下限;相邻岩顶搭接 2px;崖面不越格〉 -- **棋盘地形体系|受光与崖面**:光照 = **北/西受光**(2026-11-07 用户裁)——北/西临空缘 = 2px 主亮棱 + 2px 次亮棱(暖白族就地提亮),再外 2px 深墨临空边线;南/东临空缘 = 2px 深墨内缘 + 3 段 ×2px 顶面内阴影(自缘内 0.217×格边起,黑 α≈0.27/0.16/0.08)。南崖面 = 高 LIFT、宽 = 格边 + ESHIFT,顶缘 2px 口沿高光取本关受光棱(§4.1,dungeon `#C9AF83`)+1px 深墨线,面身横向层理叠石(大岩板同族、背光暗面),禁竖条纹栅栏;东崖面 = 宽 ESHIFT、高随岩顶南缘,横向层理、外缘 1px 深墨。验收:目检〈北/西亮棱、南/东内阴影与崖面层理;南崖不越下一行、东崖不越下一列;无竖条纹〉 -- **棋盘地形体系|材质与装饰**:岩顶 = **大岩板**(低频率斑驳 + 稀疏大板块缝 + 板缘浮雕倒角,单块材质覆盖整块岩体;禁逐格小砖纹与逐格边框);地面 = 连续暖褐土(低对比石屑、碎石斑;无缝,禁逐格砖缝);装饰变体 = 岩顶材质内的低对比裂纹/麻点/碎石贴花,走原则三零信息纪律,不新增逐格资产。验收:目检〈岩顶为单块大岩板、无逐格拼缝;地面连续无缝;装饰不构成逻辑线索〉 -- **棋盘地形体系|投影与整板悬崖**:南/东临空岩体在地面投 4 段 ×4px 渐隐影(黑 α 0.44/0.30/0.16/0.07,自崖面外缘起);整板悬崖 = 板底/右侧 `DEPTH_PX 8px` 暗面 + 岩层横纹 + 口沿高光 + 接触 AO + 底线收边 + 悬浮影,色取棋盘环境子板(§4.1)。验收:目检〈南/东投影四段渐隐;整板悬崖结构件齐备〉 +- **棋盘地形体系|受光与崖面**:光照 = **北/西受光**(2026-11-07 用户裁)——北/西临空缘 = 1px 主亮棱 + 1px 次亮棱,再外 2px 深墨临空边线;南/东临空缘 = 3 段 ×1px 顶面内阴影,明暗只负责分界,不形成闭合厚黑框。南崖面 = 高 LIFT、宽 = 格边 + ESHIFT,顶缘 1px 受光口沿+1px 深墨线,面身用低对比、长短不一且彼此错开的岩块面;东崖面 = 宽 ESHIFT、高随岩顶南缘,用断续短纹与外缘 1px 深墨。任何岩层线不得贯通整条崖面,禁规则三角装饰带与竖条纹栅栏。验收:目检〈北/西亮棱与南/东内阴影收薄;崖面岩块断续且低对比;无贯通横线、规则装饰带与竖条纹〉 +- **棋盘地形体系|材质与装饰**:岩顶 = **大岩板**(少量主裂纹、石屑与不规则色斑,单块材质覆盖整块岩体;禁逐格小砖纹、逐格边框与环绕单格的闭合裂纹);地面 = 连续暖褐土(低对比色斑与石屑;无缝,禁逐格砖缝与密集噪点);装饰变体 = 岩顶材质内的低对比裂纹/麻点/碎石贴花,走原则三零信息纪律,不新增逐格资产。三关共用同一母图换色,不另造三套地形。验收:目检〈岩顶主裂纹稀疏且不成方格;地面有质感但不抢数字;整板无重复主裂纹与逐格拼缝〉 +- **棋盘地形体系|投影与整板悬崖**:南/东临空岩体在地面投 4 段 ×4px 渐隐影(南向黑 α 0.25/0.16/0.09/0.04,东向黑 α 0.22/0.14/0.07/0.04,自崖面外缘起);整板悬崖 = 板底/右侧 `DEPTH_PX 8px` 暗面 + 岩层横纹 + 口沿高光 + 接触 AO + 底线收边 + 悬浮影,色取棋盘环境子板(§4.1)。验收:目检〈南/东投影四段渐隐且不抢岩顶;整板悬崖结构件齐备〉 - **棋盘地形体系|绘制序与遮挡**:层序 = 地面(封印格地面铺本关受光棱色封印石)→ 投影 → 数字所属格的**地面阴影圆**(开启格地面,位于小人之下,小人站该格时遮住圆)→ **按脚底 y 排序的深度对象**(岩体 = 其最南格格底;小人 = 所在格格底;升序绘制,南侧岩体自然遮住小人脚底)→ 顶面贴花(类型微光/变异纹带,随岩顶锚点偏移 −ESHIFT/−LIFT;只在未开格岩顶)与交互反馈(悬停/路径/可挖域微光)随所属格件同序——北侧(脚底≤小人)低于小人,南侧(脚底>小人)随岩体在前;封印印记与封印格身份色牌在已揭示地面、固定低于小人(不参与南侧前推)→ **浮空数字+引导线(最顶)**。验收:机检〈深度对象按脚底升序绘制;格件贴花/交互随脚底行分档;浮空层 z 最高〉+目检〈南侧岩体遮住小人脚底;顶行数字越出棋盘仍完整〉 - **棋盘地形体系|浮空数字(信息层)**:数字与格面字形(危/?)脱离格面,浮在格上方——**封印格除外**,其身份字形按封印印记条垫色牌叠于法阵之上、不进浮空层;字高 21px(7px 像素字 ×3,固定不随格边缩放)、2px 深墨描边、字芯暖白 `#F0E2C8`、1px 浮空投影;字底距格顶 15px;引导线 = 2px 双色实线(左深 `#1A140E`/右浅 `#E8D3AB`),自字底 +3 落到格顶 +4;格顶 +7 处画 10×6 四层柔边小阴影圆(标明数字所属格),圆画在开启格地面、位于小人之下,不盖小人。浮空层 z 最高,任何地形/小人/特效不遮数字与引导线。顶行数字出棋盘上缘,D 区上方预留 44px(字高 21+间距 15+描边 2+余量 6)。验收:机检〈字高 21、间距 15、顶预留 44;浮空层 z 最高;封印格无浮空 entries〉+目检〈顶行数字与引导线完整;阴影圆指向正确格〉 - **棋盘地形体系|旧资产处理**:旧 `terrain_*` 63 件(16 墙瓦片 + 5 地面变体,三关各一套)全部退役——无参考价值者直接删除,不归档;`seal_mark.png` 保留(战末金蜡封专用)。验收:机检〈旧 terrain_* 零引用、零在库;seal_mark 在库〉 @@ -519,7 +519,8 @@ ### 8.1 分辨率档位与格边长 - **两档定案**:1280×800(基座)+ 1920×1080,窗口不可调;后续调整走修订。验收:机检〈工程分辨率配置与两档一致〉 -- **格边长取值**:按档位与板形计算——固定档位下格子量增加则格边长相应变小;公式、单位与现行算例的唯一出处 = [battle.md](../ux/battle.md)「棋盘格尺寸公式」,本节不复述数值。资产侧锁两条比例:**棋盘地形不铺逐格瓦片**(岩顶/地面/崖面材质按整板矩形与格边程序化绘制,允许连续缩放——地形材质不适用 §8.2 甲类整数倍纪律)、**棋盘小人显示占位 ≤ 0.75× 格边长**。(1920 档已裁决全局等比缩放)验收:机检〈地形材质随格边/整板绘制、小人占位 ≤0.75×〉 +- **格边长取值**:按档位与板形计算——固定档位下格子量增加则格边长相应变小;公式、单位与现行算例的唯一出处 = [battle.md](../ux/battle.md)「棋盘格尺寸公式」,本节不复述数值。资产侧锁两条比例:**棋盘地形不铺逐格瓦片**(岩顶/地面材质取无缝贴图、按合并岩体与整板一次铺图,UV 用棋盘全局坐标、禁逐格重置;崖面、临空边缘、投影等结构件程序化绘制;允许连续缩放——地形材质不适用 §8.2 甲类整数倍纪律)、**棋盘小人显示占位 ≤ 0.75× 格边长**。(1920 档已裁决全局等比缩放)验收:机检〈岩顶/地面为贴图材质、结构件程序化;地形材质随格边/整板绘制、小人占位 ≤0.75×〉 +- **棋盘地形材质|过审资产规格**:三关岩顶/地面各一张 512×512 无缝 PNG,同一母图换色,单张像素域 ≤32 色;岩顶以少量主裂纹、石屑与不规则色斑构成,地面以低对比色斑与石屑构成,均无边框、无自带亮边、光照均匀。参考图指针 = [asset-path-map](asset-path-map.md) §3 `board/`。验收:机检〈6 张均为 512×512 且单张 ≤32 色〉+目检〈现行最大板内主裂纹不重复;材质无逐格边框,三关数字可读〉 ### 8.2 像素基准与画布 @@ -552,9 +553,9 @@ ### 8.5 结构件完整性与参考核验 -> **白话**:格子读感里的立体结构——顶面、缘件、角件、周界轮廓——必须是素材里**画出来的结构件**;素材缺件就停下报缺,拿调色/渐变/滤镜顶替不是变通,是违规。 +> **白话**:角色、单位与非地形 UI 格件里的立体结构——顶面、缘件、角件、周界轮廓——必须是素材里**画出来的结构件**;素材缺件就停下报缺,拿调色/渐变/滤镜顶替不是变通,是违规。棋盘地形不适用这条,按下方「生产分工」与 §3.2 棋盘地形体系执行。 -- **结构件完整性**:格面立体感(高墙顶面/坡缘/角件/周界轮廓)只能来自**素材本体绘制的结构件拼装**(样例=Necesse 式缘件:专属底色+手绘细节+暗轮廓线的独立贴图);禁止以调色、渐变、明暗滤镜、跨格投影等生成手段伪造素材中不存在的结构。样稿暴露缺件时,正确动作=停下报告缺口与「换素材/自产缺件」选项,由用户裁决后执行。验收:目检〈立体感逐件来自素材本体,无滤镜伪造〉 +- **结构件完整性(适用角色、单位与非地形 UI 格件)**:这些物件的立体感(顶面/坡缘/角件/周界轮廓)只能来自**素材本体绘制的结构件拼装**(样例=Necesse 式缘件:专属底色+手绘细节+暗轮廓线的独立贴图);禁止以调色、渐变、明暗滤镜、跨格投影等生成手段伪造素材中不存在的结构。**棋盘地形是已裁例外**:岩顶/地面走无缝贴图,崖面/边缘/角件/投影走程序化结构(§3.2、§8.1 与下方生产分工),不按本条判违例。样稿暴露缺件时,正确动作=停下报告缺口与「换素材/自产缺件」选项,由用户裁决后执行。验收:目检〈非地形件立体感逐件来自素材本体;地形件按 §3.2 程序结构判据〉 - **参考核验**:宣称「参考 X 游戏」前,必须取得并实际查看 X 的截图证据(像素级放大核验其实现方式),证据存 `artwork/mockups/` 或 `design/art/references/`;仅凭文字资料、记忆或宏观印象作出「X 是这样做」的断言无效。验收:目检〈参考结论有截图证据在库〉 - **图底分离**:已开地面的明度须低于未开格岩体,由材质选型承载(地面基色 `#695038` 低于岩顶 `#9C8462`),不靠渲染压暗实现。验收:机检〈已开地面明度低于岩顶面〉 - **生产分工**:格面地形类素材=**材质归模型、结构归程序**——AI 生图模型只出无缝填充纹理(无边框/无亮边/均匀光照/方形);一切结构件(缘件/轮廓/立面/角件/收头)一律程序化绘制或手修,因为 autotile 任意拼接的边界像素约束超出 2D 生图模型能力(实证:生图 5×5 瓦片表每枚砖自带啃咬边框与宽亮带,提示词无法根除)。**镜像规则**:东西对称结构件只许水平翻转(flip_h)复用、**禁旋转**——北受光下东西侧缘光照对称,镜像无损真;旋转会把北受光转到东边。验收:目检〈瓦片表无自带边框/亮带;对称件仅 flip_h〉 diff --git a/design/art/art-status-checklist.md b/design/art/art-status-checklist.md index c5136bf0..bf63742d 100644 --- a/design/art/art-status-checklist.md +++ b/design/art/art-status-checklist.md @@ -28,6 +28,7 @@ | 格面资源徽章 19 枚 | ◐ | [art-bible](art-bible.md) §4.6 | | 关卡节点图图标组 | ◐ | [art-assets-checklist](art-assets-checklist.md) §3.2(正式 UI 设计未成文) | | 雷/封印印记/数字砖面全套 | ◐ 封印印记已换代(环+十字法阵,参数化绘制);雷与数字砖面仍待格子样张前置 | [art-bible](art-bible.md) §1.4/§3.2 | +| 棋盘岩顶/地面材质 6 张 | ✅ 已交付:三关各一张岩顶+一张地面,512×512、同一母图换色、单张 ≤32 色;2026-11-09 整板与细部预览经用户目检通过,落 `game/assets/art/board/` | [art-bible](art-bible.md) §3.2/§8.1 · [asset-path-map](asset-path-map.md) §3 | | 增益状态效果图标 9 枚 | ✅ 已接入 | [art-bible](art-bible.md) §4.6.1(候选原稿归 candidates 档——路径描述性引用,归档纪律见 art-bible §8.3) | | 营地场景图 | ✅ 已交付:十层在包;背景层 2026-11-07 换代录入(远景 v5+地面 v3 过审、拼接量化 32 色落 `scene_camp_bg.png`);坐标接线归下游实现批(`camp_scene_layout.tres` 仍旧值) | [art-bible](art-bible.md) §6.2 | | 字体(全局 UI 像素字,Fusion Pixel 单套单字重) | ✅ 已定稿在役(用户裁现状即终稿——不另接拉丁专件、不上第二字重) | [art-bible](art-bible.md) §7.4 | diff --git a/design/art/asset-path-map.md b/design/art/asset-path-map.md index 79366e99..7db4d371 100644 --- a/design/art/asset-path-map.md +++ b/design/art/asset-path-map.md @@ -28,7 +28,7 @@ | `character/` | 角色棋盘帧 + B 区立绘 | character_hero_idle/walk(棋盘 32×32 朝左基准)、character_hero_portrait(B 区立绘 46×48)+ character_enemy_<键> 八敌 | | `fx/` | 特效帧 | shovel_swing_f0/f1/f2(挥铲三帧,握把锚 (18,12)) | | `scene/` | **场景图**(背景层 + 地面层 + 围墙层 + 可点物件层;营地场景图首批) | 营地 10 张:`scene_camp_bg`(背景层,不透明全幅=天空+远山+地面+门洞小路)+ `scene_camp_wall`(围墙层,透明底、门洞留透明缺口)+ `scene_camp_gate / forge / chest / notebook / dummy / board / campfire`(七个可点物件)+ `scene_camp_tent`(承载件,不可点)+ `scene_stage_bg_dungeon` / `scene_stage_bg_underdark` / `scene_stage_bg_deep_underdark`(B 区战斗舞台背景层三关变体,✦ 插画级,顶部空区+远景天然洞壁,不画近景地面,按 board_type 选图)+ `scene_stage_ground`(B 区连续近景地面层,✦ 插画级,泥土/砂砾/碎石+顶缘分隔带,跨关恒定)+ `scene_stage_plaza`(B 区角色脚下小石台,48×12 九宫格件)——B 区战斗舞台背景与连续地面已入包;营地 10 张已入包(`scene_camp_*` 十件在役、`TEX_CAMP_*` 十键消费;用户游戏内终审如有置换,按本行键名同径替换) | -| `board/` | 棋盘地形材质(2026-11-07 重做后改程序化绘制,无入包地形 PNG);seal_mark.png 现役用途=战末金蜡封徽记专用(战末弹层消费——棋盘侧贴图绘制路径已退役) | seal_mark.png(战末蜡封专用);旧 `terrain_*` 63 件(16 墙瓦片+5 地面变体×三关)随重做退役删除 | +| `board/` | 棋盘地形材质(2026-11-09 过审:岩顶/地面=512×512 无缝贴图、同一母图换色、单张 ≤32 色;崖面/边缘/投影=程序化);seal_mark.png 现役用途=战末金蜡封徽记专用(战末弹层消费) | `board_rock_.png`/`board_ground_.png` 六张(三关各一套,2026-11-09 用户目检通过并录入);`seal_mark.png`;旧 `terrain_*` 63 件(16 墙瓦片+5 地面变体×三关)随重做退役删除 | ## 4. 坐标/朝向等工程侧约定备查 diff --git a/design/gdd/08-Alpha版本标准.md b/design/gdd/08-Alpha版本标准.md index cc8b62f5..6c54faf0 100644 --- a/design/gdd/08-Alpha版本标准.md +++ b/design/gdd/08-Alpha版本标准.md @@ -146,7 +146,7 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战 | 像素美术风格与色板 | [美术圣经](../art/art-bible.md) | 在役 | | 棋盘瓦片与格面资源图标 | [美术圣经](../art/art-bible.md) | 在役 | | 未开格类型微光(五组色相+明度档) | [HUD框架](systems/表现与支撑/HUD框架.md) | 在役(明度档 provisional 值登记见 art-bible 的 git 提交史;观感复核已随战斗一屏样张过闸完成——用户实机目检核销,沿革查 git 提交史) | -| 棋盘瓦片与立体表现重做 | [待办清单](../../待办清单.md) | 已写卡(待编排)——设计闭合=C 方向+D 布局+三关八色冻结(art-bible v3.51/battle.md 2026-11-07/HUD框架 2026-11-07);卡片=[需求卡片](../../reports/需求卡片-棋盘瓦片与立体表现重做批-2026-11-07.md)(卡内 §16 复核通过);出口=用户实机目检棋盘立体感与素材观感达标 | +| 棋盘瓦片与立体表现重做 | [待办清单](../../待办清单.md) | 已写卡(待编排)——设计闭合=C 方向+D 布局+三关八色冻结(art-bible v3.53/battle.md 2026-11-07/HUD框架 2026-11-07);卡片=[需求卡片](../../reports/需求卡片-棋盘瓦片与立体表现重做批-2026-11-07.md)(卡内 §16 复核通过);出口=用户实机目检棋盘立体感与素材观感达标 | | 立绘显示清晰度(原稿分辨率+三档显示) | [角色设计](../art/character-design.md) | 在役(原稿分辨率入包禁降采样、显示按三档绝对高缩放、现有形象即终稿;定值单点=art-bible §8.2(档值定值面=站桩守门测试);实机目检清晰度与同屏体量顺序登记体验验证清单 ㊻) | | 敌人立绘(全敌种) | [角色设计](../art/character-design.md) | 在役 | | 主角立绘三态 | [角色设计](../art/character-design.md) | 在役 | diff --git a/design/ux/battle.md b/design/ux/battle.md index bae29a2a..2ee8b3c1 100644 --- a/design/ux/battle.md +++ b/design/ux/battle.md @@ -147,27 +147,27 @@ 已开(对照) - - + + 危 - + 3 - + 2 -像素级判据句(实现批验收锚):①印记参数沿用现行五常量单点(环外径 0.82 格边、环壁 0.11 环径、十字臂宽 0.156 环径、光圈 alpha 0.50/γ1.6),零新增美术件、零参数改动;②封印格承载 = 已揭示地面(棋盘重做批后为本关受光棱色封印石),印记居格心、环外留 9% 格宽光圈、光圈不外溢邻格;③身份字形(危/数字)垫既有色牌件叠于法阵之上——色牌取现行色板素色小牌件,墨字对色牌对比 ≥4.5:1;④封印黑对承载面对比:旧裸土 ≈7.8:1,棋盘重做批后受光棱 6.45–9.94:1(均 ≥4.5:1);⑤未开格与已开普通格观感按棋盘重做批新地形规格(对照列)。 +像素级判据句(实现批验收锚):①印记参数沿用现行五常量单点(环外径 0.82 格边、环壁 0.11 环径、十字臂宽 0.156 环径、光圈 alpha 0.50/γ1.6),零新增美术件、零参数改动;②封印格承载 = 已揭示地面(棋盘重做批后为本关受光棱色封印石),印记居格心、环外留 9% 格宽光圈、光圈不外溢邻格;③身份字形(危/数字)垫既有色牌件叠于法阵之上——色牌取现行色板素色小牌件,墨字对色牌对比 ≥4.5:1;④封印黑对承载面对比:棋盘重做批后受光棱 6.45–9.94:1(≥4.5:1);⑤未开格取岩顶色、已开普通格取连续地面色(对照列)。 > 可挖域微光画法定稿(2026-09-25 用户拍板):**接触带·空间侧 + 蓝族**——光画英雄格周界接触面(正交邻墙=整边,斜向邻墙=角点+两半边),详见 art-bible §3.2;现行墙格整框绿相呼吸为待退役占位,切换待表现侧实现(含探针断言)。 @@ -268,7 +268,7 @@ ### D 区布局与棋盘画法预览(2026-11-07 用户人审通过,内嵌备查) -> 预览依据 = art-bible §3.2/§4.1(v3.51)+本节布局表与格边公式。效果图是目标画面;像素判据以 1280×800 基座档钉死,实现批按此冻结基线(test-conventions §8.2)。 +> 预览依据 = art-bible §3.2/§4.1(v3.53)+本节布局表与格边公式。效果图是目标画面;像素判据以 1280×800 基座档钉死,实现批按此冻结基线(test-conventions §8.2)。 D 区布局——顶栏搬两侧、棋盘全高、上方 44px 浮空数字预留 @@ -337,6 +337,18 @@ 悬崖 8 · 下方 12 +**棋盘材质过审实图(2026-11-09 用户人审通过)** + + + 三关棋盘材质过审实图 + 从左到右为暖石棕、冷蓝灰、灰黑三关;同一母图换色,岩顶与地面 512×512 无缝贴图,崖面为断续岩块,边缘收薄。 + + + + + +> 实图判据:整板 12×8、格边 46、间距 2;岩顶/地面为 512×512 贴图,单张 ≤32 色;主裂纹整板不重复,崖面无贯通岩层线,北/西受光与南/东背光方向全关恒定。 + **像素判据(1280×800 基座档;实现批按此冻结基线)** | 判据 | 读数 | @@ -347,7 +359,7 @@ | 棋盘 14×14 | 格边 32、外框 474×474;原点 x=525、y=296;棋盘底 770、悬崖到 778、屏底余 22 | | 上方预留 | y 252–296 共 44;顶行字视觉顶 y=258(含 2px 描边),距 D 区上缘 6 | | 浮空字 | 字高 21、字底距格顶 15、视觉顶距格顶 38;2px 深墨描边+1px 浮空投影;引导线 2px(左深右浅),自格顶−12 到格顶+4;字底阴影圆 10×6、圆心格顶+7,画在开启格地面、位于小人之下 | -| 岩体投影 | LIFT=round(38×0.435)=17;ESHIFT=round(38×0.109)=4;相邻岩顶搭接 2;板边岩顶外延 ESHIFT;南崖高 17、宽 42(38+4)、顶缘 2px 口沿高光取本关受光棱(dungeon #C9AF83)+1px 深墨线;东崖宽 4、高 55(38+17);北/西临空缘 2px 主亮棱+2px 次亮棱+外 2px 深墨边;南/东临空缘 2px 深墨内缘+3 段×2px 内阴影(自缘内 0.217×格边起,α0.27/0.16/0.08);南/东投影 4 段×4px 渐隐(α0.44/0.30/0.16/0.07);整板悬崖 8 | +| 岩体投影 | LIFT=round(38×0.435)=17;ESHIFT=round(38×0.109)=4;相邻岩顶搭接 2;板边岩顶外延 ESHIFT;南崖高 17、宽 42(38+4)、顶缘 1px 受光口沿+1px 深墨线;东崖宽 4、高 55(38+17);北/西临空缘 1px 主亮棱+1px 次亮棱+外 2px 深墨边;南/东临空缘 3 段×1px 内阴影;崖面用低对比、断续且错开的岩块面,任何岩层线不得贯通整条崖面;南向投影 4 段×4px 渐隐(α0.25/0.16/0.09/0.04),东向 α0.22/0.14/0.07/0.04;整板悬崖 8 | | 深度遮挡 | 深度键 = 脚底格底 y;岩体取最南格格底;升序绘制;南侧岩体(键更大)画在小人之后、遮住小人脚底 | | 层序 | 地面(封印格地面铺受光棱色封印石)→投影→开启格地面阴影圆(小人之下)→深度对象(岩体+小人;格件顶面贴花〔微光/变异〕与交互反馈随脚底行同序——北侧低于小人、南侧随岩体在前;封印印记与封印格身份色牌固定低于小人)→浮空数字+引导线(z 最高) | | 顶面/视觉 rect | 墙格顶面 rect = 格矩形左上偏移 (−ESHIFT,−LIFT)、边长=格边;整格视觉 rect = 顶面向右补 ESHIFT、向下补 LIFT;微光/变异锚顶面 rect;封印锚逻辑格心;迷雾黑罩覆盖顶面+南面+东面三块 | diff --git a/game/tests/golden/README.md b/game/tests/golden/README.md index 64c50693..9ff4ad2d 100644 --- a/game/tests/golden/README.md +++ b/game/tests/golden/README.md @@ -14,11 +14,17 @@ - 营地窗态五锚 `camp_forge` / `camp_chest` / `camp_tree` / `camp_codex` / `camp_notebook` (真点热点开窗态,camp.md:45 五窗窗壳) - 浮层四锚 `battle_end`(战末结算)/ `curio_pick`(三选一)/ `legend`(图例)/ `debug_overlay`(调试浮窗) +- **材质过审预览锚(非引擎帧)7 张**:`board_material_L1`/`_L2`/`_L3`(三关整板 12×8、格边 46)+ + `board_material_L1_zoom2`/`_digit6`/`_hero4`/`_top4`(第一关机械裁切细部)。来源=2026-11-09 + 用户目检通过的棋盘材质预览,仅作 `board_material_shot_probe` 的目标图与目检对照;**不参与渲染闸 + 逐像素比对,不替代 `board_L*` 引擎基线**,故不触发本文件 §基线冻结与审核的引擎帧审核口径。 - `palette_baseline/`(色板基线,纯文件内容比对,与平台无关) 采集=**真实引擎渲染**:探针以固定种子跑到指定状态截屏(棋盘 golden 帧=微光关态,呼吸相位冻结; 确定性采集)。换代入口=`tools/golden_baseline_refresh.sh`(缺省棋盘/`--menu`/`--lmap`), 提交说明须写明触发原因(强制)。两 Shot 基线采集=`res://probe/level_map_shot_probe.tscn`。 +材质过审预览锚的整板图来自同一张过审预览,细部裁切参数为 `(12,0,332,220)×2`、 +`(286,60,382,156)×6`、`(244,236,340,332)×4`、`(180,0,400,110)×4`。 ## 基线冻结与审核(2026-11-08 用户立) diff --git a/game/tests/golden/board_material_L1.png b/game/tests/golden/board_material_L1.png new file mode 100644 index 0000000000000000000000000000000000000000..265414cb8f45a21c93fb21624f8d2955de7adf6e GIT binary patch literal 23007 zcmYhi1yCDp8#Wr8Lb2dZaR^e}in|p`aVNMHX_4Z^y-<{*~1EL_W3?M^AaIS^^ z-!A|&*?->-C_MjLmH~jc|E=o+Vle(&a^C$6R$!!J_Fx7u5Jq^?#-J=)02t1mPG|ah zo(KR}ArH8KR5XE-v#+I$!J3Od>Fx)t1O88 zGSt_or3)Z4{g55s3m*Sz!gA*b=%!1qu}c1m2e8?G`Q#s4)XUT9EsIzq=FOJHrk(G? z8VZ@%qlNoHU`p7uVtzox+;nasVzjULsyf2xMBq<;NT$}^Eb+wJbyHUS+WRV@Bug7l zMfEc+&Axj&4fg#3Eu08`AZhYf&2Im+V|(EJKj?ap(veLAV(}=rY_;Axxd6dC*;T5d z=0fl9mN8%uvtH#A|GSU&1r|uJ{tJet1(6)*fTSg|8G-^h7+52|t#Jh2in3#AQ zABRB(0;7XO+vJzl1a4N?bGC{BQXx#KP{f%|%UU__;)4I5_7a_GkGmn_w^v^Kcn8hX z9LvZ{?Y!>2v|b~_#~2(IRxdL)JhlEDBH84X4z;vSq>+sAa;Q!DT@&ymp~d950Q!jF z{S^o6{(>LV&u@LLr-2TwcPi7ZTGj2I;^DUcml8qCQN+lVz~zDKyl#q>TuiQ0f;a>I zS~F6qG_9)SIQqSGOSNpUE8pA1UD?hF@~SjUcon)hEKZg?;jBkwWNfIuSpmS>K0w6$ zQ2}44-1G>4%54D-&5fe*|4O1k7%61I+U+`Kjh0}K_Xx)oA7Mm z7Xza*XxNDNrv0m}e?v(bpr>DEy4lIg|Jmj8Bac_mMb8dTeXQP>DK=v|F~5tWwa><7 zAKrI7TVTZ4(g;#yB^Px?JFXSHmFwN*uEg{;@*kZjew%IHbUzYOzYX*|SA3bHhV0K2MsaLy$uORv78>rcCc(qM9l#{8#Ne@X1j>os}S} zzp+ZZD5vveE1vgLVXx)CIoRvEXdlD`kPMhLL>lE?(j7(tu*?Ql_7 z&yxLg)W&LogmH8*4dg{_JsI!&6kM(&U%9>urj6XyOx$f*((fdFMKLjGtf@xhb%xRl z)r}biGE~QB$x$*LMLt`6=U(stW%-o26n~5i^t+;Y^cFj#QQyn+KaL$KF`4QK-m}1rPF{QR|j*9eUU)W zP}_ogrwn+aDS7nE?Naox-~J41xo{<{5U6W_XbsLIKtT4{urO}xFwA}^YC3t&F3-*D zKb-i4jyIdCx$R{ zV^di$LrZaqq<7QR{ZbQiva#sTXd&snL%LMhV)*TsvLTdYc(4$Q_dbp2hc)AlnB14N zgW66O=Ogtom=s1BS1=v9zdecH)zduBH7_=EuC{xgEwWn;!^Hk|p2yu-JQX!NocRB# z7Gr+-@*<};W(sZud02|qvE?3DbzF$a>9qDe%Br5t!Foz}OAGlhxN~j3x<7n$j*go4 zKAAeUGdO_g9I$JOXB=sLTY&Js{+2^>gkVXU@67w1b!#Slh1cjOKyoGFvIZ4; z>$)e|8ikx%Z23L!IFGcADDB+^sWc&+)Yx};x@jz6Z=KNY!1??G2(~Rd@+`&ahEYa^ zEgp!|yOF@E$KAlWVC3}e`n-0%m>22vFkD^tGTz0aEXhBS(Gt_Djm=|S>Qej)V8d5O z$pR0yHLIKra9j0xTB8mA>@Hd#=xvNUyd|;(p0P3tHnPI-0)q>d zPSiSvXvq{8>WdZL8$C7QDJSNbzDXg|76wq$8QU;P@MuSO@8 zn#Ifbm~t8SkJRHpVXeA`7UycO^7*S=!sD{Bxx-7aKtO9-MQrXIRY+B3n4OtkAnEep z@H|4D6^g$!N8u_OhVZ}5ZqC-SSMJEnDNpsNdC#LXyINHFIe&){vY5jcPC!Q>nyPIz=QDXE;Q%;F*RdAd)qZW2+S71y|@sDx)FCoBD&TvFr9Ai%jc z%E>tJMMx=ghT3}!PpE~_QsR0@#^Ii7_Q0^kZ3=(Zz;8{|>E_eEcwoAN6a8>Bgfg1i zi0VFugAyL>cN$mSyO{Hi+GXuiN#2Sye0TEr_-4TojcFvLuXy!w7Fk}*u|iV4Dm!tc z$R+e08hI>(cp}i%4Nm_W)G6s7DPc9U5Lsv*oRpNl-rXVtQ!RYYf(PTnvay?Z^qp7%yV$%= z(6d#&{mP`nX*4nIi7B1LjOF5ZU8NdG+BBci{?vueGpm|wOGr;a%JWCMhn!`=9Xbg2 zJG|oeZdTx`B$kkS4JnQ@`yu(C^2z|s??UEDEi;L-Xd~5x-{|pV3v+qT*ig4 z--ir~xV{R1jmI8Uvp+LWS;eIozkHH5i?N;T?0-dKO7UaHi&btl_2HBo~w5I;w} z8%hyqj?3`L3c-Tf4ODY@Z2os^m$v#pB1NkCEJAy~ zevUf<{WpsR;Pg+&)IJ+*K5L(;<@UP}2hGW&?lZ_zzS+~A_hihW59{|(}i zW!C8-v9Bf7W6U8Yo{NLs$dD~NnBZD325#%4d{cmr}CxY>-qkNkYvhd!l{@ z{S={>WVm?(dF6uNtVVcntimEg>wnrSFwtrGFH)zt#6VxxQ-0o=JFMUa2f`rvPnF2N z0?dVa2swGqHHYIjb1yVzdpS0oO|JNzSUI9-L16s^y);`wVxglwiHt&|KAvr>AJ@=s zmv6fd`sN7bf^tP@uA-vMq^tDVgkaQLTTz)>iG7R_o@Q26q&S3jpABrv7ZD?e;Do4` z3h{5Mt;HyKYT+BA+d`jY6Sb+AVvMF@G?(xGZD~18xV6}Q@K#5Cb#=G)+;Q1@vhxZ5 zl`i`n@jHBVX2-KnV}WS8GC#*I40TdU5$V%?{0dA9iR`J&V{#P2Krq-eroFp3|+NskBdDgMMXJ{aR=wF8?=LxjMMD z9ziZx=*xvGp`$Ngp)_{ksTz@Pw$%GGuTLxT*OI}6`Qyl$q|b5hW*Nak6HClIf zTnrBl3S;e~9@5le`LMuV=sOWe;2_--xUk$*4z*VpeeZoW&w;sCklF&QCn5>+{Ti;7 ztFNGF15PG{JzIPYN&)bg>qpB#Vd}09Z3B$y_KS7*{4rao+v_G;Z-SpU?E>x=&1xQw zOHa>mi7Y8CvaWS@e`@Y;XFvvCVVRU=_C~DRJ-)JjL z4yC>FO8YSQpXt_$&#K*0@dh`xqsx)RJmNhm>WMjzo>SnHbhOm!osGyo> zhzCd@=gF?d`@`g%`QpEWoogM~Ivx`I@Y?y)&8rlS)HZyBHJ-OQ_hVX2JSORr=F z1RncK2izqqdlYZR#Jrg3kGu)K*?(_dGjMhpiTYeWk_r7{+7WC!p^Y2&zkZ8Pnk)oI zw~f|F*eYPjs`>9-lvT{-<@lrg%M_J0WR&c$j`1 zPE~ak^^6vU4L@1Vd=jzxf6dey{~?59ObU5NAKL8*&emz0nZi471}z*VPCm7*+$bq- zdKZ$*pTa1W^xQa!;?(p5H^-O!QW-1^8v>GQC2f&2kN78C*Ul(V>k>UX8UJ z`UEzf*QhRvesMb^+nz|Pal8;aMdT<6H&P;Nd}prmmkXoK($|r^O6IsF-U*68ylOQ zZcj{!20M-la_VJB^lfpI~Vgin-*zv=j!{^8g+O-lB=5@SKKBO4a} zmeYX!v3Qn2f@z67pdUw#Oqgs|#^S__Y4MCd>jRryzTvAJCdR^HoWO7J+Nl=dcI)FWlsm@=4$l8n>%mIfhAXc%Oj7uIzg|MXEH)R4GPt0& z;KuBIg{2-wlcz51|NUbQSLr@zMK{Ki3h@$`T7B)j><{`>>Zs^3c86U1#;duhNrT)u z`E82Phl{Eq3VoyG7k7a+PYF_du_|E%nyF6B68Z+ci<5I9Yw8n&-$>`ACKg>9AM}3! zrKdIpcmoj9B#z^gkES>xJg^&~+S*j7K$na}m&6YiBnA)vlrCed;8zMgf2@5jHz*&s zM~8o$H@^(ZmV&C>Y;XLQ)_)MlsxpUA@n-HhTg3Mxg;V|IO@0nxD(t0*Fz%q^7r zVy}P1@+x9*xyX`(yfdsvOAtPdz5EpI@pwe!u`sDzr^ld_!XRs02<2?P^a*vUK?R<_ z(c3Uquj3lgb3uhGSX1&zie5jmL8GPxGn74q6wWn(E8j<3XXpfI9-_L?k8d?Njv z;F53X5mcyZZ!V-DElI^F$ny|UG+wA>ca^Fm`G$|YtBy~`kCrqOR$0h=$rw?@+{#s% zAfXEtD(tVXrIdqEDC{Fh(+wBn8*2qai~GrD85mrE0&^n8U2zF5#zJ*AuFmySa@bz& z>BOlWuCJV0Gp*M=V$e{WG*S~EYW zL-pPn&PhAJHrZC>XlQ8HL_uwI13#RE;XPeL*%n_~S~<@+)rRzX;u2Bk8AcnTBb+*Y zOjP$O(?Y-D`$R^^bgNtJ)YTq7L7U#a(GIxK$q`Z3Kfu*swa~q*sZU7AuHS8nH%b@! zKGbWMT<)2ywwd8z5;Dca-M>?08D@fre#23 zx|zDSKO}&iPhFF9oi&K=m>69@)@%3iD1G1{$bxrUK%h2h=IC5oXSOq8L4;&bu14hW z4AoQ)vT}XkdG0{`%QN|EQhVS${obFhpB)4R7!^QQfk@<#eT~V;u3b1)1QjF$7@t(% z@T%v-{`pCovXUsE?SkJWjXzJL0uvN#brxlGJZLKl$LvP(J24;4Pd2tcE^7#q8Py2S zMv#@z&NIBI4*rxwsgbd#5346Le{28m+n>1>e6_xa8KwTAF`x;PQM12YD)V zXrUy(wT+T9ad`MQ%`vA~h$u~8Ww*_n4=5&h^HG0Ultp%>;b#!f>`}H%Hh#_1xYL+- z)xujP+bT0g{(PCU_=l%wyLu76vz5CV7N=jI;rB)onc6m)*{3^tq-rHjoafQ_KWw=T zUf#7g+DWWmZvJKFKT&d{;d=G}|2V0hGj-|H+6TUfQ1Z5L#esrbIVFcYrnHNND+f6_ zz~>G_ugNicQ-uvJP^Ku_FD`e)m+|o(jrq#&#)`tpC}JTjP3C8-VHorS3 zJQnLrk7Ua6lO>90u&DLRMdLg79cly&Vk+}km3AcU1TjbcliAf;nJzY9! zY64F~K0=T8z$iN3AqhH-nV{K^eIxHv&A-m=U1J1vmW7Q{QKh)Q?G=J7N^S97BV^Z?sj)h|N*b|hc$DRTQ@ zzScJSeVwZNg{`AS_>*%&5tBj1?`+2CP9?@Koos%KC*H-=ubCRm-(9EPC~%RIgDQu; zC9?C@qHZb95B4msO`QIY@?cVg>~W}C1=ai9gbRm%cAxmERJhjI_aLBP~f>-^}&-ytjb;a@#kz;`?nw2&o-c$JW0^;GoNv>zXqTkkJn zMb=idv)&E~^F!l%Y6r!PP*kb~87nmGL1%_GPHK3XMm zhUAq_1F;&LSDNgD?52YE%BIlGM4v-N9CF-CP^jAQy! zjMFB|R)!ByiT~1RY+I%6!3cdxQM@^Mg6R*xNj~QqB1HcY&HYHBKvw_tRZQ{)vrby{UB7?$Dyy z!$C&f7#kW8NNTrnb0@G51>;-npX8*3s%p5_EgA=K1i|Xzke@Is$+f0Dm{?(?l=-aSA z!U=YWUPJkia(+9C24SCTq0gP8d*TVx280GMQ!X?QQk(4_+A0J_pq_>;6ksS`6-6Jc z;~xZb0Xs3--rna{Uv(s`UJ!HxStrOnwHe;?d1$^^KKYw!=qFGY=<1a8YPTZxZH$d+ zeQk&zr!&lQY=RZkXt(#xH!|$`eqno`$3$wpriv-NX+i_|I4aXUF)}zUY7s`Jj}oZ) zqO!cwtWv+l_qDY|3W#%|q&-B;piysDsVn$tT(@fK(EPA248?+(#P_P4JgRd+<23#^ zMWSvdr+N~p!Rh|Q+}iV#j+=acT*Ny!;g6kgB&+P9sk(#^z#$wg;yH!H`QQb zPbpBBv0_G;G`24Zi*I#_il7!1rRx*C!Vodh(5r_)S+ZahEiJIf_{tpJJt#cw5DjFT zTEqH^X$GyYT}}FLToqb~DT&hA@;5bwJ$sRl&oRV_;s3(Rz|7w~s$@7MckNUDrX(AR zQsCS@{kbVC7l|_PK@Idujw7{l#yAZ?+%cZXCxuAdoNNYS;~39x@$&Ae!@NriPnIu! z%ikV89pPP?$f3}~j_wCE$ktasQ{QvD;eq?UPj_O@y*CSnrKwD=9e8VT<(xevH<68K zyke7)jll>+e(pS9NhrOr1I{+hemQ5{YB>DRERlXV#!jGi%s|LUMo6E&{JOlf#FWSpz zh$nb4(K;R2lj0+qH3u|#5_WgL}^Nl{tc`dU;uMer+yH{ac)ZeGgmcRx#Rer?Z4 zHYfFXZ^hDjz1uOg?T!)nzh>)|L51PB`A9%|F7`lP=|s;WBs_xrkU1pT-Vq@oZE7E`m%E?w+SjXcC#X8hPX>i! zM&vNrhTXw`jFU`fj)^e~Y~qv+sK*&>1OLt%pg=jRC7PHkuI;J~X@786@{tlmp-Q>F zTy*i8cj>`%Pcxh}5RR^?5w`LA_mxwR*KLDPz>J!fLcuNYW%mnhbZBWgFL(9)UElAc zQp0lRiLFPH!EbSaPmgIjjpw84_HAZYUn~#=g{$6AdM2SkZlc&C5$G~rY(q(M7Nq?) zN-xf7C{2&nQ|mj9b2=H%iZbG5(#OOOUYs=$|5$ceT5FV&gY~OHN(^j8%Q! z8Ar^OolbwN7Xmo4IS9YLyaihD61{G&4aW{Ga$x;-ZZKZGXozC_ohof=SrP0zb`R%4wttK7z%UN+@GlP?!;VsNv7`}o-|*)6AwPJ zT`8>b)3jx(ZlPf~KaiJw2^z@`$+j;TE~|50;s5*2q#CD1#+%(~|LEKFQ+5(BpKd@^pWCnJ5*i3o!Z{_-~Ztn8Iw@%&x77kK)4vB zs*?;oE@HpZNZ!X`-JJZ$?Xwn{H15PcvcSD(45L+zLE{|Z0=rE2Y(DulPZ*ZP9lVvB zVWl#C1(kbOZf;IgqZprnHkhABUt-MyGgwke%ZVr!A1ZAc#`$(-Bc;$DXa|IFb>k)( zzM9@+2#G&`;IT-0PPmTKT!~c*RrC(Ou4xF1dil*kS8u_cS)s5D+qJvrqL2H(VMSLJ z6U<*-ir1GL91qy2%qeX4d(QY6&+vnyYdsCiJNpd7ZQeSUqagU#2+W1WwPX@f; zVTs6LQr1Gst<#SMv?tk(ewSy7U6moTn>yM8=}y;EW%^ci#4dtAMs;T+l+wNrztzy7 zaFf{LG!^CfPD`%pQV&b^ds)T-DQV;%=ANC=fAAc$N_<^k&$th&iL-!cTFE<~d;1og zgeqHiH|SR;R&8UzIhlCA8J176ksjIVIkgIDvC|kEcZy2TmQKB>YpBQJP4C69CB_!#{MXyUZGDzLyogZs5%QhJ`cr7_?#LB|$r6(6dQ{K| zB;5!{waIVhoHhf3{43`(q%`%cPsv_=+U@zVcEsmq<*IyX(@$sL^Yz6f30tBG{yMA}e}a`A zg8S}}XD1@Q@pL)FwOCgaXjn0uJ}vf$oPwYOr-T^!#@TLyr;n#5aQ9ZutGy%Gc=5r)c4q>BvxF9LZbL3&CeVVGC|@9@Ig{tYUU<7Ia|h=+7B6 z$GcY8L5GWLJQmVc={Yyoc&%2Vz0xXluZ4iQIoAy2!^7XmwIcM4h}I!B2ggZtn7aC8%XIAHX%!2Mg#`}yeR>_5rLL1Mh9INScT9@) zwH>Y9L(xOz#bM@3>;spgS2IPxcXR`&^Sxd?-mlf((4OhtvW}GP^BEepY7Y(e_x#pr z?DV$+$w3z5s1X>rpn^{1Hb2N^q;u1OMK40g(dtj~B*@->kIEZ$J^F~b>FWW-{qg6) zpaQkRg_n0vqfY1Z?~PEnk5f7Q`{EuGRUBG!dwrP=D`y^bX9J=suJq8CS)eYnVk*CK zh1Y?+BM*ezA#I(T>f=K{K^X=_?&-b!XrA#Ap-!Yhr-6KV+hQ>KFn*>tR$mU^0xYHV zHHHUcCofSOpr6tfNL;4zUo_~8n{IUqGH##21qRN`UrJ;;M#=}`&K*G?h0|0_V{tg)mTgZWv#!2>F8}I?T1_>j@HGv_^ zIB_P-vuwfN4Fgg!Y%!P>odRv&c=!jo(uT_Kdc^f|%CCK@WZ2}C;=IlW80mHhcQ3{Q zxZTKKV0oyT6KRk3$gwEOpd+muj%VaZh^9iJ3!9UoN+`K;zk6qC#VxDu&j}MJ!7ain z$ zRu%&XLJYqf>ZL|pcTOW`JDo@S@%&Ngg2RS#;X*ILHW(As&dJeS`j+=2{WJ$iI*?@e z+O)OV(d-S~i6oG(J%#pc3-vn{dkbE^Zqrx0darvc4*~@dOKoK{%2u=aJuo|auwM=2pC^56w0M}pM>M!|@HDH~cZp@uXj zWWC8LcTn-yUhGfA&8q`ggzFeta*gQ^D1n5i#@v}n62p<8ed|{d=et7v46@liW9$m- zw&29}#<-IN0)}iujZ{g`D`tHo%}*$NeT@r;hE)rl`jwlK1nx$5{~B3QV)Sfq4L|FV zX-A?x+*-!`x3h98_xGa?SLsJ?ni}xv?N{D9gpQ1%DG9rGbS;@a8e_i#VE`A4XnSZs zJWiSjkF`K{(m)2iyN?sY*N74RL#4lu{@sf>2J~e91JJ9NV{< z-&*$id2MU_rVo}4u=^q2MEu*0J(bhY;d3@s>J{lLWSa?V1bgjUhT`Sb^#^8Wn#fy` z>CPEE14oE<^wOTHoK@c|zvI-aokShajENFE1YzoWlYAgExLwzY;U-h-3x#K8{_Tv4 zap2Um{L+psYGBlk5L^|F*w04+m@yPmXtHh|VHEd-;SVYKl5_ZO4ORm-ZZ6O#TU47oFD}*Z=@}Q=rQ2)hQv44>l30K zcrg8lel;xXK;!q_*s^`8o*W+{79}thzp}1Mf60c{I*hR&=}pR1>z}ALwW;3}ApA#6 z5VbB_>UYa}g^;&uR-(37oG1Z~b`lYyV4B4^@NFpYSFd^wHG*LqYmi9@0nJDnE~sE|Ti%i@Nu+ztsIoqAGn}KBB7!5D0yCzu2EG*r7KJ1b8dC7I6>Xq;n;$156f>qfV+U9!$ZStMRM_s z!A}bl>8_^goX#H>JZ|!~w#Nwh8Ae#G5g!2Xt?I;T=q6K@yZ9}NM0tYzN@_egrr0YTgy@M6i!gtU29w*J6|j$aCShj0|f&6CwuLrI2F4hm)g6pQJZr z`0)OgwVw)KIE{nTNT!d~PVe18T z+M@FyrE&e@LhsyHF;mR!*++FQY~^S}ApKbmi4*|;JfOo%nlZZiagg=0N^DNL7g&ls zGOpU!+N*tUzDive{J*r?Es6TX|7f+R!?*A@rwzNsK{YEQx==*ES;^blQF#a9g(>WPO4N4X}%`@YUl006gGV6&!`fM@7#F_ zwr}6XV<-L!yc!m71UIQb&&*yhm;gjT@ zcd#h>&!6_cO8M@u+UEr3>n5Ka|Mv!7Kk-M*AywHMaz&=!7yCE)6*cm|H!C`2N{)oGOYlQo$>!eqhY$03C)vM6WC!6q3C3+Q|BkXfW{W*W57(DXsi!sy4`yCzsjzA;1xu;2w$_hMi=AjAZ;e7rknYuqy! zV=WP86q!JLDn4@+^br6?7&q=-zMN9z8-viHEs2wL%uW*W%@W|$ z!4P)P@%%UB%4U@5NqN=kfq!;7o3-?PZ0hue_f>1aIkM$Px@eY=?HI<|pi1WR+5pmV zl^vfg-ti_&EeWoqQh*Zj&a_KF&$;1O`lI9P^|)|Ucifn8uZ_C>VKx> z5Yo|6JJD!Ipx*?h#^W+VQUD4?L7EIz1)U-Gpk5}~no{djHdYDp=!?@@GTt^?aPnNg`s{JC%i@ZlR(u}GFEQcF_yc@0lpeG@4vxwz zTCH`6QqQS)r}PEgP|F9fLYWCVU~|rBbbADOb9P{tt?%4a6r${xV#BbN^i^voztz;3828!m;t)>M$O1kTdsSjL{zi=yM5z_D|UX>d%kKccEQCo zD2}|u&V2SH4vB=;dYX7#*{U!td4MCbiH?FF?mp+5#7BD@$|QNE`5Z67ObETbU5_P}P7>!#KWFb3 zpUkShW7l)ky@`no+xe1J1Ur=>ebrCXzU3W0`5%MmTAJD9vCTbqv& zrsa$gy%%yCsid3(s1)eT`q-l;hE#C17ye{T+SP0YdAHm5gHfv@hswU{H~MX$!eCpY zadVo~gzzwJiP<;CMC>{E?n0Z_m?vRZBXZwRIxN-GtA73330>KsP? z0p?V>Iu1UmN`fo`Y2*B->BDXLfigYa21ZEIPga)<1los?AO*s@?$w^eX@ffGW@n6{ z3iB>1kCY2g)``RfXkgk-*E&6d`d`n(m$LPE1@G?XMTO6$UJZ6wEWggS7$kR`N#N&^ zdfb1{ONSKSb6XI%$tv?7tC2PTzTQnr)hpS&l|SGMYZ=#TvLwTC-wwJZC2wung#7%P zFvmaCIgKZm=I?sD_pU>dVJgg9qVMnty?bEHd37Ot3{c6szQs?bS7ZFNU?qzL>%Ko^ z8-t4i7m77C0_U}ZZKKml<{mJICh^U)1^m``?SL3swA1IZ5>YX}y51*<>_1Ax{_*{J zY6TbN0`fs?M#|-NYP@P(qBzk<>{S>5yrg+LOeE`{V#Oilq9co<{;@jZ3$W(&yPn@B z4&_0=44jX*H^C(uEo_yL+UOLnCh;#Wp>j~DI7WaSY0+4}#dz#QCJHune%wL<0EzCt ziujQGKRoEV!t1xPjnXnU`*`QFV8t(Y@s)akEFY|}O08ct&S&#k1=<*lNs6F|ALRxRWBYr!?@h{C^4C^w)zv5f zdn(XH-gb;a->1UG#`;Arl}X_xDs$RO|1owx%rs_*Ty03hMYuU=Az(`{QXr;`1a@eq z&P+p6h5Mn&7(3sxyX>R0pnu(=t4T}Ra(P`rw&_90Dl(6P(Y9_^FSOmK1etOH2hxtL zJ4tp;gwYSuV*7it^l;C`@}K|O}{%M)0e^x5aP-+YfL^qgKCWuBUF*YE_&}NNy*am2V_Y|fgU0i z2oogzPWl>|MInr~(U{#xLA%om}D4(f~!u` z2)VQl)Z9~BdVk&)bWeBUg`u0Kc>sJ}8KNfx7JE&JcReP7>L+JV?a-T2$g^;z8K+B( zuoen58%xCst_T^P#=O$AlADQiV1O=XXt)$fk>*iE5Q+M~{~TN{dp+?pGrkBbHg{A* zDX9U8Trm|(WK2;E)Q^#213RYo20SvRW9vX$TNy4IF1@2R@+QWHijJ0Ziy^Mci9Mk^ zUJn@y40}g0ri)b|rwSJUK&E#SOU~jXxfr^LwGTPwY-{+r(bkoM18l2h(yN$Z&i0^b zRBXKqINDbaLuw?JQ7+P7cV1OQbz>f1i4`1)TJhKMq zhC(ZyLOx@tpa7k*(&HejU7fyjQ)Ebc~ z3pzq}OczfiN?Doo{s7|L;Vg@VNV&zyzTlM6K=w&~P%q0MVWV;(frwYdA7E(T_4IyJ zCC>d}kH_*nGG@@`!b1vwNzpsk67NMu-8KSA0G7nq_-KLM!pLCKc3fzKoFGkfBwG7d zRKW52MW#Ur-#Qp&h_H9exosRphj49v9tW_@2yGFsC+TR#rWI!>$;S$LM-z0>yTPU< z^DwxCAeLSD#KtINz{3#wlSHIcmR8amCq_0X(0AO7i_CGB8g39vO)YS%^Ru1UWpU4b ztz~2#dqsl_C|CU@tJiZ4fTB%J<4>sYm6R!KkBj>6P}zC%ceT{KwY|j~qMwG$+d0ql zrd$kyF*eIN8lf%I)?(R;U=^-gCd$|hWfuI)j{>Jg+vSzL)9O95NB~Zqz_+*iFhHK{ zy9})%?*pPZ(5F?BLdNBn|BpWrwJ~BUFzbYir`U&k^w46epr(1vPyP(A#*EO3_RWV} z&(C+Pvv7VAq^o}>hkm{*YG?{Y?6=KFHc^+$Tij~~2(_VjyW3J2cWUheFCx|#GRU=07S@RyEP zBMpj6mvx}b>*ZP&P@~f2Hsqk(*Oy1g@c@m~nLhc|x8iFk7QGy}_W!^Fit(kriOzCQ zuW9OAQ%xZpMx^TpeP)K)e!Pltm4YVh{xQ#*H=7!n@mdk7dIcX`n!x0Zcr#- zeieJ0eUiNc75q^J==#aT^Z2+5A(A7utLOi6+M^Ls%SO}&xg zP*bed*xB$inT6EV{YTnN86Gc3{TzP(fF+0G{`!*JT+Z76{DRXPtAM7Zy}_vzV@plM z&mBI%jmlf4pMqvV9R*G!dvV*meHzuxo{s!Vo*fIHrsXuhrpA3vze2oWnLWhshAR$- zHq;?$gZE;^luV)_G0!nB*7}$VQkpIqR)l6lj~T8`&i|jj!_8b{dKH76UeQaSO9m4 zt@@~#QH9cxHgc`Gcc&I*2EY#2>|i>ku)I?{X3^LG3CYJv;-EQd*y0?Vh_T9Snp zq@3ylou}{c_6$zArrr1CXm#Lf93NZGQuW)AID)9_1!ll8FXlN)3L#dtkEfP*xm0Am7*oNsLjH_p&7T>3I zNjcaEX?nF*9-_o}Dfn8uZ5WK-RGhlzLiIBYcuKZjwW8+p7#JPgT#RfpOIU^yLTiOL z|12c99;zmflVAt^;73BSm%`2BT}_Fzv&|D472MSTnWe!WK5q*NodhH}u3(?Dj!-7V zaU3;bLPA<_@K3-bE=erZWa|YrnWitkMJZx3&yvVr+M%2$%h_gCCH|K8NBj17kiY4D z*x>vpRw#FM(IQPSzM-KAW^4@Flx2t;Z%ttITIu-U{AY`=AG2+^^7bctJm(Bv?n9!1 zM>Z0|JnmY_7%qk8tHiU$iE_?v>ikrru9Wr1;kdlKW(?QwAV#-#U&_B|-JHzNGnkpN z$$S>Y;a<(?U;{9wX5_|`#y}4Qc7yThgDtt^5Y1dA)(pS8Pr7qVpH%JT-BAy~1@Fmmu_d6L|wm-6u z6!5>Y`4J0v2_b6`$+BEFz$6M#ol9-h(3WWp&&7O4oU5$lbCv|W^90pQvGq*EloeVMFx}eIxUtqpflrZ_$k-2^yyJG_5oi}w6 z-FFj_;W`HJc)v{AM;Gl4Am>f*RQpmC2hKXFKBoqsKMV3yd>=fiV`IH4@YBU)6%BbI zJc9Qh5K)IMrBAnJ4ylaF-Wl`M6(2Ti1y-R5^lnalB(KBHx0%^LR7+f1P{O;gjkZ)p z<35`(vry$$bQAnxX_Ig*lnrv#>N|t)_&3b06xPY*>!`-&!*ML*2Pi|}z!5WxAyiHX zQA{{zs&Q^-^=>43@^W6Cr4?Vwl=j*icBARc(6zY{^c;SB9r>*rO#4xrA|Kuv?xwF3 zn;{$q6`3ydAuM3CxSmbSRJ;h(#ml@8VI;Y80&2GQtV{=AHqiu9k^-=k6c~4sc&za9 zkW&|;Crr}L1=;=0NsWu84uhXYRAFB?jr6%Z&XJOl0WdepYJhkOrV&@bxc3mX^Z-)5 z@480*SLH4N{Q9PA4fRME0eF2F-BVCHtHujO`d}R}F!xmFk*p7R4J7TeCC5o5R8yA_ zIlM#5m^}9G(imzyQ5|P-B=b)ZS{G(7W8#_vO+R~BU4x{^U0Qoiqa`3f=<`(*)y1+v2ue(&jE};Kwx(t=KCQ$69%mM4u0)uV zd$Ky&S+Rz(IfDTy7A&&)IFMV`1eo2ji0! zTbp@RoY+al+2`sXni{UmJd%jNq$#pO>Mj4;1u#R^<^RV{Y23zos-n(lyoq;nY;-$z z3p~3=z(H=GA4~V7gU+y?_inWUuFHe({``@C?j2Y~%n$XUiCEOP>$mzNyx4LAIbaS# zojyqOThKo#cXGap-}lw?3s4q5Ny^OFsB`OqwBAP-ptL9*={hejKha@M|MJki@b zF6=iqPD>#9{J2}w@x&_1gbwAy9rx+Om)l>Y6}VQyZTm~#;mc}J$zwr7ITmTk#-Xhb z&L+geDzK91^G8{K(E52d=5zdXK`ecLNxy3B<`eW(R5>ah;Z$(rc~j5Hv!!?ZfpIlzRAoYB|rKCZc|ghi0J$5Rf2< zR3)LQpn^yX2t))a2_*udDAJ2kLW>mXND)wx-UK2cAWb^bdyx);6zS57q2w;UGwPd2-I&hz~K&+<=5V=uX1IhP}G%_q?d*?rN!m<1tT#t0TpTKr@vogBe( zKNiQaZam8TKBe~eE4n1{S2C=hy{4q-rY`OZ*X=p3EX+E3FFWo(tvZ>{Llt_SNcGe) zOWZKaXkRy&7%zVb79S*!^ZNz$>D0W)-GyH>Z4#j?QZx*u5iq}(%mz0Pz0%$w>wxuG zZhSp`+Om9JUgC9r@?#FoM`;cRdDCR~!MbhFOCPGU503+`l1t$?D_z|F4wC1{H4X=> zU}LnglLFY*R*3h$d=mc0$Gv9-Lw~-?CN~VQ?h63&kcEOd#pxC7M#HT|Bpr=|2{N2% zqi$Iyuy59uWMj)4OI%f7M|-S3l_%}kRUwal zEm2k18fF=!nN~nfRh9Y{F^#0zh3wI zYAILzD!Dnm&RROL_8{_cIqSDSnsj6mL# zFa`NqR#xICJN2hWw8rLg01F+M+HHJ{+R;hNi|J>47uI2P|HJ=UL8$M6CRL`-V{rDE4cVzi-n(E1}JJ0g%j+%U%sXy4V z%^-RCZ4wtj$Ys78c^>I}7j9b*zxmiE7{n#4QkUEV?HqG0`2MzOwbqKrym}&k8vl<& z14{Bj?!{IbNOMhI^;(|n8!=w*SzeF|>=UoaMj0V(tg{0CQk~{B&vui_;+TNgdAx zmCOx4vL9*C@f7#2mXf+(s#;t4!>1qaiUCQRfvxt*>PV|fyQyE%z;7kB*wNgW4QHCydR!sLi~IZr#=3u^Hcf8gSIuT0 zDk+k#FYZ8~f#Q<`oG{mWm3{`NFF`|dic@6g4MN=x`B<-N;-tC!#Fc5~Cn;rmRFeG7 z(eJms^aN`pJ83eJXFVfy>LGHhN1b8DMWlBrZB&Z?Z6wo{N3C zZ4vO29SK%2f5;b(St!KQo4vrG&Q(_kGFGog9{KH&Plr$Hu)VB=Sz7nd`X;8jBZJ+R z^8F0I3pM+hSH0(c9(Y!pq_(=wC1Gs?f7B;i1+?Y7|0P!o)Y{v)_n-GYk&nPmtS**Q zQ`LqnGf;t|a7~mT%umu=$K#;szb@a_$L}xq+^?u zOs1&T%;tky&Xvgmkds(FRvx$`@&A z=$)YN4W;NCEG{1nDK{wv+%8o8&N(vi1Yqg6@>>g9ljI{c7wbiW>>~$Ae%iZ)vA#i6 zU|(JBTycmA!K-F$Wr<7&QqH+2esU)!qRz$bl|$#eu6T96DtS)n{_OKDwJ=`;k$3pn zW0~TiMtPah`x}yfS`2Gi3g( z5FYs&#-pg`hIyz_(14KkOODM6>(cvLemX>t;CPd(Svp>mwspMrKKd@mY_d}FvC8SG z>C4b~?tBX^bSd>#0I|ZH$%Y^O$jN0St0GDV$&l)vG4v-z-O-m&WK>}3$vcs0DTZ_b zgifOQz9~aAr2z5)09$x-=*A6Ho#0xT9X#c zw+iK3GO8#C0a71uZYR461mi3x+E~cZ>DGlm=ttZ3Pe{jhE;p|9Qe@6pVW9dW-PHqqs0hcjmwcySVfKWD+FW{}3*CM}yy{E=3R&F1;jPksrw7+C||WpfYkYYRu0GsLOG^Nmssb%eJYz{*pp5Ps%J40a|57|B#jV41trVH z^Tdkn45TeJ^>qU^S}&4KQjmR8b9zK6(u)fOqE$wi?~!CKC(M7Ym^C(tA{iA(dH9r~ zsgLJ^d4H??*x0FPj&7Dz3Z4|dacn0GP{T^eEYU( zct!I9_gnvk`GOq6W%OK1X8*Lz5JKF@9ch!wTZ-@sYmbk~$}5Edo~x=1Xenlnk$RNZ z_tI0$T6_AIqm(gsVsIKoefDc}!w9=PBU59-%pziWvddCHNa3O(7T2+&-lF6m9Nt}h zHKTQVw(RtwoSB&0@m_LId|B?S`^mQ4_^MMpmAC$I+2u|anFJbiZP>uJsm2MDKq8S^ z0O(os5z2I`=N8X)FHoYAnK0ZNuq}8Ayd>QKc_DiYox1(yux}Vue8RK@wYaY_jOT0a zvTT|U2U!TQK3f%24}N`k?*~dwLKEuySETeP_2cG=JTo;UC0zBtg7r&J#C#-K!x3Zk z5aYwmc7FI}q8*6^{&s4ZEP?o$15rx6&;v}ImP6aX>hAHTTNyiA=ROsgT)#mmrr#Z^ z?o+zqC)W0p+!Zm1a*j2@aDg1uUMfP*rBK+H28U~8>uq`FX}L-q(pvB%jM01bx4+;3 z!4>DnCa4YTQBYOgd_%!jrhh~+SMx;ul^ASqX!M7YJ79a|V9C9v<`luBgQ&!LNKs%c z<5oU5#o$*Q1Sb02!`?8bxG7)m<^YJCFFk2{OL6ydbTZB3S&`@_k*iRU6P}%|#+0j3RQsPes#|js9R;JC#(7y7 zRT~w@ADbRyZip#hE(YlyTEg9Y)>(~2F92ka#1gqu4foEKm{45K|7#|1urtI|CxZ7E ztd_2TV)1$=0YdmRg-46G$x*5)YQ~-sED07vLByR$Frq-A^s&R$83a21zTMk)C$PNU z36+Y%X9b9tNUUDuUK>{o$Gy9}Asviwv_sH|X~l4-xBC@~;#Mt2#QgbVhi)WU+=X5X zuRs*s?KaBa9eISSY)MD`1WJ2W{KbGl0P2gF1S7^G&#LR}Rba zBMNy%FKcW=GS~y?8I=&gWH(w(X16g2Tj&AKUlb0xkPajUq2Oi_n96TUsMC zmkZD{TdyM}72B-taO;M?GM?)&kb7d>*X`^1_Vw_g7>&yzE4xbW@OaU{J}SPWrX4PRxuh0NWWClce3}xR=$GaV>7cu5`T3 zs&812Yq3+n$a`X-ffvq=b<9?(7#rZ)!QGrl#E*(@9j3b@llcThX z(=!2fhUKfj{rVSojIhx%X8P&aQUKQi2;;0jUxWk0vCdn$7FJ`{{*EBSmQJmC zpM*CMezC~49nYuM-hh?;n+a6O6~;mriD1JMfN697Hv?g#)fC&e2s1yu9skNp)Xar` z%u$L93dF2+=u`arHYG~F;0B##1|=;Yd6!zxs}iG){!7s7--@0Rvrg)61JCh&HhCn> zznFG5TXlUN)^_-vVN*x;0tembiHkg_`6&#Dx2ouTgz> zqr^=(y=|22ft579yqVM6JL5v%M`ogNb9(11Gh7NipulB!B_)crND82>U)Ws}%@2RB zV9KeE*Vt;$v;1^$4TS3pvB2c5(9lk>w|hLWEJ{Lw+iin zNW6zYfEIn$1H3lPGiJ8@vFb3m4| zp^-5Y8@>?2MumfuMAlwQzAt-uNJN&h3z-Uz#&QFf0SqkmOk0^@SD%psx;=Rp_$mdH z+$Cvi>z~@X2nl@=J|{B4zp3Nq9Y&%#C>mkPc{Ph6FS?Cpg{qC3NtREYydlQ1nu0x; zbZ!R?+TX1X$m&BG>Lu{nQ70Xi!zcU6u5qJ4pn=7u@5S*?d7$Uw^;ss|qv0ftV;s}k zbf##e;81*w5}z^*MHV;z#=4%rT1^`eS|#?PRzZBGybD6jSR&&i(BZxF5$UbWr6?#f7>Wm^JXLc}_gfiJ4 z?c=;KC zkQM|1?|C}lp%gfN@O2(0;50P6hP|}7QaEuB0E_=nf1*+uoIIx$D)m`iNT^5<#0vv| zy_5=2*zoH4b+TZb!DOx23#(-uu?&r?9SBGZqCt<6T^TP;19u*8CeUT-mhtM4zyN=G z2Q$85d;V+pN9sK;9!-fYk^idUr9EP@t7|86EYc0AIe5daLx94EiazQj#d_v3lAqyI ze1!7lJC9nG^f}gqi0PL1$AL1;=mqMw&MB6CvI}h7c?f(inz2$ur@x3BEa;XLWYx}` zxJTwOS%*%6TkMJEBN@w3qdko8Q`<_0(<%pTDd2W5S#bN_*`|6`bI$7=oS|~NKLY@lke$|Q&d`B| z{ll-iW>rTkjzn?@^Krd5@n+mt^6N40_SN;btbj?0 zOYL`=HxS4Qg5L)GbjO*`=RzMUBkRP<|9q}I*FGPXS$HM*i;d$eBvDV$tJwy>fDj_< z$n`rF*-d%3W~Advz|L6vspEdgP4jyMYMj&lj!)}3t+a#NqAR;@ zT>s>^On3_X{-ljN{uG&RFlEzU^0eap9fyoF4^88KW<%~bR)&EOlw(X?9MH$Ua!KN2 zhhGeuii<8PIZQoqWr%IBwDKX1w`8-FW|JgW`L6|MjSR;`gDcIp=fx~0`Nz1rG&N}i}n1mEf$XAnCdj-zk z-n72V;A7=_1eNA>O<|wuYc!Ydm_fDhRRt~730CEkYZ66-4XnYQK&aKQ$4L3GUF9NmbTy76gs$sw zC4)EKHMQnvm`bD*dPLXeE3EHPNhWxSA^Cjt*)|Cd3I=2w389kwv@95&ZcpD}Sd-2V zcvxzgi$-EvPlHOay57KKu1q5y5|fo%`@ZB55E>eN!VE`UN*(xhGxZ8TXkm+)4a#x} zb}&5d+N`3;(6_%?!lFf=jKwDq*a82pAoC%UfjE7HMn|K=w9K=u#lQL`L@Pu&i~a?7 zt+EMgfRSR>HI4sT)H3A`gUEP2=u9IBcpQb|VAsq!PoRo;#uJ*aMHWNJ&i(OpnaWKh z?R+@I>hgq#p+c}EgQ$K?qJtA$DY&% zn}v)%GQFpv_=3wYoh4LiQO4tWWHR=C-N)yg?VCr{dXX?iA0W6S;mv7Tm5}EA+H%-~ zJNZL42Sd%bGt;nKGNZ5Flb`w@R-25Agl`C;vHm~H)ucH(pP2Ih!fkOC&p&#nXtJd( zrP77L6T&cNnDbOTR?1yg7l;i>B~aUQ^4t*U zA6AtF?lu}5!=?lW!TYycdxG~dhXRoH?L9)g&38=5XnxGA&pFhQc!riJH775b4d|CL z5qCOUA-J6?^85zuRg(^x zZ`#LmxC~p5lwPFdDi=G#@Kb^f3HZ2;4xNk8)oOQLOWeh1_v7 z+@r>Fu}bV&a>|7}j=z&#tE)%v{a|3=X_q+$TkWzL7ZM#aIleWhA_Kva4YdQ71sWL4 z`V@?@_lBI0pvw_m)Q6w#^<|Kggt?qd2z8DPW>1xU%wILtj4B=Fd_9Li%bQlK5qQb4 zsgZ<|6vg9iG*P;|{&fj&T@-B~%x@U87azO8cX#s&=}Au{9!JucY;#c;D8nYr92m9k1?k?X1t9&io&hBy1L6xG3BX9uZ7#xiSvUqJ? zRz3AkJ$Ke*SD{mfEek0zW#5MC*Z=LHHn-lRlvlBekj?g3-ZkJEKJyQ%R{Km zn=wY~Kgq(wkmj?V3QWQuzGs3s{-p_TR~SGn{xwI_IRSVb&`c8zaL^!78bAn~y=qhZ yCx`g|d~>| zSe8&pvx+6c9y)T*eJ70IE&tK0U`|I=hey;D&`}6tj>M;i!C56oj z5C}xc_6Wui0+Bti{F9f3Kp^Au4mb#8gRCv)p!0>>yq=>;o+Ht+No{L)Ac2D>k!dw>I}7h(tAC?t?n8fD2RyJr`TW_kv`6WLJ?d z^;0F;AM>=YC9|r1Z?2m~PD znOCMb0Fa_5cQe7_(#p2>g>qHCuB&()YxLs8+p)s$qU{#Ox>&nh-W3PUwnXvZgq_if zMq5EplD->*cZRKp1w@kwEsr6&V5u0#zy2ZmVK~#R!)h1DI%>XVDgnDmG8nKtAyrc5 zBoxj;Pdf*B}lCCy5__rg%$2}Zk{{SRN)%H5aqCz4weY2Dc)oI#+0eC z{XgM{2@KW=IzTb*BD3}=^ho8jyZmqD^(i#QXQ23544PxbTxjTDr{i6`yClHBhMcyA@e@%A~X{Mf5U zE4cBi#5wk{B`zdXOdcc~np=VxO5a_xxhKnxF0n0oYDsdN9cM{=cQK~7sO;5%t7sQV zZ}(o9#0Pm0dp38uzu5l(lnWHuxn3Fe*z)NdzM#GZ zg4NZbaiuK3hn*twmj^zq@aoD?@2;8e&{a!#+|`5Hg{EeW9jy9E%k$QK&#@a7S%qF^ zCb0%-T^%4yYppn2;8kEaHeP`UFF?EYQD3?O=FMI#i2`wO9ZdT8ssxKQ=712^*&{==_yd% za!(79$TOm=K^a71s~2hD#V~%@j$?Uz!O1XY$(@OtUoy1xAU77SOH~?X`aA)*GS*#} zSS`qSjMjH4_FzzvbTJPWQ|cz-dqPTe1Q_F6=Z6nyUwX_w84-dwrJ zSE)KlZtP_(s<7)hUa_P&VP`Mv_=yh2QlW%6oV~>?CEk0M=p4g8JJstg?y*V9v_VHa zo9n5}x1hYf&<={jm-71;8l2em_1~6qgjePwOVIjt=iH!#BrJ4(5}gb*ZyDF)K2dB+l97Fa&=I=;$DV+tJn04 zT1o%|S!HB)54Ejpirrz`E87juw0K2=a*k)7hHXZfb{%v$WM;OJ4MkuBrD;XZ6N z+z)DTovX{Q^JKUiBZSJ4p0n;W>`e9$HAYM<3E|hqy3(Tt4OyP_2K$8s3*|1<65bE@ zek^UUPq^jJt8#^yeHFgWBPomaArc#L2EmqKgZ8$x6v1|6u~2t&WKP3KSMz;9_$@?z z+W|f9#v;oO5g)|JBYRy7tzhU)*PCY<6_2XEP8Y5#{6B;Q#u8ioL-fV$LT;B$; z-$owDK`G||1i4{rgh9!kV8>>VAsy1kY=XmdTI{rjhr2XX?>o$^*1XA8!A zNW~3114#@1B@e@+1LE35qb;p?zu9?wNk|}$80VVc|L}9N>@;4sd26Df|EHoHfKxN< z*!69aQTE;L)Cx=p*m}AhFMmA;`7CPo)f%Zw!;bWqAZ;+=4ISD<8+S?v&WFLMh}VAL zc)T|2@nU=|35$;TML?n?3iuI`!|53+bztho@$wr0WJiJ<1EgyH#;R*ifjC+@c>i&A zuJSRl+PVCHeO&;HmVpK`x!PdeSZ5_|~GPjG1X&LNfFrYxUJ^vxgPE+M` zq-_Q6*SItU+YC^uxMZZEffE~Z1)6WHJz=6GhK5Ct-bla}%^T~?5 cDp7$yf0r$ra>x((Qv_oBjRU6G+UN3r0re}YfB*mh literal 0 HcmV?d00001 diff --git a/game/tests/golden/board_material_L1_hero4.png b/game/tests/golden/board_material_L1_hero4.png new file mode 100644 index 0000000000000000000000000000000000000000..8bcf17a68d1f65e17f5e067ef95b13186ceb97f0 GIT binary patch literal 4166 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 M(Ub1A-gO``kQqakAUAe#d$M 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 P2;gArbf)6;)nEP>-o^(S literal 0 HcmV?d00001 diff --git a/game/tests/golden/board_material_L1_zoom2.png b/game/tests/golden/board_material_L1_zoom2.png new file mode 100644 index 0000000000000000000000000000000000000000..021215a29da3cd8a852bf812887acccbef710468 GIT binary patch literal 9418 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 TcMt^t?$5&1=1S!y$dmsAYD8AD literal 0 HcmV?d00001 diff --git a/game/tests/golden/board_material_L2.png b/game/tests/golden/board_material_L2.png new file mode 100644 index 0000000000000000000000000000000000000000..9aca067eef49aef43114744a9d64b1268852c656 GIT binary patch literal 22930 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 literal 0 HcmV?d00001 diff --git a/reports/2026-11-09-棋盘材质预览-v2.html b/reports/2026-11-09-棋盘材质预览-v2.html new file mode 100644 index 00000000..3aa4ffd4 --- /dev/null +++ b/reports/2026-11-09-棋盘材质预览-v2.html @@ -0,0 +1,18 @@ + +棋盘材质预览 v2 +
+

棋盘材质预览 v2 · 真实像素候选

+

同一母图换色;岩顶与地面均为 512×512 无缝材质。整板一次铺图,崖面为断续岩层,顶面黑边收薄。浮空数字、格边 46、间距 2、抬升 20、侧移 5 全部沿用。

+

三关整板

第一关 · 暖石棕
第二关 · 冷蓝灰
第三关 · 灰黑
+

崖面与岩顶细部(3×)

断续岩层、薄黑边、稀疏裂纹
+

数字与地面细部(3×)

低对比地面、浮空数字几何不变
+

无缝材质母图

第一关 · 暖石棕 · 岩顶 512×512
第一关 · 暖石棕 · 地面 512×512
第二关 · 冷蓝灰 · 岩顶 512×512
第二关 · 冷蓝灰 · 地面 512×512
第三关 · 灰黑 · 岩顶 512×512
第三关 · 灰黑 · 地面 512×512
+
artwork/2026-11-09-棋盘材质候选-v2/ · 材质已于 2026-11-09 录入 game/assets/art/board/;本页为过审视觉基线。
\ No newline at end of file diff --git a/reports/需求卡片-棋盘瓦片与立体表现重做批-2026-11-07.md b/reports/需求卡片-棋盘瓦片与立体表现重做批-2026-11-07.md index 0b75ad18..384032b3 100644 --- a/reports/需求卡片-棋盘瓦片与立体表现重做批-2026-11-07.md +++ b/reports/需求卡片-棋盘瓦片与立体表现重做批-2026-11-07.md @@ -1,10 +1,10 @@ # 需求卡片:棋盘瓦片与立体表现重做批 > 来源:`待办清单.md`「棋盘瓦片与立体表现重做」(2026-11-07 登记)。 -> **设计事实源(唯一事实源)**:`design/art/art-bible.md` v3.51 §1.4/§3.2/§4.1「三关棋盘环境八色」/§6.3/§7/§8.2+`design/ux/battle.md`(Last Updated 2026-11-07)「Layout Zones」D 区行/「D 区布局与棋盘画法预览」/「封印格呈现预览」+`design/gdd/systems/表现与支撑/HUD框架.md`(2026-11-07)D 区行与字号下限+`game/tests/golden/README.md`「越格口径」。 +> **设计事实源(唯一事实源)**:`design/art/art-bible.md` v3.53 §1.4/§3.2/§4.1「三关棋盘环境八色」/§6.3/§7/§8.1「格边长与材质分工」/§8.2/§8.5「生产分工」+`design/ux/battle.md`(Last Updated 2026-11-09)「Layout Zones」D 区行/「D 区布局与棋盘画法预览」/「封印格呈现预览」+`design/gdd/systems/表现与支撑/HUD框架.md`(2026-11-07)D 区行与字号下限+`game/tests/golden/README.md`「越格口径」。 > **验收档:中**(呈现与交互几何改动,后果玩家可见但不损持久状态;用户 U0 可改判)。 -> **预计**:9.5 个工作日(区间 9–10;T0 0.5/T1 1.5/T2 0.5/T3 2.0/T4 1.5/T5 1.5/T6 0.5/T7 1.0/T8 0.5)。 -> **卡片状态**:复核记录见 §16;第一轮 19 条、第二轮 23 条、第三轮 4 条、第四轮 5 条、第五轮 1 条、第六轮(合并整合)6 条均已处置,第六轮定向复核通过。 +> **预计**:11.0 个工作日(区间 10–12;T0 0.5/T1 1.5/T2 0.5/T-A 0.5/T3 2.5/T4 1.5/T5 1.5/T6 0.5/T7 1.5/T8 0.5)。 +> **卡片状态**:复核记录见 §16;第一轮 19 条、第二轮 23 条、第三轮 4 条、第四轮 5 条、第五轮 1 条、第六轮(合并整合)6 条、第七轮(材质实现回退)1 条、第八轮(浮空数字几何)1 条、第九轮(512 材质与过审同步)14 条均已处置,第七/八/九轮定向复核通过。 --- @@ -16,13 +16,13 @@ 1. 1280×800 基座档:12×12 格边 38px、14×14 格边 32px;D 区 1036×548;左/右栏各 200px;棋盘 12×12 外框 478×478、**屏幕坐标**原点 (523,296)、board_area 局部原点 (279,44);14×14 外框 474×474、屏幕原点 (525,296)、局部原点 (281,44)。 2. 顶行浮空数字视觉顶 y=258(含 2px 描边+1px 浮空投影),距 D 区上缘 6px;数字、引导线、阴影圆全部在 D 区内,无裁切。 -3. 岩体投影:LIFT=round(格边×0.435)、ESHIFT=round(格边×0.109);四邻连通合并;相邻岩顶搭接 2px;南崖高 LIFT、宽 格边+ESHIFT、顶缘 2px 口沿高光取本关受光棱(§4.1);东崖宽 ESHIFT、高 格边+LIFT;北/西 2px 主亮棱+2px 次亮棱+外 2px 深墨边;南/东 2px 深墨内缘+3×2px 内阴影(自缘内 0.217×格边起,α0.27/0.16/0.08);四段投影 4×4px(α0.44/0.30/0.16/0.07);整板悬崖 8px。 +3. 岩体投影:LIFT=round(格边×0.435)、ESHIFT=round(格边×0.109);四邻连通合并;相邻岩顶搭接 2px;南崖高 LIFT、宽 格边+ESHIFT、顶缘 1px 受光口沿+1px 深墨线;东崖宽 ESHIFT、高 格边+LIFT;北/西 1px 主亮棱+1px 次亮棱+外 2px 深墨边;南/东 3×1px 内阴影;崖面用低对比、断续且错开的岩块面,任何岩层线不得贯通整条崖面;南向投影 4×4px(α0.25/0.16/0.09/0.04)、东向 α0.22/0.14/0.07/0.04;整板悬崖 8px。 4. 深度排序:深度键=格底 y;岩体取最南格格底;升序绘制;南侧岩体画在小人之后并遮住小人脚底;小人所在格数字仍完整可见。格件顶面贴花/交互反馈随所属格件参与同一深度排序——北侧(脚底≤小人)低于小人(`z=0`),南侧(脚底>小人)随岩体在前(`z=3`);浮空数字仍最顶。 5. 浮空数字:字高 21px、2px 深墨描边+1px 浮空投影、暖白字芯、字底距格顶 15px、2px 双色引导线、10×6 阴影圆(圆心格顶+7,画在开启格地面、位于小人之下);数字与引导线 z 最高,任何地形/小人/特效不遮数字与引导线;小人可遮阴影圆。 6. D 区:左栏 AP 点阵+停手,右栏 RAP 点阵+数字+图例+弃图刷新;`side_rail_w=200` 入布局表;`ap_bar_h` 游戏视图零引用(布局表字段暂留供样张渲染工具,删除归工具批);棋盘底常驻操作提示条退役;toast 槽在左栏顶部且不覆盖棋盘与浮空数字。 7. 旧 `terrain_*` 63 件与 `tile_palette.gd`/`cell_base_layer.gd` 删除;`seal_mark.png` 保留;**普通数字**棋盘绘制路径零 `DIGIT_PLATE`/`plate` 调用;封印格身份字形色牌保留(迭代56封印改版,唯一例外)。 8. 封印呈现按迭代56「受理即揭示」口径:印记居已揭示地面格心、身份字形垫色牌叠于法阵之上、印记与色牌固定低于小人、该格不生成浮空 entries;封印格地面铺本关受光棱色封印石(零新增色,对封印黑对比 6.45–9.94:1),普通已开格地面仍为连续新地面。 -9. 三关(dungeon/underdark/deep_underdark)都走新材质与同一画法;三关八色按 art-bible §4.1 冻结(underdark 冷蓝灰、deep 灰黑);三关 golden 基线重制并在渲染闸通过。 +9. 三关(dungeon/underdark/deep_underdark)都走 512×512 新材质与同一画法;三关八色按 art-bible §4.1 冻结(underdark 冷蓝灰、deep 灰黑);三关 12×8 材质过审预览锚已按 2026-11-09 用户过审图重制,引擎侧 `board_L*` 三关 golden 基线仍待实现后按渲染闸口径换代并通过。 10. 命中仍按逻辑格矩形:点在抬升岩顶/崖面/浮空数字上不改变格坐标映射;16×16 等非当前板型由同一公式求值。 **不做**:真 3D、HD-2D、A/B 方案对照、旧瓦片回退、逐格新 PNG 瓦片、B/C 区改版、核心规则/数值/RNG 改动。 @@ -31,12 +31,12 @@ ## 2. 设计事实源 -- **画法与配色**:`design/art/art-bible.md` v3.51 §3.2「棋盘地形体系」八条(术语与定义/投影与搭接/受光与崖面/材质与装饰/投影与整板悬崖/绘制序与遮挡/浮空数字/旧资产处理)+封印印记条、§4.1「棋盘环境子板/三关棋盘环境八色/封印黑/数字色牌」、§6.3「三关 tile_closed/tile_open 终值」、§8.2「封印印记参数表」、§1.4 第一验收项。 +- **画法与配色**:`design/art/art-bible.md` v3.53 §3.2「棋盘地形体系」八条(术语与定义/投影与搭接/受光与崖面/材质与装饰/投影与整板悬崖/绘制序与遮挡/浮空数字/旧资产处理)+封印印记条、§4.1「棋盘环境子板/三关棋盘环境八色/封印黑/数字色牌」、§6.3「三关 tile_closed/tile_open 终值」、§8.1「格边长与材质分工」、§8.5「生产分工」、§1.4 第一验收项。 - **封印呈现前置**:迭代56「封印动作改版批」已闭合 `design/gdd/systems/排雷循环/排雷玩法.md` v2.0「封印受理即揭示」与 `design/ux/battle.md`「封印格呈现预览」——封印格 = 已揭示地面+法阵+身份字形色牌;本卡承接其地形换代(承载面改受光棱封印石、圆心仍格心、色牌与法阵层序不变),不重写揭牌逻辑。 -- **布局与像素判据**:`design/ux/battle.md`(2026-11-07)D 区行、棋盘格尺寸公式、「D 区布局与棋盘画法预览」像素判据表(含顶面/视觉 rect、悬停/路径 rect、层序)、Component Inventory 三行(行动资源侧栏/棋盘地形层/棋盘浮空数字层)。 +- **布局与像素判据**:`design/ux/battle.md`(2026-11-09)D 区行、棋盘格尺寸公式、「D 区布局与棋盘画法预览」像素判据表(含顶面/视觉 rect、悬停/路径 rect、层序)、「棋盘材质过审实图」节(12×8/46/≤32 色/无贯通岩层线)、Component Inventory 三行(行动资源侧栏/棋盘地形层/棋盘浮空数字层)。 - **HUD 契约**:`design/gdd/systems/表现与支撑/HUD框架.md` D 区行(侧栏/全高棋盘/提示条退役)、布局表高度口径、字号下限(浮空数字 21px 固定)。 - **验收面**:`game/tests/golden/README.md`「加严口径(棋盘三图)」「越格口径(2026-11-07 棋盘地形换代)」。 -- **上游已裁**:C 方向(合并岩体+越格画法+新大岩板材质)2026-11-07 用户看样张通过;顶栏搬两侧(D)2026-11-07 用户看三方案预览后选定;北/西受光、按样张调深、脚底行排序三项同会话裁定;underdark/deep 两关色板 2026-11-07 用户看方向样张后选定「按目标八色冻结」;棋盘底操作提示条退役同会话选定。 +- **上游已裁**:C 方向(合并岩体+越格画法+连续岩顶图/连续地面贴图材质+浮空数字)2026-11-07 用户看样张通过——用户裁的是画面外观,**不含「程序化材质」**;材质=无缝贴图、结构=程序化,分工按 art-bible §8.5。顶栏搬两侧(D)2026-11-07 用户看三方案预览后选定;北/西受光、按样张调深、脚底行排序三项同会话裁定;underdark/deep 两关色板 2026-11-07 用户看方向样张后选定「按目标八色冻结」;棋盘底操作提示条退役同会话选定。写卡段曾把材质误写成程序化,本卡按 2026-11-09 用户裁回退,见 §16 第七轮。**512×512 三关材质、断续岩块与薄边缘**于 2026-11-09 用户目检 `reports/2026-11-09-棋盘材质预览-v2.html` 后确认「没有问题,可以按这样」,本卡按该预览冻结。 --- @@ -64,14 +64,14 @@ | 普通已开危险格「危」当前垫色牌;落牌断言在玩家复制回归件(本卡后普通「危」改浮空、plate=false;封印格「危」仍垫牌) | `game/tests/unit/presentation/player_copy_sweep_test.gd:142-147`(`u.plate == true`) | | 单元测试入口登记 terrain 套件 | `game/tests/run_all.gd:225` | | 布局表字段被样张渲染工具读取(本批不改工具) | `tools/layout_config.py:12`;`tools/render_sample_sheet.py:51,956`;`tools/render_sample_sheet_v3.py:862,936` | -| 档期现状:待办清单已「已写卡」、roadmap 待编池「棋盘瓦片与立体表现重做(已写卡,待编排)」、08 已写卡 | `待办清单.md:265-268`;`roadmap.md:9`;`design/gdd/08-Alpha版本标准.md:149` | +| 档期现状:待办清单为「已写卡+已编迭代 57」,roadmap 迭代 57 已登记本卡、状态待开工;08 已写卡 | `待办清单.md` 本条目状态段;`roadmap.md` 迭代 57 行;`design/gdd/08-Alpha版本标准.md` 本卡行 | --- ## 4. 设计契约(🔴 触碰=L3 停机呈报) 1. 🔴 **只改呈现层与必要接线**:禁止改 `game/core/` 的排雷规则、棋盘数据、AP/RAP、战斗结算、RNG;棋盘数据只读。新增/修改只落 `game/presentation/`(含 `main.gd`/`main_debug_flow.gd` 的重建接线)、`game/probe/`、`game/tests/`、`game/data/schemas/`、`game/data/tables/` 与 `reports/`。 -2. 🔴 **不做逐格瓦片**:禁止保留或新增 16+5 逐格瓦片路径、`terrain_*` 回退、`TilePalette` 装图链;岩体/地面/崖面必须按整板矩形与格边程序化绘制,连通按四邻。 +2. 🔴 **不做逐格瓦片**:禁止保留或新增 16+5 逐格瓦片路径、`terrain_*` 回退、`TilePalette` 装图链;岩顶/地面材质用无缝贴图(按合并岩体与整板一次铺图,UV 用棋盘全局坐标、禁逐格重置;贴图来源与命名见 T-A),崖面/临空边缘/投影/层序等结构件程序化绘制;连通按四邻。 3. 🔴 **普通数字零底牌**:普通数字(含普通已开格的「危」/「?」)只走浮空描边字;禁止 `_digit_ink_mode` 三态、`plate_digit` 在普通数字路径复活。**封印格身份字形色牌为唯一例外**(迭代56封印改版:`plate=true`、`_draw_digit_plate` 保留、字形叠于法阵之上),禁把例外扩回普通数字。 4. 🔴 **浮空分层**:数字+引导线必须比地形/小人/封印/微光/交互反馈都高,任何元素不得遮数字与引导线;**阴影圆相反——画在开启格地面、位于小人之下**,小人站该格时遮住圆;顶行数字必须在 D 区内完整可见。**顶面贴花/交互反馈不得一律置顶**——随所属格件脚底行分档:北侧(脚底≤小人)低于小人,南侧(脚底>小人)随岩体在前;禁恢复“格件一律 z=3”。**封印格例外**:该格不生成浮空 entries/阴影圆,印记与身份色牌固定低于小人(整格 z=0,不参与南侧前推)。 5. 🔴 **命中按逻辑格**:`_cell_at` 仍用逻辑格矩形与 `SEP` 步长;抬升岩顶、崖面、浮空数字不是命中区;顶面左上角点按逻辑公式归属北/西邻格,不做“归本格”特判。 @@ -82,7 +82,7 @@ 10. 🔴 **文档不直改**:实现批禁写 `design/`、`game/tests/README.md`(能力清单由写卡段本批入表)、`roadmap.md`、`08-Alpha版本标准.md`、`待办清单.md`;发现条款偏差一律列 `reports/iter-反哺点-<日期>.md`。 11. 🔴 **不删断言换绿**:不得删除或放宽 `board_shot_probe` 的加严口径、渲染闸 2% 判据、`ui_contrast_probe` 对比断言;只允许按本卡 §12「测试削弱申报」列出的旧断言删除/替换。 12. 🔴 **拆分边界**:判据权威=`design/engineering/code-conventions.md` §1.1;每个拆出单元必须有职责语句与单一变化原因(§10);禁止为过阈值凑数拆件;拆不出内聚单元=停卡呈报。 -13. 🔴 **RNG 单点**:程序化材质/装饰噪声禁止 `randomize()`、自建 `RandomNumberGenerator`、消耗 `RngService` 共享流;一律用格坐标确定性哈希(同板同参逐位复现)。 +13. 🔴 **RNG 单点**:程序化结构/装饰噪声禁止 `randomize()`、自建 `RandomNumberGenerator`、消耗 `RngService` 共享流;一律用格坐标确定性哈希(同板同参逐位复现)。 14. 🔴 **色字面量落点**:三关八色只落 `board_terrain_palette.gd`;用 `Color("#RRGGBB")` 常量,禁 `Color8` 散落;其它绘制点只读 palette,禁第二份色值表。 15. 🔴 **BoardView 公开面不增**:`board_view.gd` 公开方法保持 27、类成员 ≤31(S13 基线;删 `_palette` 后 30);新增地形/浮空/阴影圆层一律落为**固定名字子节点**(`_world` 下 `TerrainBack`/`TerrainFront`/`LabelShadow`,壳层下 `FloatLayer`),三层在 `_init` 创建一次常驻、`rebuild` 只重跑 `setup` 不重建节点,经 `get_node_or_null` 取用,不新增类成员;只允许 `set_cell_area`/`rebuild` 增加可选参数与私有 `_visual_rect_for`/`_top_face_rect`/`_resort_cell_decals`,禁新增公开方法或成员。 16. 🔴 **封印呈现对齐迭代56**:封印印记居已揭示地面格心(不随岩顶 −ESHIFT/−LIFT 偏移);身份字形垫色牌叠于法阵之上(`seal_mark_layer` 子件 `show_behind_parent=true` 或等价实装)、不参与浮空层、不生成阴影圆;印记与色牌固定低于小人(封印格整格 z=0);封印格地面铺本关受光棱色封印石(零新增色,`palette.light_edge`);法阵参数(环径/环壁/十字/光圈)与揭牌逻辑沿迭代56,禁在本卡重写。 @@ -106,13 +106,13 @@ **不收件**: - B 区舞台/站桩、C 区数据框、AP/RAP 数值与规则、战斗结算、RNG、存档——一律不动。 -- 新增地形 PNG 素材:本批按已过审样张做程序化材质;若后续要换成 PNG 材质,另立登记条目走 asset-ingest。 +- 已过审 6 张地形贴图之外的再创作、换图或重新量化:T-A 只承接 2026-11-09 已过审的 512×512 六张;本批不再出程序化材质替身,也不以平色回退充当终稿。 - 真 3D/HD-2D、A/B 方案对照、用户试玩结论——试玩只登记不阻塞。 - 三关之外的板型专属美术(16×16 等)——同一公式与材质覆盖,不另出资产。 - 样张渲染工具(`tools/layout_config.py`、`render_sample_sheet*`)的 `ap_bar_h` 字段清理——布局表字段本批保留,工具换代登记待办清单后续直改。 - 三关互辨抽测工具 `tools/glow_discrimination_sheet.py` 的换代(读已删旧 `terrain_*`)——本批不跑;三关互辨由用户过审样张+`board_terrain_test._test_palette_three_boards` 逐值承担,工具换代登记待办清单后续工具批。 -**不收件去向**:B/C 区改版→待办清单新条目;PNG 材质替换→asset-ingest 登记;样张/互辨工具换代→待办清单(tools 批);条款偏差→反哺点清单。 +**不收件去向**:B/C 区改版→待办清单新条目;已过审六张之外的贴图再创作/换图→另立美术批;样张/互辨工具换代→待办清单(tools 批);条款偏差→反哺点清单。 --- @@ -120,15 +120,15 @@ | 文档 | 关联点(实现会改变它的哪条陈述) | 同步义务 | |---|---|---| -| `design/art/art-bible.md` §1.2/§3.2/§4.1/§6.3/§6.5/§7/§8.2 | 三关八色、四邻合并、顶面/视觉 rect、阴影视小、浮空字 1px 投影、贴花按脚底行分档、记忆态合成底、提示条 caption 退役;封印印记改已揭示地面格心+受光棱封印石+身份色牌层序(v3.51) | 设计段已按本卡写入 v3.51;实现读数若与条款不符→列反哺点,文档批裁决,实现批禁直改 | -| `design/ux/battle.md` §Layout/§Component/预览判据 | D 区全高、侧栏 200、棋盘 38/32、原点、顶预留 44、层序(贴花/交互按脚底行分档)、悬停/路径 rect、提示条退役;封印格承载面改受光棱封印石、圆心格心、色牌叠法阵 | 设计段已同步(2026-11-07);实现偏差→反哺点 | +| `design/art/art-bible.md` §1.2/§3.2/§4.1/§6.3/§6.5/§7/§8.1/§8.2/§8.5 | 三关八色、四邻合并、顶面/视觉 rect、阴影视小、浮空字 1px 投影、贴花按脚底行分档、记忆态合成底、提示条 caption 退役;封印印记改已揭示地面格心+受光棱封印石+身份色牌层序;岩顶/地面材质=无缝贴图、结构件=程序化(v3.53) | 设计段已按本卡写入 v3.53;实现读数若与条款不符→列反哺点,文档批裁决,实现批禁直改 | +| `design/ux/battle.md` §Layout/§Component/预览判据 | D 区全高、侧栏 200、棋盘 38/32、原点、顶预留 44、层序(贴花/交互按脚底行分档)、悬停/路径 rect、提示条退役;封印格承载面改受光棱封印石、圆心格心、色牌叠法阵;材质过审实图与 12×8/46/≤32 色/无贯通岩层线判据 | 设计段已同步(2026-11-09);实现偏差→反哺点 | | `design/gdd/systems/表现与支撑/HUD框架.md` D 区/字号 | D 区侧栏、全高棋盘、`ap_bar_h` 不再参与、浮空数字 21px、提示条退役 | 设计段已同步(2026-11-07);实现偏差→反哺点 | | `game/tests/golden/README.md` | 棋盘裁剪 1036×548、越格口径、类型微光禁越圈范围 | 设计段已同步;实现批禁直改,基线重制按该文件口径执行(重制前用户确认) | | `design/gdd/术语表.md` 掩尘/裸土/浮空数字/色牌 | 基色值、浮空数字定义、普通数字色牌退役+封印格色牌例外 | 设计段已同步;实现批禁直改 | -| `design/art/asset-path-map.md`/`art-assets-checklist.md` | 旧 terrain_* 退役、seal_mark 保留、普通数字色牌退役+封印格色牌例外、程序化材质无入包 PNG | 设计段已同步;实现删除资产后按反哺点核对 | +| `design/art/asset-path-map.md`/`art-assets-checklist.md` | 旧 terrain_* 退役、seal_mark 保留、普通数字色牌退役+封印格色牌例外、岩顶/地面 6 张无缝贴图入包(`board_rock_*`/`board_ground_*`) | 设计段已同步;实现删除资产后按反哺点核对 | | `design/engineering/architecture/architecture.md:178` | 单格两绘制域件行把 `cell_base_layer` 记为在役组件;本批删除该件、新增地形/浮空/阴影层 | 架构文档写权限=用户专属(2026-11-07 裁):实现批禁直改,T8 反哺点列「架构表该行待用户发令修订」 | | `game/tests/README.md` 能力表 | 新增 6 条能力;旧「地形瓦片套与格面数字可读」保留(删除归写卡段后续;实现批禁写);「战斗屏三区几何」代表用例改名 | 写卡段本批入表(本卡同 commit);实现批只核对名字与实际落地一致 | -| `roadmap.md`/`design/gdd/08-Alpha版本标准.md`/`待办清单.md` | 本卡已写/待编排状态 | 编排段与收尾段推进;实现批禁直改 | +| `roadmap.md`/`design/gdd/08-Alpha版本标准.md`/`待办清单.md` | 本卡已写卡/已编迭代 57、待开工 | 编排段与收尾段推进;实现批禁直改 | --- @@ -136,7 +136,7 @@ | 文件 | 行为改动/非行为 | 职责 | 验收行 | |---|---|---|---| -| `game/presentation/views/board_terrain_palette.gd`(新增) | 非行为(数据) | 三关八色表:`palette_for(board_type)`;dungeon/underdark/deep 取 art-bible v3.51 §4.1 冻结值;八槽键 `rock_top/ground/cliff/seam/bevel_light/bevel_dark/ink/light_edge`;封印石读 `light_edge`(零新增色);只读 | §12-14 | +| `game/presentation/views/board_terrain_palette.gd`(新增) | 非行为(数据) | 三关八色表:`palette_for(board_type)`+`tex_paths_for(board_type)`;dungeon/underdark/deep 取 art-bible v3.53 §4.1 冻结值;八槽键 `rock_top/ground/cliff/seam/bevel_light/bevel_dark/ink/light_edge`;封印石读 `light_edge`(零新增色);只读 | §12-14 | | `game/presentation/views/board_terrain_layer.gd`(新增) | 行为 | 地面、合并岩顶、南/东崖面、内阴影、四段投影、封印格受光棱封印石贴片;`setup(cell, cols, rows, wall_at, sealed_at, palette, board_type)`/`set_hero_foot_y()`/`set_pass()`/`mass_rects()`/`terrain_metrics()`;静态 `lift_for()`/`eshift_for()`;back/front 两实例(`_world` 下固定名字 `TerrainBack`/`TerrainFront`,不占 BoardView 成员) | §12-3/4/5/8 | | `game/presentation/views/board_float_layer.gd`(新增,Control) | 行为 | 外壳层浮空字:2px 描边、1px 浮空投影、双色引导线;`setup()`/`set_entries()`/`set_font()`/`label_rects()`/`label_metrics()`;不画阴影圆;**封印格不生成 entries**;壳层固定名字子节点 `FloatLayer`,不占 BoardView 成员 | §12-6/7 | | `game/presentation/views/board_label_shadow_layer.gd`(新增,Node2D) | 行为 | 开启格地面 10×6 四层阴影圆;`setup(cell, cells)`/`circle_rects()`(世界局部/格坐标);**封印格不生成圆**;`_world` 下固定名字 `LabelShadow`,不占 BoardView 成员;z=0,位于小人之下 | §12-6/7 | @@ -189,14 +189,14 @@ | 新文件 | 公开方法预算 | 成员变量预算 | 说明 | |---|---|---|---| -| `board_terrain_palette.gd` | 1(`palette_for`) | 8 个常量 | 纯数据;不新增类状态 | -| `board_terrain_layer.gd` | ≤7(`setup`/`set_hero_foot_y`/`set_pass`/`mass_rects`/`terrain_metrics`/`lift_for`/`eshift_for`) | ≤13(新增 `_sealed_at` 一个成员——封印石贴片输入;其余同前) | 两个实例共享一个类;`pass_mode` 区分 back/front | +| `board_terrain_palette.gd` | 2(`palette_for`/`tex_paths_for`) | 8 个色常量+2 个路径格式常量 | 纯数据;不新增类状态;贴图路径单点 | +| `board_terrain_layer.gd` | ≤7(`setup`/`set_hero_foot_y`/`set_pass`/`mass_rects`/`terrain_metrics`/`lift_for`/`eshift_for`) | ≤15(新增 `_sealed_at`、`_tex_rock`、`_tex_ground` 三个成员;其余同前) | 两个实例共享一个类;`pass_mode` 区分 back/front;贴图经 `UiKit.load_tex` 装载 | | `board_float_layer.gd` | ≤5(`setup`/`set_entries`/`set_font`/`label_rects`/`label_metrics`) | ≤8 | 一个 Control;所有数字在一个 `_draw` | | `board_label_shadow_layer.gd` | ≤2(`setup`/`circle_rects`) | ≤6 | 一个 Node2D;所有圆在一个 `_draw`;坐标=世界局部/格坐标 | | `ap_bar_view.gd`(改造) | 既有 10 个公开函数不减 | 既有 14 个成员不增(左右栏容器为 `_init` 局部变量) | 不新增公开面/成员;只改 `_init`/`_build_*` | | 三个测试件 | 每件 ≤20 个 `func _test_*` | 夹具变量 ≤15 | 不计生产接口;测试件无消费面 | -**存量触面**:`board_view.gd` 852 行、公开方法 27、类变量 31→30(删 `_palette`);本批只扩展 `set_cell_area(avail, side_rail_w := 0.0)` 与 `rebuild(board, minesweeper, side_rail_w := 0.0)` 的可选参数,新增 `_visual_rect_for`/`_top_face_rect`/`_resort_cell_decals` 私有方法,**不新增公开方法/成员**;地形/浮空/阴影圆层经固定名字子节点取用(`TerrainBack`/`TerrainFront`/`LabelShadow`/`FloatLayer`);S13 键只降不升。`board_zone_view.gd` 6→7 成员(新增 `_side_rail_w`,默认阈值内)。`board_cell_unit.gd` 12→13 成员(删 `base` 与 `_BASE_LAYER` 预载,新增 `top_face_offset`/`visual_rect`,保留 `plate` 封印色牌;净 +1;`ContactGlow`/`MemoryGround` 用固定名字子节点、不新增成员,默认阈值内)。`ap_bar_view.gd` 14 成员不增。`cell_mark_overlay.gd` 普通数字路径只减面,封印格色牌/字形面保留。迁移函数对账:`cell_base_layer.gd` 的 `draw_base`/`_draw_south_facade`/`_draw_north_projection`/`_draw_e_facade` 不迁入新件同名函数,新件按职责重写并保留像素判据;`tile_palette.gd` 的 `load_board_tiles`/`digit_ink_mode`/`normalize_floor_luma` 不迁移(职责退役)。 +**存量触面**:`board_terrain_layer.gd` 新增的贴图成员只服务材质面,不进 `board_view.gd`;`board_view.gd` 852 行、公开方法 27、类变量 31→30(删 `_palette`);本批只扩展 `set_cell_area(avail, side_rail_w := 0.0)` 与 `rebuild(board, minesweeper, side_rail_w := 0.0)` 的可选参数,新增 `_visual_rect_for`/`_top_face_rect`/`_resort_cell_decals` 私有方法,**不新增公开方法/成员**;地形/浮空/阴影圆层经固定名字子节点取用(`TerrainBack`/`TerrainFront`/`LabelShadow`/`FloatLayer`);S13 键只降不升。`board_zone_view.gd` 6→7 成员(新增 `_side_rail_w`,默认阈值内)。`board_cell_unit.gd` 12→13 成员(删 `base` 与 `_BASE_LAYER` 预载,新增 `top_face_offset`/`visual_rect`,保留 `plate` 封印色牌;净 +1;`ContactGlow`/`MemoryGround` 用固定名字子节点、不新增成员,默认阈值内)。`ap_bar_view.gd` 14 成员不增。`cell_mark_overlay.gd` 普通数字路径只减面,封印格色牌/字形面保留。迁移函数对账:`cell_base_layer.gd` 的 `draw_base`/`_draw_south_facade`/`_draw_north_projection`/`_draw_e_facade` 不迁入新件同名函数,新件按职责重写并保留像素判据;`tile_palette.gd` 的 `load_board_tiles`/`digit_ink_mode`/`normalize_floor_luma` 不迁移(职责退役)。 **指标例外申报**:无。若实现期发现 `board_terrain_layer.gd` 超过 7/13,按职责拆 `board_terrain_face_layer.gd`(崖面/投影)——先停卡呈报,不在实现段自行扩面。 @@ -227,7 +227,7 @@ - [ ] 跑 `board_shot_probe` 存三关当前帧与 `board_meta.json`,记下 hash;不重制基线(T7 才换代)。 - [ ] 确认 `game/assets/art/board/` 63 PNG+63 `.import`+`seal_mark.png` 在库;报告列清单。 - [ ] 跑 `python tools/gdstyle_gate.py` 记录 `board_view.gd` 当前 27/31 基线读数;跑 `python tools/capability_audit.py` 记录当前红项(T8 复跑)。 -- [ ] 录三关 `board_type` 字符串与 art-bible v3.51 §4.1 三关八色;不采样旧瓦片均值。 +- [ ] 录三关 `board_type` 字符串与 art-bible v3.53 §4.1 三关八色;不采样旧瓦片均值。 ### T1 布局表与 D 区侧栏(1.5 日) @@ -258,21 +258,34 @@ - [ ] `ui_input_probe.gd:360-366` 的 `set_cell_area` 恢复调用带 `main.db.presentation.battle_layout.side_rail_w`;`board_gen_reward_test` 的 2 参调用保持(测试独立口径)。 - [ ] 跑 `board_terrain_test` 与 `layout_probe`;报告写读数。 -### T3 地形深度层(2.0 日) +### T-A 地形贴图接入(0.5 日,asset-ingest 段,2026-11-09 已完成) -**取用**:T2 的格边/原点;art-bible v3.51 §4.1 三关八色。 +**取用**:用户 2026-11-09 目检通过的 `reports/2026-11-09-棋盘材质预览-v2.html`+art-bible v3.53 §8.1/§8.5。 +**产出**:三关岩顶/地面 6 张 512×512 无缝贴图入 `game/assets/art/board/`;`asset-path-map`/`art-assets-checklist`/`art-status-checklist` 登记;`.import` 边车;像素域 ≤32 色。 + +- [x] 资产契约:`board_rock_.png`/`board_ground_.png`,board_type=dungeon/underdark/deep_underdark;无缝、无边框/无亮边/均匀光照、方形;源尺寸 **512×512**;同一母图换色;单张像素域 ≤32 色。 +- [x] 素材已按 asset-ingest 段接入:用户 2026-11-09 对三关整板、崖面/数字细部与 6 张母图确认「没有问题,可以按这样」;预览图作 `board_material_shot_probe` 目标图(非引擎基线),旧 C 方向原稿不再作为新材质基线。 +- [x] 落位与边车:6 张全部在 `game/assets/art/board/`,命名合规;Godot 4.7.2 `--import` 已生成 6 个 `.import`。已按 `asset-path-map` §1 把 6 PNG+6 `.import` 同步到主区与 `board-material-fix` 工作区,两区各 12 项一致。 +- [x] `asset-path-map.md` 的 `board/` 行改为「512×512 岩顶/地面 6 张无缝贴图+seal_mark」;`art-assets-checklist.md` 记录贴图材质;`art-status-checklist.md` 新增「棋盘岩顶/地面材质 6 张」✅ 行。 +- [x] 缺位容错:`UiKit.load_tex` exists 守卫;缺图只在开发态回落 palette 平色,正式包必须 6 张齐;`board_terrain_test._test_material_assets_present` 断言 6 张在库。 +- [x] 已删旧候选口径:不再引用 `artwork/2026-11-09-棋盘材质候选/` 的 128×128 稿与 `board_preview_three_levels.png`。 + +### T3 地形深度层(2.5 日) + +**取用**:T2 的格边/原点;T-A 的 6 张贴图;art-bible v3.53 §4.1 三关八色。 **产出**:`board_terrain_palette.gd`、`board_terrain_layer.gd` 两个实例(back/front);`BoardView` 装配;`cell_base_layer.gd` 删除;接触带迁入 CellUnit。 -- [ ] `board_terrain_palette.gd`:八色常量(`Color("#...")`)按 art-bible v3.51 §4.1 三关表;八槽键 `rock_top/ground/cliff/seam/bevel_light/bevel_dark/ink/light_edge`;`palette_for(board_type)` 返回 Dictionary;未知 board_type 回退 dungeon 并记录(fail-fast 只在核心,呈现回退不刷错)。 +- [ ] `board_terrain_palette.gd`:八色常量(`Color("#...")`)按 art-bible v3.53 §4.1 三关表;八槽键 `rock_top/ground/cliff/seam/bevel_light/bevel_dark/ink/light_edge`;`palette_for(board_type)` 返回 Dictionary;`tex_paths_for(board_type)` 返回岩顶/地面两条 `res://assets/art/board/...` 路径(路径单点);未知 board_type 回退 dungeon 并记录(fail-fast 只在核心,呈现回退不刷错)。 +- [ ] `board_terrain_layer.gd` 材质面:`setup` 末尾经 `UiKit.load_tex` 装载 `_tex_rock`/`_tex_ground`(exists 守卫,禁 preload);地面整板一次铺图(`draw_texture_rect` 或等价,UV 用棋盘全局坐标);岩顶按合并岩体一次铺图(同块岩体内相邻格 UV 连续、禁逐格重置、无拼缝);崖面用低对比、断续且错开的岩块面,临空边缘收薄,内阴影与投影按 §1 完成定义 3;缺图时退回 palette 平色(仅开发容错,正式包必须 T-A 6 张齐)。 - [ ] `board_terrain_layer.gd`:`setup(cell, cols, rows, wall_at, sealed_at, palette, board_type)`(`sealed_at` = 封印格查询 Callable);`set_pass("back"/"front")`;`set_hero_foot_y(y)`;`_draw()` 中**地面/投影/封印石/背岩体只在 back 画**(整板悬崖仍由 `BoardWorld._draw` 承担,不重复绘制),岩体按 pass 过滤(back=脚底≤hero,front=>hero),每个 setter 调 `queue_redraw()`;静态 `lift_for(cell)`/`eshift_for(cell)`。 -- [ ] 封印石贴片(back):`sealed_at(c)` 为真的格,在连续地面之上铺本格逻辑 rect 的 `palette.light_edge` 实色(可带 1px `palette.seam` 收边),不越格、不加新色;封印黑对受光棱对比 6.45–9.94:1(art-bible v3.51 §3.2/§4.1)。 -- [ ] 岩顶公式:`LIFT=round(cell*0.435)`、`ESHIFT=round(cell*0.109)`;四邻连通合并;相邻墙顶搭接 2;板边外延 ESHIFT;南崖高 LIFT、宽 cell+ESHIFT;东崖宽 ESHIFT、高 cell+LIFT;禁竖条纹。 +- [ ] 封印石贴片(back):`sealed_at(c)` 为真的格,在连续地面之上铺本格逻辑 rect 的 `palette.light_edge` 实色(可带 1px `palette.seam` 收边),不越格、不加新色;封印黑对受光棱对比 6.45–9.94:1(art-bible v3.53 §3.2/§4.1)。 +- [ ] 岩顶公式:`LIFT=round(cell*0.435)`、`ESHIFT=round(cell*0.109)`;四邻连通合并;相邻墙顶搭接 2;板边外延 ESHIFT;南崖高 LIFT、宽 cell+ESHIFT;东崖宽 ESHIFT、高 cell+LIFT;崖面分段由格坐标确定性哈希驱动,任何岩层线不得贯通整条崖面,禁规则三角装饰带与竖条纹。 - [ ] `BoardView` 在 `_init` 以固定名字子节点创建一次常驻的 `_world/TerrainBack`(z=-1)与 `_world/TerrainFront`(z=2),不新增类成员;两层设 `use_parent_material = true`(随 `_world.material` 去饱和);back 画地面/投影/封印石/背岩体;front 画南侧岩体;`hero z=1` 不变;格件 z 按脚底行分档(北侧 0、南侧 3;**封印格恒 0**),由 `_resort_cell_decals` 重算(顶面贴花/交互/迷雾同格件 z);`board_world` 悬崖保留 z=0、`mat` 取新 palette 岩顶色(`_refresh_slab` 不再写 `COL_BRICK`);`rebuild` 清 `_world` 子件时跳过 `TerrainBack`/`TerrainFront`/`LabelShadow`(只清格件与英雄),再对各层重跑 `setup`(不重建节点);`setup` 传入 `_minesweeper.has_seal` 作 `sealed_at`。 - [ ] `BoardView._resort_cell_decals()`(私有):遍历 `_cells`,`u.z_index = 0 if u.seal_on else (3 if c.y > hero.y else 0)`;`ContactGlow`/`MemoryGround` 子件 `z_as_relative=false`、`z_index=-1`(全局 -1:地面之上、阴影圆 0 之下);`refresh` 与 `_update_hero` 末尾调用;hero 缺位时全部按 0 档。 - [ ] `board_view.gd` 删 `_paint_cell_base`/`_paint_cell_facade`(及 `_paint_cell`/`refresh` 调用)、`_floor_tile_for`/`_wall_tile_for`、`_build_cell_unit` 的 `u.base.bevel`;`_paint_cell_ink` 删 `bg` 计算/返回(`COL_FLOOR`/`COL_BRICK` 随之删)但保留 glyph 计算:**封印格写 `u.glyph`/`u.glyph_color`/`u.plate=true`(色牌字形),普通已开格只把 glyph 交给浮空 entries、`u.glyph` 留空**;`_apply_contact_bands`/`_process`/`_reset_breath` 的 `u.base.contact_*` 改调 `ContactGlow.set_bands(bands, corners, color, ground_visible_rect)`(不再经 `u.base`);`COL_DIGIT` 无引用即删;英雄贴图缺位字形「人」回退随基座退役(T4 登记)。 - [ ] 删除 `cell_base_layer.gd`;`board_cell_unit.gd` 去 `_BASE_LAYER` 预载、`base` 成员与 `base.draw_base`,文件头注删 `cell_base_layer` 引用;英雄蓝框随基座退役;接触带绘制迁入固定名字低层子件 `ContactGlow`(`z_as_relative=false`、全局 z=-1:地面之上、阴影圆 0 之下;只画英雄格地面侧,正交整边/斜向角点+两半边,逻辑格边,不进岩体);记忆态地面色/灰罩/记忆墨数字迁入固定名字低层子件 `MemoryGround`(同全局 -1);BoardView 计算 `ground_visible_rect`(本格逻辑 rect 扣除南/东邻未开格岩顶越入,南邻约 LIFT−SEP、东邻约 ESHIFT−SEP)并下发 `MemoryGround.setup(...)`/`ContactGlow.set_bands(..., ground_visible_rect)`,子件不读棋盘、CellUnit 不增成员;两个低层子件只绘地面可见区,禁整矩形覆盖 back 岩顶/崖面;设 `use_parent_material = true`(随世界去饱和);`draw_removed_dim` 墙格改顶面 rect。 - [ ] `standee_present_values_test.gd:79-86`:`cell_src` 源码锚由 `cell_base_layer.gd` 改指 `board_terrain_layer.gd`(北/西主亮棱绘制点),删 `FACADE_HIGHLIGHT_PX), UiKit.BRICK, true` 断言;`body_src` 段保留;跑该件至 0。 -- [ ] `board_terrain_test.gd:_test_merged_mass_geometry`:四邻合并、相邻墙顶 rect 相交/搭接 2、无墙顶内框、地面无缝;`_test_projection_ratios`:38 格 LIFT=17、ESHIFT=4、南崖 17×42、南崖顶缘高光=本关受光棱、东崖 4×55、北/西 2+2+外 2 墨边、南/东内阴影 3×2。 +- [ ] `board_terrain_test.gd:_test_merged_mass_geometry`:四邻合并、相邻墙顶 rect 相交/搭接 2、无墙顶内框、地面无缝;`_test_projection_ratios`:38 格 LIFT=17、ESHIFT=4、南崖 17×42、南崖顶缘 1px 受光口沿+1px 深墨线、东崖 4×55、北/西 1+1+外 2 墨边、南/东内阴影 3×1、崖面无贯通岩层线;`_test_material_assets_present`:6 张 512×512 贴图在库且 `tex_paths_for` 三关路径非空;`_test_material_vs_structure`:岩顶/地面采样来自贴图(相邻格 UV 连续、无平色断带),崖面/边缘仍为 palette 结构色。 - [ ] `board_terrain_test.gd:_test_depth_order`:三行夹具,断言 back 含北岩体、front 含南岩体、hero 在两者之间;北侧格件 `z_index=0`、南侧格件 `z_index=3`、**封印格(含南侧)`z_index=0`**、`ContactGlow`/`MemoryGround` 全局 -1;南岩体覆盖小人脚底像素(探针)。 - [ ] `run_all.gd` 注册 `board_terrain_test.gd`。 - [ ] 跑三关 golden 采集(先不重制基线)看差异落点;报告写地形层 draw calls。 @@ -282,12 +295,12 @@ **取用**:T2 的原点/格边;T3 的深度分层。 **产出**:`board_float_layer.gd`(Control 外壳)、`board_label_shadow_layer.gd`(Node2D 世界层);`BoardView` 装配;`cell_mark_overlay` 删数字路径。 -- [ ] `board_float_layer.gd`:`setup(cell, origin, entries, font)`(origin = 壳层棋盘原点);`_draw()` 画双色引导线(左深右浅、2px、格顶−12..格顶+4)→数字(字高 21、2px 八向描边、1px 浮空投影、暖白芯);`危/?` 同规则;`label_rects()`/`label_metrics()`(壳层局部坐标);全幅 Control(`mouse_filter=IGNORE`)、z 最高;每个 setter 调 `queue_redraw()`;**不画阴影圆;封印格不进 entries**。 -- [ ] `board_label_shadow_layer.gd`:`setup(cell, cells)`(世界局部/格坐标系,不传 shell 原点;`cells` = 浮空 entries 的格集,**不含封印格**);`_draw()` 画 10×6 四层同心椭圆(外→内 α40/70/105/140,尺寸 100%/80%/60%/40%;用 `draw_set_transform` 缩放后 `draw_circle` 或 16 点椭圆多边形,禁单用 `draw_circle`);圆心 = 逻辑格心、格顶+7;z=0(小人之下);`circle_rects()`(世界局部);setter 调 `queue_redraw()`。 +- [ ] `board_float_layer.gd`:`setup(cell, origin, entries, font)`(origin = 壳层棋盘原点);`_draw()` 画双色引导线(左深右浅、2px、格顶−12..格顶+4,线底接阴影圆上缘)→数字(字高 21、2px 八向描边、1px 浮空投影、暖白芯);`危/?` 同规则;`label_rects()`/`label_metrics()`(壳层局部坐标);全幅 Control(`mouse_filter=IGNORE`)、z 最高;每个 setter 调 `queue_redraw()`;**不画阴影圆;封印格不进 entries**。**几何硬口径**:字高 21 = 字形墨高(不含描边),渲染字号取使墨高=21 的值(现行融合像素字体 27;`FONT_H` 仍记 21 作墨高/矩形高);`draw_string`/`draw_string_outline` 的 pos 是**基线**,一律传 `rect.position + Vector2(0, FONT_H)`(矩形底边),禁把矩形顶当绘制原点;`_label_rect` 行 y 用步距 `(格边 + 2)`(与格件/引导线/阴影圆同式),字底 = `origin.y + c.y × 步距 − 15`、矩形高 21;多行不得按 `c.y × 格边` 落位(逐行漂移 2px)。 +- [ ] `board_label_shadow_layer.gd`:`setup(cell, cells)`(世界局部/格坐标系,不传 shell 原点;`cells` = 浮空 entries 的格集,**不含封印格**);`_draw()` 画 10×6 四层同心椭圆(外→内 α30/52/78/108,尺寸 100%/80%/60%/40%;用 `draw_set_transform` 缩放后 `draw_circle` 或 16 点椭圆多边形,禁单用 `draw_circle`);圆心 = 逻辑格心、格顶+7;z=0(小人之下);`circle_rects()`(世界局部);setter 调 `queue_redraw()`。 - [ ] `BoardView` 在 `_init` 以固定名字子节点创建一次常驻的 `FloatLayer`(BoardView 子 Control,全幅,z 最高)与 `_world/LabelShadow`(Node2D,z=0),不新增类成员;`LabelShadow` 设 `use_parent_material = true`,`FloatLayer` 不在 `_world` 材质链,`set_desaturated` 同拍给 `FloatLayer.material = _desat_mat`/`null`(结算期浮空数字同样灰化,禁成彩色例外);`rebuild` 清 `_world` 子件时跳过 `LabelShadow`(T3 同款跳过表);entries 由 `refresh` 的已开记录生成(`1–8`/`危`/`?`),**封印格跳过**(其字形走色牌),记忆态不生成 entries。 - [ ] `BoardView.set_world_font(f)` 同时 `FloatLayer.set_font(f)`;`cell_mark_overlay.gd` 删普通数字字形/色牌路径,**保留封印格字形+`_draw_digit_plate` 色牌**;`BoardCellUnit.plate` 保留(封印格 `true`、普通格 `false`);`board_view.gd` 删 `_digit_ink`/`_palette.digit_*`;`refresh` 字形段删 `_digit_ink` 三档与 `plate_digit` 普通路径(:586-591),封印格写 `u.glyph`/`u.glyph_color`/`u.plate=true`,普通已开格只交 entries(记忆墨仍用 `FOG_MEMORY_INK`;浮空字固定暖白芯);英雄贴图缺位字形「人」回退随基座退役(资产在包,正常路径不可达),实现报告「实现决定记录」登记。 - [ ] `run_all.gd` 注册 `board_float_label_test.gd`。 -- [ ] `board_float_label_test.gd:_test_label_geometry`:字高 21、字底距格顶 15、视觉顶距格顶 38、线 2px、1px 投影;`_test_topmost_layer`:`FloatLayer` 为 BoardView 子 Control、z 最高、顶行 rect 在 D 区内(顶行 top=6 local);`_test_shadow_circle`:圆 10×6、圆心格顶+7、`_world/LabelShadow.z==0` 低于 hero、开启格才有圆、封印格无圆;`_test_desaturation`:`set_desaturated(true)` 后 `FloatLayer.material` 与 `TerrainBack/TerrainFront/LabelShadow` 的 `use_parent_material` 同拍生效;`_test_contrast`:四类底复合对比 ≥4.5。 +- [ ] `board_float_label_test.gd:_test_label_geometry`:字高 21(墨高;矩形高 21)、字底距格顶 15、视觉顶距格顶 38、线 2px、1px 投影;**行 y 按步距 `(格边+2)` 落位**(至少两行断言,第 2 行起零漂移);三关截图目检数字墨底与引导线相接、线底接住阴影圆上缘、无长线悬空;`_test_topmost_layer`:`FloatLayer` 为 BoardView 子 Control、z 最高、顶行 rect 在 D 区内(顶行 top=6 local);`_test_shadow_circle`:圆 10×6、圆心格顶+7、`_world/LabelShadow.z==0` 低于 hero、开启格才有圆、封印格无圆;`_test_desaturation`:`set_desaturated(true)` 后 `FloatLayer.material` 与 `TerrainBack/TerrainFront/LabelShadow` 的 `use_parent_material` 同拍生效;`_test_contrast`:四类底复合对比 ≥4.5。 - [ ] `board_float_label_test.gd:_test_no_ordinary_plate_path` 与 `board_terrain_test.gd:_test_seal_substrate` 扫描/断言:普通数字路径(`board_view.gd`/`board_float_layer.gd` 与 `cell_mark_overlay` 的非封印分支)零 `plate_digit`/`_digit_ink_mode`;`DIGIT_PLATE`/`_draw_digit_plate` 只在封印格分支命中。 - [ ] 跑 `board_float_label_test`;三关截图看顶行数字越界与小人遮圆;报告写读数。 @@ -298,7 +311,7 @@ - [ ] `BoardView._top_face_rect(c)`(私有)= 墙格 `Rect2(x-ESHIFT, y-LIFT, cell, cell)`、地面格逻辑 rect;`BoardView._visual_rect_for(c)`(私有)= 墙格 `Rect2(x-ESHIFT, y-LIFT, cell+ESHIFT, cell+LIFT)`、地面格逻辑 rect;两者不新增公开方法。 - [ ] `CellUnit` 增 `top_face_offset`(墙格 `(-ESHIFT,-LIFT)`、地面 `(0,0)`)与 `visual_rect`;`_draw` 用 `Rect2(top_face_offset, edge, edge)` 传给 face;`_sync_seal_layer` 调 `setup(edge, visible)`(**不传 top_face_offset**——封印居逻辑格心,见下条);`cell_type_glow_layer.setup(edge, group, top_face_offset)`;`cell_mark_overlay` 的变异/徽章/悬停/退色/路径按该 rect(墙格顶面、地面逻辑;路径点迹只地面逻辑)。 -- [ ] 封印圆心:`seal_mark_layer.setup(edge, visible)` 不变(子件本地全幅 draw_rect,圆心 = CellUnit 本地 `(edge/2, edge/2)` = 逻辑格心);**不随岩顶 −ESHIFT/−LIFT 偏移**(art-bible v3.51 §3.2/§8.2);环径/环壁/十字/光圈比例不变;验收 `ring_px` 仍 82%±1。封印子件设 `show_behind_parent = true`,保证身份色牌叠于法阵之上;封印格地面受光棱石由 `board_terrain_layer` back 画(T3)。 +- [ ] 封印圆心:`seal_mark_layer.setup(edge, visible)` 不变(子件本地全幅 draw_rect,圆心 = CellUnit 本地 `(edge/2, edge/2)` = 逻辑格心);**不随岩顶 −ESHIFT/−LIFT 偏移**(art-bible v3.53 §3.2/§8.2);环径/环壁/十字/光圈比例不变;验收 `ring_px` 仍 82%±1。封印子件设 `show_behind_parent = true`,保证身份色牌叠于法阵之上;封印格地面受光棱石由 `board_terrain_layer` back 画(T3)。 - [ ] 类型微光:绘制 rect 改顶面 rect;`board_shot_probe`/`type_glow_shot_probe` 的「禁越圈」允许区改顶面 rect;微光不越出本格岩顶。 - [ ] 迷雾:`CellUnit._draw_fog_layer` 墙格画三块黑罩(顶面 rect+南面 `Rect2(x-ESHIFT,y-LIFT+cell,cell+ESHIFT,LIFT)`+东面 `Rect2(x-ESHIFT+cell,y-LIFT,ESHIFT,cell+LIFT)`;只在未开格);记忆态由固定名字低层子件 `MemoryGround` 画新地面色(palette floor)+灰罩+记忆墨数字,不读 `base.tex_base`,不生成浮空 entries;只绘地面可见区(扣南/东邻岩顶越入),不覆盖北/西邻格地面;封印格在记忆态同样随格隐没(印记与色牌不显)。 - [ ] 接触带:绘制迁入固定名字低层子件 `ContactGlow`(全局 z=-1:地面之上、阴影圆 0 之下);`board_view._apply_contact_bands`/`_process`/`_reset_breath` 改调 `ContactGlow.set_bands(bands, corners, color, ground_visible_rect)`,不再经 `u.base.contact_*`;只画英雄格地面侧,正交整边/斜向角点+两半边;只绘地面可见区(扣南/东邻岩顶越入);`_contact_unit` rect 不改;光不进岩体。 @@ -310,21 +323,22 @@ **取用**:T3/T4/T5 绿。 **产出**:63 PNG+63 `.import` 删除;`tile_palette.gd`/`terrain_tile_sets_test.gd` 删除;`player_copy_sweep_test` 落牌断言替换;`ui_contrast_probe` 迷雾派生段替换。 -- [ ] 删除 `game/assets/art/board/terrain_*` 63 PNG 与同名 `.import`;保留 `seal_mark.png`+`.import`。 +- [ ] 删除 `game/assets/art/board/terrain_*` 63 PNG 与同名 `.import`;保留 `seal_mark.png`+`.import` 与 T-A 的 6 张 `board_rock_*`/`board_ground_*` 贴图。 - [ ] 删除 `tile_palette.gd`、`terrain_tile_sets_test.gd`;`run_all.gd` 移除该套件;`board_view.gd`/`board_world.gd`/`ui_contrast_probe.gd` 的 `TilePalette` 引用全清。 - [ ] `player_copy_sweep_test.gd:142-147`:普通已开危险格 `u.plate==true` 改 `u.plate==false`,并断言浮空 entries 含该格(或 `label_metrics()` 有该格);封印格色牌断言归 `board_terrain_test._test_seal_substrate`;`ui_contrast_probe._fog_derived_check` 改读 `board_terrain_palette` 的新地面/岩顶色或渲染帧取样,三行行值按新地面色重算(±2/255),删除旧瓦片均值段。 -- [ ] `board_terrain_test.gd:_test_legacy_assets_absent`:目录无 `terrain_*`、`seal_mark.png` 在库;源码 grep 零 `terrain_`/`TilePalette`/`CellBaseLayer`/`u.base`。 +- [ ] `board_terrain_test.gd:_test_legacy_assets_absent`:目录无 `terrain_*`、`seal_mark.png` 在库、6 张 `board_rock_*`/`board_ground_*` 在库;源码 grep 零 `terrain_`/`TilePalette`/`CellBaseLayer`/`u.base`。 - [ ] 跑 `repo_structure_audit.py`、`capability_audit.py` 与 `board_terrain_test`;报告写清单;旧地形行**保留**(实现批禁写 `game/tests/README.md`;删除归写卡段后续,T8 audit 经卡内豁免通道绿)。 -### T7 验收面换代与三关 golden(1.0 日) +### T7 验收面换代与三关 golden(1.5 日) **取用**:T3–T6 全绿。 **产出**:`board_shot_probe` 视图 1036×548、侧栏 200、顶面 rect 微光圈/封印 rect;三关 golden 重制;渲染闸绿;`type_glow_shot_probe`/`layout_probe`/`ui_input_probe`/`ui_contrast_probe` 换代;三关色板逐值/互辨。 - [ ] `board_shot_probe.gd`:`view.size=Vector2(1036,548)`、`view.position=Vector2.ZERO`;`view.rebuild(..., 200)`;`_meta` 写全幅 rect;`_crop_cell` 用 `_visual_rect_for` 的屏幕换算;`_check_dual_frames` 的允许区改顶面 rect(用 `lift_for/eshift_for` 换算);**`_seal_evidence` 保持逻辑格 rect(封印居格心),选择器按迭代56后的 `has_seal` 口径**;注释与 `game/tests/golden/README.md` 口径一致。 - [ ] `type_glow_shot_probe.gd:64-78` 视图改 1036×548、`rebuild(..., 200)`(与生产同格边 38),允许区/取样改顶面 rect;`layout_probe.gd` 的 `_cell_for` 带侧栏;`ui_input_probe.gd` 的恢复调用带侧栏;`ui_contrast_probe` 浮空四类底段与迷雾段换代。 -- [ ] 跑一次渲染闸看差异(预判棋盘三图全幅 changed>0,属换代);**显式呈报用户,按 `game/tests/golden/README.md` 现行口径获用户确认后**再按 `tools/golden_baseline_refresh.sh` 重制三关基线;复闸绿。 -- [ ] 三关色板逐值核对:`board_terrain_test.gd:_test_palette_three_boards` 与 art-bible v3.51 §4.1 三关八色同值(用户 2026-11-07 已看样张冻结);`glow_discrimination_sheet.py` 读已删旧 `terrain_*`,本批不跑,工具换代登记待办(tools 批);不过即停卡呈报,不调色绕过。 +- [ ] 材质过审预览锚(非引擎帧):`game/tests/golden/board_material_L1.png`/`_L2`/`_L3`(三关整板,12×8、格边 46)+`board_material_L1_zoom2.png`/`_digit6`/`_hero4`/`_top4`(第一关机械裁切)已按 2026-11-09 用户目检通过的预览重制,并在 `golden/README.md` 登记为预览锚、明确不替代 `board_L*`;新增/扩展 `board_material_shot_probe` 以同一 12×8、46px 构图复刻,与 512×512 新材质、断续岩块和薄边缘对齐比对(材质/构图差异判据沿用渲染闸容差)。 +- [ ] 引擎侧 `board_L1_dungeon`/`board_L2_underdark`/`board_L3_deep_underdark` 仍待实现后换代:先跑一次渲染闸看差异(预判全幅 changed>0,属换代);**显式呈报用户,按 `game/tests/golden/README.md` 现行口径获用户确认后**再按 `tools/golden_baseline_refresh.sh` 重制三关引擎基线;复闸绿。材质过审预览锚不替代本步。 +- [ ] 三关色板逐值核对:`board_terrain_test.gd:_test_palette_three_boards` 与 art-bible v3.53 §4.1 三关八色同值(用户 2026-11-07 已看样张冻结);`_test_material_assets_present` 核对 6 张 512×512 与像素域 ≤32(实测岩顶 9 色、地面 6 色);`glow_discrimination_sheet.py` 读已删旧 `terrain_*`,本批不跑,工具换代登记待办(tools 批);不过即停卡呈报,不调色绕过。 - [ ] 跑 `bash tools/run_all_gates.sh --code`;报告写 smoke/unit/probe/render 读数。 ### T8 产出物落位(0.5 日) @@ -346,23 +360,23 @@ | 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+通过判据) | 层级 | 真实入口 | 判据绑定面 | 能力行 | |---|---|---|---|---|---|---| -| 1. D 区侧栏+提示条退役(判据:`design/ux/battle.md:124`、`design/gdd/systems/表现与支撑/HUD框架.md:62`) | `battle_layout_table.gd`、`battle_layout.tres`、`ap_bar_view.gd`、`board_zone_view.gd:23-37,74-79,91-92` | `board_side_rail_test.gd:_test_side_rail_layout`+`_test_signals`;`stage_background_test.gd:_test_side_rail_width_from_table`;`layout_probe.gd:_ready` | 单元+探针 | `BoardZoneView.new(layout)`→`ap_bar`/`_board_area`(测试读私有) | 左/右栏各宽 200、board_area 高 548、`side_rail_w==200`、hint 节点不存在、toast 不压棋盘 | 新增:D 区行动资源侧栏(AP 左栏、RAP 右栏、全高棋盘) | -| 2. 格边/原点/顶预留/重建接线(判据:`design/ux/battle.md:140,144`) | `board_view.gd:205-232,403-404,428-439`、`main.gd:470`、`main_debug_flow.gd:104` | `board_terrain_test.gd:_test_cell_formula_base`+`_test_hit_test_logical_rect`;`layout_probe.gd:_ready`;`ui_input_probe.gd` | 单元+探针 | `BoardView.set_cell_area(Vector2(1036,548), 200)`/`rebuild(..., 200)` | `_cell_for(12, Vector2(1036,548), 200)==38`、`_cell_for(14, Vector2(1036,548), 200)==32`、局部原点 (279,44)/(281,44)、屏幕 (523,296)、全格命中 | 新增:棋盘点击命中与格边公式(逻辑格矩形) | -| 3. 合并岩体+连续地面(判据:`design/art/art-bible.md:170,173`) | `board_terrain_layer.gd`(新增)、`board_view.gd`、删 `cell_base_layer.gd` | `board_terrain_test.gd:_test_merged_mass_geometry`;`standee_present_values_test.gd:_init`(V11 源码锚改指 `board_terrain_layer.gd`);三关 `board_shot_probe` 截图 | 单元+探针 | `BoardView.rebuild()`→`_world/TerrainBack`、`_world/TerrainFront` 的 `mass_rects()` | 四邻合并、相邻墙顶搭接 2、无墙顶内框、地面无缝、板边外延 ESHIFT;V11 口沿高光新锚在位且全套件绿 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | -| 4. 投影/崖面/受光(判据:`design/art/art-bible.md:171,172,174`) | `board_terrain_layer.gd` | `board_terrain_test.gd:_test_projection_ratios`;三关 golden | 单元+探针 | 同上 | 38 格 LIFT=17、ESHIFT=4、南崖 17×42、南崖顶缘高光=本关受光棱、东崖 4×55、北/西 2+2+外2、南/东内阴影 3×2 自 0.217 起、投影 4×4 α0.44/0.30/0.16/0.07 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | -| 5. 脚底排序遮挡(判据:`design/art/art-bible.md:175`) | `board_terrain_layer.gd`、`board_world.gd:39,48` | `board_terrain_test.gd:_test_depth_order`;三关截图 | 单元+探针 | 构造 hero 行与南邻墙;`terrain_metrics()["order"]`/`CellUnit.z_index` | back 含脚底≤hero 的岩体、front 含 >hero 的岩体;北侧格件 z=0、南侧格件 z=3、**封印格(含南侧)z=0**、`ContactGlow`/`MemoryGround` 全局 -1;南岩体覆盖小人脚底像素 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | -| 6. 浮空字+阴影圆几何/对比(判据:`design/art/art-bible.md:176`、`design/ux/battle.md:307`) | `board_float_layer.gd`(新增)、`board_label_shadow_layer.gd`(新增) | `board_float_label_test.gd:_test_label_geometry`+`_test_shadow_circle`+`_test_contrast`;`ui_contrast_probe.gd` 浮空字段 | 单元+探针 | `BoardView.refresh()`→`FloatLayer.set_entries()`/`_world/LabelShadow.setup()` | 字高 21、间距 15、视觉顶 38、线 2、1px 投影;圆 10×6、圆心格顶+7、z=0 低于 hero;**封印格无 entries/无圆**;四类底复合对比 ≥4.5 | 新增:棋盘浮空数字与引导线(最顶层、顶部预留) | -| 7. 浮空层最顶/顶行不裁切(判据:`design/ux/battle.md:165,307,313`) | `board_view.gd` 层装配、`board_float_layer.gd` | `board_float_label_test.gd:_test_topmost_layer`+`_test_desaturation`;三关截图 | 单元+探针 | `BoardView` 固定名字子件 z 序与 entries/`set_desaturated()` | `FloatLayer` 为 BoardView 子 Control、z 最高;`TerrainBack`/`TerrainFront`/`LabelShadow` 固定名字在树;顶行 rect top=6 local;无元素遮数字/线;结算期浮空层与地形层同拍灰化 | 新增:棋盘浮空数字与引导线(最顶层、顶部预留) | -| 8. 顶面锚点/封印/交互(判据:`design/art/art-bible.md:167,175`、`design/ux/battle.md:311-312`) | `board_view.gd`、`cell_mark_overlay.gd`、`seal_mark_layer`、`cell_type_glow_layer`、`board_cell_unit.gd` | `board_terrain_test.gd:_test_top_face_anchor`+`_test_seal_substrate`;`seal_mark_params_test.gd`;`type_glow_test.gd` | 单元+探针 | `BoardView.refresh()`→`CellUnit.visual_rect`/`CellUnit.z_index`/封印格 `plate` | **封印圆心=逻辑格心(不偏移)**、变异/微光/墙格悬停按 -ESHIFT/-LIFT;地面路径按逻辑 rect;环径 82%±1;封印格 `plate=true`、`glyph` 为危/数字、无浮空/无圆、色牌叠法阵上;封印格 z=0 低于小人,其余格件北 0/南 3 | 新增:棋盘顶面锚点与迷雾几何(微光、变异岩顶偏移,封印格心) | -| 9. 迷雾几何/记忆态(判据:`design/art/art-bible.md:427-429`) | `board_cell_unit.gd:_draw_fog_layer`/`MemoryGround`、`board_view.gd` | `board_terrain_test.gd:_test_fog_rect`+`_test_memory_cover`;`ui_contrast_probe.gd` 迷雾段;`type_glow_test.gd` | 单元+探针 | `BoardView.refresh()`→`CellUnit.fog_state`/`MemoryGround` | 墙格三块黑罩(顶面+南+东)覆盖、北/西邻格非岩顶地面像素零覆盖(岩顶投影可越入邻格屏幕区);地面格不越格;记忆态/退色不覆盖南邻岩顶(`MemoryGround` 只绘地面可见区,重叠区像素来自南邻墙体);封印格记忆态随格隐没;封印格地面=palette.light_edge;记忆态无浮空 entries;记忆墨对比 ≥4.5 | 新增:棋盘顶面锚点与迷雾几何(微光、变异岩顶偏移,封印格心) | -| 10. 命中逻辑格(判据:`design/ux/battle.md:140`) | `board_view.gd:428-439` | `board_terrain_test.gd:_test_hit_test_logical_rect` | 单元 | `BoardView.cell_center_local()`/`_cell_at()` | 全格 `_cell_at(cell_center_local(c))==c`;顶面左上角点按逻辑归北/西邻格;板外 (-9,-9) | 新增:棋盘点击命中与格边公式(逻辑格矩形) | -| 11. 旧资产退役/普通数字零底牌(判据:`design/art/art-bible.md:177,215`) | `game/assets/art/board/`、`tile_palette.gd`、`cell_base_layer.gd`、`terrain_tile_sets_test.gd` | `board_terrain_test.gd:_test_legacy_assets_absent`;`board_float_label_test.gd:_test_no_ordinary_plate_path`;`repo_structure_audit.py` | 单元+静态 | 扫描 `game/assets/art/board/` 与源码 | 零 `terrain_*`、零 `TilePalette`/`CellBaseLayer`/`u.base`、`seal_mark.png` 在库、普通数字零 `plate_digit`/`_digit_ink_mode`(封印格 `plate`/`DIGIT_PLATE` 为唯一例外) | 新增:旧瓦片退役与普通数字零底牌 | -| 12. 侧栏信号/setter(判据:`design/ux/battle.md:163`) | `ap_bar_view.gd` | `board_side_rail_test.gd:_test_signals` | 单元 | 真实按钮 `pressed`/setter | `stop_pressed`/`refresh_confirmed`/`legend_toggled` 逐信号;`set_ap`/`set_rap`/`set_refresh_state` 读数 | 新增:D 区行动资源侧栏(AP 左栏、RAP 右栏、全高棋盘) | -| 13. 接触带延续(判据:`design/art/art-bible.md:168`) | `board_cell_unit.gd`、`board_view.gd:740,764-765` | `board_terrain_test.gd:_test_contact_glow`;`type_glow_test.gd` | 单元 | `BoardView.refresh()`→`ContactGlow.set_bands(..., ground_visible_rect)` | 英雄格地面侧接触带在位,正交整边/斜向角点+两半边,只绘地面可见区、不进岩体;全局 z=-1 | 既有:未开格类型微光(8 邻作用集、五组色相、零玩法写入) | -| 14. 三关色板/互辨(判据:`design/art/art-bible.md:202,415`) | `board_terrain_palette.gd` | `board_terrain_test.gd:_test_palette_three_boards` | 单元+静态 | `palette_for("dungeon"/"underdark"/"deep_underdark")` | 三关八色与 art-bible v3.51 §4.1 逐值一致;三关同名槽位不全等(用户过审样张冻结);不变槽恒定;封印石读 `light_edge` | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | -| 15. 取证面换代(判据:`game/tests/golden/README.md:28,31`) | `board_shot_probe.gd`、`type_glow_shot_probe.gd`、`layout_probe.gd`、`ui_input_probe.gd`、`ui_contrast_probe.gd` | 三关 `board_shot_probe`+渲染闸;`type_glow_shot_probe`;`layout_probe.gd:_ready`;`ui_input_probe.gd`;`ui_contrast_probe.gd` | 探针+渲染闸 | `res://probe/board_shot_probe.tscn`;`tools/render_gate.sh` | 视图 1036×548、侧栏 200、裁剪全幅、顶面 rect 微光圈、**封印取证保持逻辑格 rect(圆心格心)**、三关 golden 重制后 0 差异 | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) | -| 16. 测试入口/能力审计(判据:`design/engineering/test-conventions.md:196`) | `run_all.gd:225`、新增测试件、`game/tests/README.md` | `bash tools/run_all_gates.sh --code`;`capability_audit.py` | 集成 | 单元测试全套件 | 三新套件在册、terrain 套件移除、能力审计红项 0、全绿 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | -| 17. 产出物/独立审计(判据:`design/engineering/test-conventions.md:147`) | `reports/` | 末卡产出物落位;`reports/iter-验收审计-<日期>.md` | 集成 | 实现报告/反哺点清单/审计报告 | 三件齐、逐行勾选、审计未过不合并 | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) | +| 1. D 区侧栏+提示条退役(判据:`design/ux/battle.md「Layout Zones」side_rail_w`、`design/gdd/systems/表现与支撑/HUD框架.md「战斗屏三区双舞台:挖掘与结算同屏不切场景」D 区全高归棋盘`) | `battle_layout_table.gd`、`battle_layout.tres`、`ap_bar_view.gd`、`board_zone_view.gd:23-37,74-79,91-92` | `board_side_rail_test.gd:_test_side_rail_layout`+`_test_signals`;`stage_background_test.gd:_test_side_rail_width_from_table`;`layout_probe.gd:_ready` | 单元+探针 | `BoardZoneView.new(layout)`→`ap_bar`/`_board_area`(测试读私有) | 左/右栏各宽 200、board_area 高 548、`side_rail_w==200`、hint 节点不存在、toast 不压棋盘 | 新增:D 区行动资源侧栏(AP 左栏、RAP 右栏、全高棋盘) | +| 2. 格边/原点/顶预留/重建接线(判据:`design/ux/battle.md「Layout Zones」棋盘格尺寸公式`) | `board_view.gd:205-232,403-404,428-439`、`main.gd:470`、`main_debug_flow.gd:104` | `board_terrain_test.gd:_test_cell_formula_base`+`_test_hit_test_logical_rect`;`layout_probe.gd:_ready`;`ui_input_probe.gd` | 单元+探针 | `BoardView.set_cell_area(Vector2(1036,548), 200)`/`rebuild(..., 200)` | `_cell_for(12, Vector2(1036,548), 200)==38`、`_cell_for(14, Vector2(1036,548), 200)==32`、局部原点 (279,44)/(281,44)、屏幕 (523,296)、全格命中 | 新增:棋盘点击命中与格边公式(逻辑格矩形) | +| 3. 合并岩体+连续地面(判据:`design/art/art-bible.md「3.2 环境几何」棋盘地形体系|材质与装饰`) | `board_terrain_layer.gd`(新增)、`board_view.gd`、删 `cell_base_layer.gd` | `board_terrain_test.gd:_test_merged_mass_geometry`+`_test_material_assets_present`+`_test_material_vs_structure`;`standee_present_values_test.gd:_init`(V11 源码锚改指 `board_terrain_layer.gd`);三关 `board_shot_probe` 截图 | 单元+探针 | `BoardView.rebuild()`→`_world/TerrainBack`、`_world/TerrainFront` 的 `mass_rects()`/`tex_paths_for()` | 四邻合并、相邻墙顶搭接 2、无墙顶内框、地面无缝、板边外延 ESHIFT;6 张 512×512 贴图在库且被消费、相邻格 UV 连续;V11 口沿高光新锚在位且全套件绿 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | +| 4. 投影/崖面/受光(判据:`design/art/art-bible.md「3.2 环境几何」棋盘地形体系|受光与崖面`) | `board_terrain_layer.gd` | `board_terrain_test.gd:_test_projection_ratios`;三关 golden | 单元+探针 | 同上 | 38 格 LIFT=17、ESHIFT=4、南崖 17×42、南崖顶缘 1px 受光口沿+1px 深墨线、东崖 4×55、北/西 1+1+外2、南/东内阴影 3×1、崖面无贯通岩层线、南向投影 4×4 α0.25/0.16/0.09/0.04、东向 α0.22/0.14/0.07/0.04 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | +| 5. 脚底排序遮挡(判据:`design/art/art-bible.md「3.2 环境几何」棋盘地形体系|绘制序与遮挡`) | `board_terrain_layer.gd`、`board_world.gd:39,48` | `board_terrain_test.gd:_test_depth_order`;三关截图 | 单元+探针 | 构造 hero 行与南邻墙;`terrain_metrics()["order"]`/`CellUnit.z_index` | back 含脚底≤hero 的岩体、front 含 >hero 的岩体;北侧格件 z=0、南侧格件 z=3、**封印格(含南侧)z=0**、`ContactGlow`/`MemoryGround` 全局 -1;南岩体覆盖小人脚底像素 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | +| 6. 浮空字+阴影圆几何/对比(判据:`design/art/art-bible.md「3.2 环境几何」棋盘地形体系|浮空数字`、`design/ux/battle.md「D 区布局与棋盘画法预览」浮空字`) | `board_float_layer.gd`(新增)、`board_label_shadow_layer.gd`(新增) | `board_float_label_test.gd:_test_label_geometry`+`_test_shadow_circle`+`_test_contrast`;`ui_contrast_probe.gd` 浮空字段 | 单元+探针 | `BoardView.refresh()`→`FloatLayer.set_entries()`/`_world/LabelShadow.setup()` | 字高 21(墨高)、间距 15、视觉顶 38、线 2(格顶−12..+4,接圆上缘)、1px 投影;**绘制基线 = 矩形底边、行 y 按步距(格边+2)**;圆 10×6、圆心格顶+7、z=0 低于 hero;**封印格无 entries/无圆**;四类底复合对比 ≥4.5 | 新增:棋盘浮空数字与引导线(最顶层、顶部预留) | +| 7. 浮空层最顶/顶行不裁切(判据:`design/ux/battle.md「D 区布局与棋盘画法预览」禁裁切`) | `board_view.gd` 层装配、`board_float_layer.gd` | `board_float_label_test.gd:_test_topmost_layer`+`_test_desaturation`;三关截图 | 单元+探针 | `BoardView` 固定名字子件 z 序与 entries/`set_desaturated()` | `FloatLayer` 为 BoardView 子 Control、z 最高;`TerrainBack`/`TerrainFront`/`LabelShadow` 固定名字在树;顶行 rect top=6 local;无元素遮数字/线;结算期浮空层与地形层同拍灰化 | 新增:棋盘浮空数字与引导线(最顶层、顶部预留) | +| 8. 顶面锚点/封印/交互(判据:`design/art/art-bible.md「3.2 环境几何」封印印记`、`design/ux/battle.md「封印格呈现预览」色牌`) | `board_view.gd`、`cell_mark_overlay.gd`、`seal_mark_layer`、`cell_type_glow_layer`、`board_cell_unit.gd` | `board_terrain_test.gd:_test_top_face_anchor`+`_test_seal_substrate`;`seal_mark_params_test.gd`;`type_glow_test.gd` | 单元+探针 | `BoardView.refresh()`→`CellUnit.visual_rect`/`CellUnit.z_index`/封印格 `plate` | **封印圆心=逻辑格心(不偏移)**、变异/微光/墙格悬停按 -ESHIFT/-LIFT;地面路径按逻辑 rect;环径 82%±1;封印格 `plate=true`、`glyph` 为危/数字、无浮空/无圆、色牌叠法阵上;封印格 z=0 低于小人,其余格件北 0/南 3 | 新增:棋盘顶面锚点与迷雾几何(微光、变异岩顶偏移,封印格心) | +| 9. 迷雾几何/记忆态(判据:`design/art/art-bible.md「6.5 视野迷雾与黑暗区域渲染」记忆态`) | `board_cell_unit.gd:_draw_fog_layer`/`MemoryGround`、`board_view.gd` | `board_terrain_test.gd:_test_fog_rect`+`_test_memory_cover`;`ui_contrast_probe.gd` 迷雾段;`type_glow_test.gd` | 单元+探针 | `BoardView.refresh()`→`CellUnit.fog_state`/`MemoryGround` | 墙格三块黑罩(顶面+南+东)覆盖、北/西邻格非岩顶地面像素零覆盖(岩顶投影可越入邻格屏幕区);地面格不越格;记忆态/退色不覆盖南邻岩顶(`MemoryGround` 只绘地面可见区,重叠区像素来自南邻墙体);封印格记忆态随格隐没;封印格地面=palette.light_edge;记忆态无浮空 entries;记忆墨对比 ≥4.5 | 新增:棋盘顶面锚点与迷雾几何(微光、变异岩顶偏移,封印格心) | +| 10. 命中逻辑格(判据:`design/ux/battle.md「Layout Zones」格边按公式现算`) | `board_view.gd:428-439` | `board_terrain_test.gd:_test_hit_test_logical_rect` | 单元 | `BoardView.cell_center_local()`/`_cell_at()` | 全格 `_cell_at(cell_center_local(c))==c`;顶面左上角点按逻辑归北/西邻格;板外 (-9,-9) | 新增:棋盘点击命中与格边公式(逻辑格矩形) | +| 11. 旧资产退役/普通数字零底牌(判据:`design/art/art-bible.md「3.2 环境几何」棋盘地形体系|旧资产处理`) | `game/assets/art/board/`、`tile_palette.gd`、`cell_base_layer.gd`、`terrain_tile_sets_test.gd` | `board_terrain_test.gd:_test_legacy_assets_absent`;`board_float_label_test.gd:_test_no_ordinary_plate_path`;`repo_structure_audit.py` | 单元+静态 | 扫描 `game/assets/art/board/` 与源码 | 零 `terrain_*`、零 `TilePalette`/`CellBaseLayer`/`u.base`、`seal_mark.png` 与 6 张 `board_rock_*`/`board_ground_*` 在库、普通数字零 `plate_digit`/`_digit_ink_mode`(封印格 `plate`/`DIGIT_PLATE` 为唯一例外) | 新增:旧瓦片退役与普通数字零底牌 | +| 12. 侧栏信号/setter(判据:`design/ux/battle.md「Component Inventory」行动资源侧栏`) | `ap_bar_view.gd` | `board_side_rail_test.gd:_test_signals` | 单元 | 真实按钮 `pressed`/setter | `stop_pressed`/`refresh_confirmed`/`legend_toggled` 逐信号;`set_ap`/`set_rap`/`set_refresh_state` 读数 | 新增:D 区行动资源侧栏(AP 左栏、RAP 右栏、全高棋盘) | +| 13. 接触带延续(判据:`design/art/art-bible.md「3.2 环境几何」可挖域接触带微光`) | `board_cell_unit.gd`、`board_view.gd:740,764-765` | `board_terrain_test.gd:_test_contact_glow`;`type_glow_test.gd` | 单元 | `BoardView.refresh()`→`ContactGlow.set_bands(..., ground_visible_rect)` | 英雄格地面侧接触带在位,正交整边/斜向角点+两半边,只绘地面可见区、不进岩体;全局 z=-1 | 既有:未开格类型微光(8 邻作用集、五组色相、零玩法写入) | +| 14. 三关色板/互辨(判据:`design/art/art-bible.md「4.1 主色板」三关棋盘环境八色`) | `board_terrain_palette.gd` | `board_terrain_test.gd:_test_palette_three_boards`+`_test_material_assets_present` | 单元+静态 | `palette_for("dungeon"/"underdark"/"deep_underdark")`/`tex_paths_for(...)` | 三关八色与 art-bible v3.53 §4.1 逐值一致;三关同名槽位不全等(用户过审样张冻结);不变槽恒定;封印石读 `light_edge`;6 张 512×512 贴图路径在库、单张像素域 ≤32(实测岩顶 9 色、地面 6 色) | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | +| 15. 取证面换代(判据:`game/tests/golden/README.md「基线冻结与审核」才允许出候选图`) | `board_shot_probe.gd`、`board_material_shot_probe`(新增/扩展)、`type_glow_shot_probe.gd`、`layout_probe.gd`、`ui_input_probe.gd`、`ui_contrast_probe.gd` | 三关 `board_shot_probe`+渲染闸;`board_material_shot_probe` 对过审预览图;`type_glow_shot_probe`;`layout_probe.gd:_ready`;`ui_input_probe.gd`;`ui_contrast_probe.gd` | 探针+渲染闸 | `res://probe/board_shot_probe.tscn`;`tools/render_gate.sh`;`game/tests/golden/board_material_L1.png`(过审预览锚) | 视图 1036×548、侧栏 200、裁剪全幅、顶面 rect 微光圈、**封印取证保持逻辑格 rect(圆心格心)**、三关 golden 重制后 0 差异;12×8/46px 材质探针与 512×512 新材质、断续岩块、薄边缘预览对齐,差异在容差内 | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) | +| 16. 测试入口/能力审计(判据:`design/engineering/test-conventions.md「8.9 三层模型」能力清单`) | `run_all.gd:225`、新增测试件、`game/tests/README.md` | `bash tools/run_all_gates.sh --code`;`capability_audit.py` | 集成 | 单元测试全套件 | 三新套件在册、terrain 套件移除、能力审计红项 0、全绿 | 新增:棋盘合并岩体与连续地面(深度遮挡、投影、崖面) | +| 17. 产出物/独立审计(判据:`design/engineering/test-conventions.md「8.6 测试时机」不要求先红后绿`) | `reports/` | 末卡产出物落位;`reports/iter-验收审计-<日期>.md` | 集成 | 实现报告/反哺点清单/审计报告 | 三件齐、逐行勾选、审计未过不合并 | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) | **测试削弱申报**(允许删除/替换的旧断言): @@ -384,7 +398,7 @@ - **L2 记录继续**:三关色板派生读数偏差在 ±1 通道内、draw calls 波动 <10%——记入实现报告继续。 - **L3 停机呈报**: - 新路径与 art-bible 条款冲突(比例/顶预留/圆心/层序/三关色板/封印承载任一不符)——停卡,列反哺点,禁自行改条款。 - - 封印呈现与迭代56「受理即揭示」或 art-bible v3.51 封印条冲突(印记落未开格、圆心随岩顶偏移、身份字形进浮空层、色牌层序颠倒、封印石对比 <4.5)——停卡呈报,禁把封印改回旧假设。 + - 封印呈现与迭代56「受理即揭示」或 art-bible v3.53 封印条冲突(印记落未开格、圆心随岩顶偏移、身份字形进浮空层、色牌层序颠倒、封印石对比 <4.5)——停卡呈报,禁把封印改回旧假设。 - `board_terrain_layer` 超 7 公开方法/12 成员且按职责拆不出内聚单元——停卡走豁免/还债通道,禁凑数拆绿。 - 机检键与卡片契约互斥(如测试要求保留 `plate` 字段)——停卡呈报,禁为机检保留无效成员。 - 三关色板逐值/互辨不过——停卡呈报,禁调色绕过或改判据。 @@ -399,8 +413,8 @@ 允许实现期自行拍板(超清单记入实现报告「实现决定记录」): 1. `board_terrain_layer` 内 back/front 两实例的精确 z 值(只要满足 back