From 6208a9cd1ac3bcaba19d78861541663ddd843c7c Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Sun, 1 Nov 2026 23:44:29 +0800 Subject: [PATCH] =?UTF-8?q?iter47-=E5=8D=A13=EF=BC=9A=E5=8D=A1=E2=91=A4(?= =?UTF-8?q?=E8=BF=AD=E4=BB=A347=C2=B7Esc=E6=B5=AE=E7=AA=97=E4=B8=8E?= =?UTF-8?q?=E8=90=A5=E5=9C=B0=E9=A1=B6=E6=A0=8F=E6=89=B9):=20Esc=E6=B5=AE?= =?UTF-8?q?=E7=AA=97=E5=9B=9B=E6=80=81=E8=B7=AF=E7=94=B1+CampHudBand?= =?UTF-8?q?=E9=A1=B6=E6=A0=8F=E6=A0=8F+=E8=AE=BE=E7=BD=AE=E8=AF=AD?= =?UTF-8?q?=E5=A2=83=E5=88=86=E6=94=AF+=E6=96=AD=E8=A8=80=E6=89=B9+?= =?UTF-8?q?=E5=AE=A1=E8=AE=A1=E8=A1=A5=E5=B7=AE+master=E5=8F=96=E7=94=A8+c?= =?UTF-8?q?amp.md=20v2.3=E5=AE=9A=E7=A8=BF=E5=90=B8=E6=94=B6(=E5=8D=8A?= =?UTF-8?q?=E9=80=8F=E6=98=8E=E9=81=AE=E7=BD=A90.6=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E6=A0=B9=E7=95=99=E5=BA=95/Esc=E5=85=88=E5=85=B3=E7=AA=97Q1?= =?UTF-8?q?=E7=94=B2=E6=8D=A2=E4=BB=A3)=E2=80=94=E2=80=94=E7=BB=88?= =?UTF-8?q?=E6=80=81=E5=85=AD=E6=9E=9A=E8=90=BD=E6=BB=A1?= 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 | 35 +-- design/art/art-pipeline-tools.md | 2 +- design/art/art-prompts.md | 73 +++--- design/art/art-status-checklist.md | 4 +- design/art/character-design.md | 4 +- design/gdd/08-Alpha版本标准.md | 4 +- design/gdd/ux/battle.md | 2 +- design/gdd/ux/camp.md | 4 +- design/gdd/ux/level-map.md | 2 +- game/presentation/camp_shop_presenter.gd | 1 + game/presentation/main.gd | 19 ++ game/presentation/main_esc_flow.gd | 56 ++++ game/presentation/main_esc_flow.gd.uid | 1 + game/presentation/main_overlay_flow.gd | 6 +- game/presentation/main_ui_build.gd | 16 +- game/presentation/ui_camp_modals.gd | 1 + game/presentation/ui_registry.gd | 2 + game/presentation/views/camp_esc_overlay.gd | 32 +++ .../views/camp_esc_overlay.gd.uid | 1 + game/presentation/views/camp_hud_band.gd | 27 ++ game/presentation/views/camp_hud_band.gd.uid | 1 + game/presentation/views/camp_scene_view.gd | 2 + game/presentation/views/camp_sub_view_base.gd | 8 +- game/presentation/views/career_overlay.gd | 1 + game/probe/screen_flow_probe.gd | 75 +++++- game/probe/ui_click_probe.gd | 10 +- game/probe/ui_struct_probe.gd | 55 ++++ game/tests/README.md | 6 +- reports/iter47-反哺点-2026-11-01.md | 19 ++ reports/iter47-实现报告-2026-11-01.md | 126 +++++++++ reports/iter47-验收审计-2026-11-01.md | 128 +++++++++ ...lling与godot-master-立绘显示档批-2026-11-01.md | 50 ++++ .../需求卡片-状态合并累加制批-2026-11-01.md | 151 +++++++++++ reports/需求卡片-立绘显示档批-2026-11-01.md | 244 ++++++++++++++++++ tools/shot_checker.py | 10 +- 待办清单.md | 36 +-- 37 files changed, 1117 insertions(+), 107 deletions(-) create mode 100644 game/presentation/main_esc_flow.gd create mode 100644 game/presentation/main_esc_flow.gd.uid create mode 100644 game/presentation/views/camp_esc_overlay.gd create mode 100644 game/presentation/views/camp_esc_overlay.gd.uid create mode 100644 game/presentation/views/camp_hud_band.gd create mode 100644 game/presentation/views/camp_hud_band.gd.uid create mode 100644 reports/iter47-反哺点-2026-11-01.md create mode 100644 reports/iter47-实现报告-2026-11-01.md create mode 100644 reports/iter47-验收审计-2026-11-01.md create mode 100644 reports/复核-双审-grilling与godot-master-立绘显示档批-2026-11-01.md create mode 100644 reports/需求卡片-状态合并累加制批-2026-11-01.md create mode 100644 reports/需求卡片-立绘显示档批-2026-11-01.md diff --git a/design/art/art-assets-checklist.md b/design/art/art-assets-checklist.md index 2b2eb14e..d87ef9a5 100644 --- a/design/art/art-assets-checklist.md +++ b/design/art/art-assets-checklist.md @@ -17,7 +17,7 @@ **通用规格纪律**: - 交付格式 PNG 透明底;动画用序列帧或精灵表(SpriteFrames),帧数规格随样张定(候选档已成文 art-bible §8.4)。命名规范候选草案见 art-bible §8.3。 -- **分辨率档位已定案:1280×800 + 1920×1080 两档**,窗口不可调、格边长按档位计算,后续调整走修订;像素画布基准见 **art-bible §8.2**(主角人设原图 48×72〔人设侧画布〕;站桩立绘/战斗状态图源高 48;棋盘小人 32×32 二头身;敌种逐键源档 36–94;整数倍缩放纪律;终值归样张冻结,待办清单已登记)。 +- **分辨率档位已定案:1280×800 + 1920×1080 两档**,窗口不可调、格边长按档位计算,后续调整走修订;像素画布基准见 **art-bible §8.2**(棋盘小人 32×32 二头身独立源档;站桩立绘=原稿分辨率入包、显示按三档绝对高 96/144/188 缩放,定值单点与逐件归档见 §8.2 站桩立绘显示档条)。 - 程序化占位是现行结构冻结条款:资产未就位的槽位保持占位渲染,不空窗。 - **复用闸(♻ 渠道四道验收,一道不过不入包)**:① 色板量化——改色对齐 art-bible §4.1 token,不保留原包杂色;② 吸色检查——无 HSV 色相 300°–345°(紫赤禁入带);③ 灰度/色弱可辨——去色相后仍可辨且不与语义件混淆;④ 授权干净——CC0 优先,CC-BY 署名记入设置/关于页,license 不明的一律不用。 @@ -59,14 +59,14 @@ ## 2. P1 —— 角色级(样张通过后开工,ComfyUI) -> 提示词规格卡 art-prompts.md 现行为 **v2.0**(主角三态+八敌种,逐资产自包含完整提示词,整段可直贴)。 +> 提示词规格卡 art-prompts.md 现行为 **v2.13**(主角三态+八敌种逐卡提示词仍在册;站桩立绘走 §5.4 按档派生、不重画)。 ### 2.1 主角战斗小人 - **要什么**:待机 / 攻击 / 受击 三态起步(移动态样张后定);透明底 PNG。 - **风格/规格**:小人原型——**窄、直立、对称,轮廓凹凸 ≤2**;2~3 头身两档下剪影均成立;主色小人蓝 `#2E86DE`(候选值,样张冻结终稿);格内占位最窄、不吞数字位。 - **来源**:✦ ComfyUI(prompt 卡 v2.0 §2);剪影原型是设计载荷(宽≥高/凹凸计数/甲档/紫赤独占),素材站无对的,不复用。 -- **现状**:站姿样张已有先例(源文件已清理);战斗三态未出。 +- **现状**:战斗三态在役(迭代 6 T3 落位);2026-11-01 显示档改中档 144,按档派生落位归立绘显示档实装批。 ### 2.2 八敌种形象(键集事实源 = `data/tables/enemy.tres` 行键) @@ -81,7 +81,7 @@ | 钩爪恐魔 hook_horror | 普通怪(钩爪/多足轮廓注意凹凸计数控制) | light | 第三关群行捕食者,小体量可辨 | | 灰矮人石君王 duergar_king | **Boss:锐角与不对称**,体量最大 | heavy | 第三关 Boss;紫赤色相独占+形状独占双通道 | -- **通用规格**:亮色描边+落影底盘轮廓通道硬规则;透明底 PNG;每敌种 2–3 版候选;护甲类型视觉区分方案已落 art-bible §5.3(已定稿)。 +- **通用规格**:亮色描边+落影底盘轮廓通道硬规则;透明底 PNG;显示档三档绝对高 96/144/188、源=原稿不降采样(art-bible §8.2 v3.32);护甲类型视觉区分方案已落 art-bible §5.3(已定稿)。 - **来源**:✦ ComfyUI(prompt 卡 v2.0 §3,八敌种+L2 熊地精变体共 9 卡);理由同 §2.1——不复用。 - **联动**:显示名以 `data/tables/enemy.tres` 与敌人系统文档为准(L2 熊地精=bugbear 复用,显示名熊地精系)。 @@ -162,7 +162,7 @@ | 站桩石板地台件 `scene_stage_plaza.png` | 近景地台独立件(art-bible §6.1/§8.2) | 源 48×12、九宫格横向拉伸、顶缘受光线 2px 不随拉伸变形;跨三关恒定,不吃 `wall_ambient` tint;连续地面层在其下方,先保留 | ⚙/✦ 自产 | | 特殊技动画终稿 | 并入 §2.3 三档意图动画,不另起体系 | 攻/防两型旧口径由三档替代 | ✦/⚙ 自产(同 §2.3) | | 连锁坍塌显形演出 | 连锁展开触发时的连锁演出 | 与音频方向同批配对登记;「坍塌显形」=连锁展开的玩家可见名 | ♻ 粒子/碎块改色 + ⚙ 坍塌结构自产 | -| 封印特效 | 该动作的呈现名 = **封印**(art-bible §3.2):**施印瞬间特效 + 印记常显形态**两件 | 印记旗面走封印黑 `#000000`(现行封印色,色史归 art-bible §4.1);特效走运动+色相(§2:状态/情绪不走明度,空间光照可走);现行占位 = 封印黑「旗」字形;印记常显形态可与 §3.3 旗面像素化合并出 | ✦/⚙ 自产(精灵+粒子,烟尘光点可 ♻ 改色) | +| 封印特效 | 该动作的呈现名 = **封印**(art-bible §3.2):**施印瞬间特效 + 印记常显形态**两件 | 印记旗面走封印黑 `#000000`(现行封印色,色史归 art-bible §4.1);特效走运动+色相(现行取法——明度分层不动);现行占位 = 封印黑「旗」字形;印记常显形态可与 §3.3 旗面像素化合并出 | ✦/⚙ 自产(精灵+粒子,烟尘光点可 ♻ 改色) | | 弹道/退场等动画密度 | 战斗表现输入清单,方案未定 | 样张锁动画方案后启动 | ♻ 通用弹道/光点/消散粒子改色为主 | **现状**:三关舞台背景层与连续地面层已交付(2026-10-31 入包 `game/assets/art/scene/`:dungeon v10c / underdark v10c / deep_underdark v10c,均 1280×252;共用地面 v12b,1280×100,按作者裁保留原亮度 L≈0.132);小石台件已在役。 diff --git a/design/art/art-bible.md b/design/art/art-bible.md index 557ea9e4..5631a41b 100644 --- a/design/art/art-bible.md +++ b/design/art/art-bible.md @@ -1,6 +1,10 @@ # 美术圣经(Art Bible)— Dungeon Sweeper -> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.31,历次修订明细见 git 提交史 +<<<<<<< HEAD +> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.33,历次修订明细见 git 提交史 +======= +> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.33,历次修订明细见 git 提交史 +>>>>>>> docs-mood-ban > > **Art Director Sign-Off(AD-ART-BIBLE)**:历次批均未签核——此为 Lean/Solo 模式(非 PHASE-GATE)下的现行治理状态;full 门禁签核时机待用户表态。 > 风格基调:地牢题材但**非暗黑风**——轻快明亮的幻想冒险风,全年龄;像素风;角色 2~3 头身。 @@ -30,7 +34,7 @@ **原则二|明亮为皮,明度分档为骨**(取自 Moonlighter、Peglin;锚定 P1 可读性前提、P4 探险氛围) -取 Moonlighter 的暖质地砖与亲和冒险者气质、Peglin 的明快全年龄洞穴色彩:全局暖倾向、无压抑。可读性由**格底明度分档**承载——已开格(数字所在格)明度走世界底层档(§2 明度分层;格态语义见《排雷玩法》;美术侧据此未开格走受光墙顶档、已开格走挖出空间沉暗档,与 §8.5 图底分离同轴),亮族数字墨直接画在格底上,直画对比 ≥4.5:1 恒成立。**数字色牌为后备手段**——仅复杂格底(物件纹样/变异纹带/微光叠加致格底对比不足)时垫牌后备(画法 §3.3、色值 §4.1)。格子本体美术放开:纹理、材质、装饰变体、类型纹样皆可入画;格底参数域见 §4.1 硬指标(分档明度域、饱和上限),仍避 Boss 禁入色相带。与参考之别:ITB 以半透明压暗板承载信息;本作格底功能分档(信息可读性服务,属 §2 明度分层允许域),情绪压暗仍禁。验收:机检〈1–8 全档数字对所在已开格底对比 ≥4.5:1〉 +取 Moonlighter 的暖质地砖与亲和冒险者气质、Peglin 的明快全年龄洞穴色彩:全局暖倾向、无压抑。可读性由**格底明度分档**承载——已开格(数字所在格)明度走世界底层档(§2 明度分层;格态语义见《排雷玩法》;美术侧据此未开格走受光墙顶档、已开格走挖出空间沉暗档,与 §8.5 图底分离同轴),亮族数字墨直接画在格底上,直画对比 ≥4.5:1 恒成立。**数字色牌为后备手段**——仅复杂格底(物件纹样/变异纹带/微光叠加致格底对比不足)时垫牌后备(画法 §3.3、色值 §4.1)。格子本体美术放开:纹理、材质、装饰变体、类型纹样皆可入画;格底参数域见 §4.1 硬指标(分档明度域、饱和上限),仍避 Boss 禁入色相带。与参考之别:ITB 以半透明压暗板承载信息;本作格底功能分档(信息可读性服务)。验收:机检〈1–8 全档数字对所在已开格底对比 ≥4.5:1〉 *设计测试:当格子美术与数字可读性冲突时,先调格底明度档,复杂格底垫色牌后备,不动格子画。* @@ -69,7 +73,7 @@ > 本节服从第 1 节宣言「明快的地牢,轻快的扫荡,仔细的推理」。能量值为全作统一 0–10 刻度:0 静谧,10 沸腾。 > -> **明度分层(硬规则)**:明度按视觉层分带——**信息面层**(数字/UI 数据/预告/语义标识)最高、**世界中层**(格底顶面/角色/物件)居中、**世界底层**(背景/纵深/远景/已开空间)可更低;层间明度差服务空间纵深与光照(Moonlighter 式洞穴层次)。**情绪明暗禁令**:明度变化禁止用于**情绪表达**——画面禁止靠压暗/渐晕阴沉下来;roguelike 失败重开,世界无光暗记忆;Darkest Dungeon 式压暗仍在 §9.2 反面清单。**状态表达不受本禁令约束**:状态可用明度、色相、饱和、运动、元素任一手段承载。**允许域**:空间纵深、光照氛围、形体塑造。类型微光的明度梯度(§4.2)属信息面层内梯度,不扰世界层明度档。验收:目检〈情绪表达不走压暗/渐晕;三档明度带层间灰度可分〉 +> **明度分层(硬规则)**:明度按视觉层分带——**信息面层**(数字/UI 数据/预告/语义标识)最高、**世界中层**(格底顶面/角色/物件)居中、**世界底层**(背景/纵深/远景/已开空间)可更低;层间明度差服务空间纵深与光照(Moonlighter 式洞穴层次)。类型微光的明度梯度(§4.2)属信息面层内梯度,不扰世界层明度档。验收:目检〈三档明度带层间灰度可分〉 > > **世界底层两子带**:世界底层拆两条子带——**底层下沿带 L 0.014–0.06**(远景、洞窟纵深、B 区舞台底、屏幕根底)与**底层上沿带 L 0.08–0.14**(已开格底、迷雾记忆态合成底),子带间隔 ≥0.02。拆两子带用于解决**世界底层内部** B 区舞台底(L=0.036)与 D 区已开格底(L≈0.10)同层难辨的问题——两者同属世界底层,单带下跨度 0.126 吃掉层间间隔 0.08,灰度图上会表现为两个不同的底。§1.4 整屏②项约束的是层间可分(底层上沿 0.14 对世界中层下沿 0.22,差 0.08 本就满足),②项不约束同层内可分,故本条不属②项的成立要件,而是世界底层内部的可读性纪律。验收:机检〈同一屏的世界底层成员全部落进两条子带之一,两子带 L 区间不重叠且间隔 ≥0.02〉 @@ -84,15 +88,15 @@ ### 2.2 轮末自动战斗结算 - **主情绪**:延迟兑现的清算爽感——扫雷之因逐行兑现为战果;完美封印(概念定义与兑付结构见《地图战斗资源》)的高光兑现——结算带高光行,以其为全场喝彩级的最高反馈档 -- **色彩性格**:情绪不走明度(§2 禁令),色彩转向金橙主导、饱和拉高;数字色转译为弹道色沿行推进 +- **色彩性格**:情绪由色相与饱和承载——金橙主导、饱和拉高,明度分层不动;数字色转译为弹道色沿行推进 - **氛围形容词**:酣畅、递进、一气呵成 - **能量**:7/10,随连击爬升 -- **承载元素**:兑现光带逐行横扫棋盘,开格化箭雨、印记化暴击砸向敌人,因果全程可见可归因。验收:目检〈兑现光带逐行横扫、因果可见可归因;情绪表达不走压暗〉 +- **承载元素**:兑现光带逐行横扫棋盘,开格化箭雨、印记化暴击砸向敌人,因果全程可见可归因。验收:目检〈兑现光带逐行横扫、因果可见可归因〉 ### 2.3 清图奖励与换图 - **主情绪**:短促丰收——宝箱揭盖式的喜悦,三五秒即收,不拖节奏 -- **色彩性格**:全屏饱和峰值:金粒喷泉与彩纸迸发,饱和瞬时拉满后回落;明度不动(§2 情绪禁令) +- **色彩性格**:全屏饱和峰值:金粒喷泉与彩纸迸发,饱和瞬时拉满后回落;明度分层不动 - **氛围形容词**:丰收、轻快、干脆 - **能量**:8/10,尖峰后速降 - **承载元素**:最后一格碎砖中喷出的 GP 喷泉,叮当落入 UI 钱袋。验收:目检〈金粒喷泉短促收敛,饱和峰值后回落〉 @@ -108,7 +112,7 @@ ### 2.5 战斗失败(冒险终结) - **主情绪**:温柔的惋惜与「再来一次」的邀请——有分量、不惩罚,像合上一册冒险日志 -- **色彩性格**:情绪不走明度(§2 禁令),色相转暖灰掺暮蓝;全作禁血红与黑场,唯此一拍最静 +- **色彩性格**:情绪由色相承载——色相转暖灰掺暮蓝,明度分层不动;全作禁血红与黑场,唯此一拍最静 - **氛围形容词**:惋惜、安静、余温、可再来 - **能量**:1/10 - **承载元素**:小人坐在碎砖上摇头掸灰,落下的封印印记逐枚化作光点收回行囊。验收:目检〈无血红与黑场;色相转暖灰掺暮蓝〉 @@ -159,7 +163,7 @@ ### 3.2 环境几何 -- **雷图棋盘呈现基准**:战棋地块质感 × 正俯视角——取 ITB 参考图(`references/itb_1.jpg`)的地表质感骨架:地块纹理多样、起伏体块感、岛缘/砖缘厚度、格上装饰小立牌;但相机一律正上方垂直向下,格线屏轴对齐,**禁等距/斜视角与菱形格**;形状语言仍守总纲圆角方形。砖缘厚度与岛缘立体面属形体塑造,不属状态/情绪表达,不受 §2 情绪明暗禁令约束(属 §2 明度分层允许域;顶面格底仍守 §4.1 参数域)。装饰小立牌属 ITB 参考的观感元素,本作不采用;装饰变体走氛围层纪律(纹理级/物件级形状家族,见下方装饰变体条),零信息纪律以原则三为准。验收:目检〈棋盘正俯视、格线屏轴对齐、无菱形格〉 ←原二;原三;§2 +- **雷图棋盘呈现基准**:战棋地块质感 × 正俯视角——取 ITB 参考图(`references/itb_1.jpg`)的地表质感骨架:地块纹理多样、起伏体块感、岛缘/砖缘厚度、格上装饰小立牌;但相机一律正上方垂直向下,格线屏轴对齐,**禁等距/斜视角与菱形格**;形状语言仍守总纲圆角方形。砖缘厚度与岛缘立体面属形体塑造(顶面格底仍守 §4.1 参数域)。装饰小立牌属 ITB 参考的观感元素,本作不采用;装饰变体走氛围层纪律(纹理级/物件级形状家族,见下方装饰变体条),零信息纪律以原则三为准。验收:目检〈棋盘正俯视、格线屏轴对齐、无菱形格〉 ←原二;原三;§2 - **地砖**:一切环境体由同一圆角方形衍生:未开 = 完整凸砖,已开 = 同形缺角碎裂,雷 = 碎裂加巢穴纹(危险格玩家说法见《排雷玩法》);只以"完整度"叙事,不为状态新造形。验收:目检〈三格态仅以完整度区分,无新造状态形〉 ←原三;P4 - **装饰变体(未开格氛围层)**:覆尘完整砖之上叠加裂纹/碎石斑/物件级点缀等装饰。物件级装饰(小石块/陶片/骨殖等)须走**专属装饰形状家族**(与信息元素形状语言隔离、灰度下不与任何逻辑元素同形),数量配额按图类型定(候选 3–5 种,样张已冻结,§1.4),一律残缺、内凹、低对比而自然后退(§3.4);零信息纪律(分布随机、与雷/安/类型零相关、灰度下禁止制造新分类特征、分布每板一次跨轮不复掷)以原则三为准,此处不赘。验收:目检〈物件级装饰不与任何逻辑元素同形;装饰残缺低对比后退〉 ←原三 - **结果整格表达(已开格)**:已开格按当格结果整格表达(结果清单见原则三);画法——产资源格的家族物件纹样用 §3.1 道具点剪影语言(直线几何体)角嵌于砖缘,砖心与数字字形占位区留白(已开格仍承载数字);危险格巢穴纹较已开格更凶一档,形状+颜色双通道。验收:目检〈产资源格嵌家族纹样且砖心留白;巢穴纹更凶一档〉 ←原三;P3 @@ -377,7 +381,7 @@ - **双舞台常驻下的 B 区环境**:战斗画面区(站桩立绘所在)的背景 = 明亮地窟,与 §1 风格基调同源——暖倾向、无压抑;背景整体**低对比自然后退**(§3.4 焦点预算延伸):背景禁止构成完整凸形、禁止抢 B 区立绘与 D 区数字的焦点,识别层级恒为 立绘 > 背景。验收:目检〈背景无完整凸形、立绘最抢眼〉 - **舞台正面目标**:B 区 = **地窟看台**——立绘脚下地台/落影承载(世界中层),背景环境层低饱和后退、明度走世界底层档;角色禁止直接贴平色底。规格与终值归整屏样张闸(§1.4)冻结。**地台面上零文字**——暖白 `#F0E2C8` 对地台板身 `#968264` 实测仅 2.89:1,已越 §7.2 的 4.5:1 硬指标,落法按 §7.2「文字禁直接压纹理底」(垫容器、素牌或罩层),非新条款;站桩文字位改垫素底或落进结算明细带(实装=站桩名字行垫 `HP_BAR_BACK` 深档素底牌、文字基线上移至地台顶上方——2026-10-30 落地)。验收:目检〈立绘脚下有地台/落影,非贴平色底〉+机检〈B 区站桩文字位正下方像素非地台板身色 #968264〉 -- **明度分层适用**:背景氛围的情绪表达仍禁止以压暗/渐晕实现(§2 禁令);空间纵深与洞穴感走明度分层允许域——世界底层档、光照氛围、色相饱和与形体承载(§3.2 同款逻辑)。验收:方向性 +- **明度分层适用**:空间纵深与洞穴感走明度分层——世界底层档、光照氛围、色相饱和与形体承载(§3.2 同款逻辑)。验收:方向性 - **图类型联动**:背景层按 `board_type` 选三张变体(`scene_stage_bg_dungeon.png` / `scene_stage_bg_underdark.png` / `scene_stage_bg_deep_underdark.png`,方向取 §6.3 三关色板候选);**背景不再走 §4.3 `wall_ambient` tint**(该槽保留给棋盘/世界的墙雾氛围,避免对三张背景二次染色)。紫赤仅 Boss 战允许短暂进入背景氛围纹样(§2.6 色相独占的舞台侧延伸,高饱和独占不变),非 Boss 战高饱和紫赤禁入。验收:机检〈背景吸色无非 Boss 高饱和紫赤;背景素材不引用 `wall_ambient` 槽〉 - **场景构成(2026-10-31 用户裁)**:B 区舞台从远到近分三段——**顶部空区**:洞顶以上的昏暗空间,只留深色空区,**不画钟乳石、吊锥、悬挂物或任何可辨形状**;**远景(纵深洞厅)**:不是贴墙的后壁,按远/中/近三层组织——远层暗剪影(远处洞口/通道、层叠岩体、洞底轮廓)、中层主要细节层(岩台、岩柱、凹壁、裂缝)、近层左右暗色岩框;剪影被中层部分遮挡、不贴顶、不孤立,**禁贴墙感、禁单件圆柱贴顶、禁砖石墙/规则砌缝/方整石块**;三关母题(地精=支洞/木栈道/木桩围栏;卓尔=巨柱/石笋/蛛网/螺旋塔剪影/巨菇/石桥;灰矮人=石笋城郭/棱角石厅/石桥/矿道口/烟囱塔)见 `battle-stage-prompts.md` §3.2;**分隔带**:远壁根部与近景地面之间一条不规则碎石带/阴影缝,边界清楚但不笔直,**禁瓷砖缝、踢脚线、规则台阶**;**近景地面**:干净压实泥土为主,全幅只零星几颗小石、散点分布,中央平缓留空给角色站位,**禁成排/成堆碎石、满铺砂砾、泥点噪声、瓷砖、规则铺装、草、木地板**。纵深与三段构图归 §1.4 样张;逐条要素、分层提示词与否定后缀 = `battle-stage-prompts.md`(本文件不重复维护)。验收:目检〈顶部无钟乳石/吊锥;远景有纵深、非贴墙;无孤立圆柱贴顶;近景为泥土碎石;分隔带不规则;中央无大障碍〉 - **图层归属(2026-10-31 用户裁)**:背景层 = 三关变体 `scene_stage_bg_dungeon/_underdark/_deep_underdark.png`(顶部空区+纵深洞厅远景,不画近景地面;按 `board_type` 选一张);近景地面 = **独立连续地面层** `scene_stage_ground.png`(泥土/砂砾/碎石地面,全宽、底边贴 B 区底、顶缘即分隔带;高度读布局表 `ground_h`,字段由地面层实装批新增并回填,本批终稿高 100、代码批落表);现有每角色小石台 `scene_stage_plaza.png` 保留,叠在连续地面之上。连续地面层与小石台**三关共用**、跨关恒定、**不吃 `wall_ambient` tint**(世界中层承载面随关卡换明度会破 §2 层间关系);背景三张变体各自带关卡色族,不再叠 tint。验收:机检〈三张背景文件名带 board_type 后缀;地面层/小石台文件名无 board_type 后缀;背景与地面层均不引用 `wall_ambient` 槽〉 @@ -422,7 +426,6 @@ - **记忆态可读性判据**:数字对合成底**归一后(真实渲染面)三关 ≥4.5:1**(WCAG 硬指标;合成底 L1 #4C4038/L2 #3F4147/L3 #3E4048;行值与素材随动,测点=ui_contrast_probe 迷雾段)。**归一注**:装载亮度归一是现行生产路径(`board_view._normalize_floor_luma`),原图均值≠渲染面,复算须落归一后底。可辨性自查(三通道,随样张/实机自检):①对全黑未开格——合成底 #3E3731(L≈0.036)对 L0,实机目检常光档可分(暗房档一并抽检);②对灯光区内活态已开格——主判据=数字墨灰度差(记忆墨 L0.55 对亮墨三档 L≥0.75 / 色牌 #F5EAD3 L≈0.83,灰度 ΔL≥0.20)+ 色相通道(记忆态近中性灰,对活态暖底暖墨);③格态三形在记忆态保持灰度可辨——形通道经纹理+灰罩形态不变,沿 §1.4 验收 2 同源判据。验收:机检〈ui_contrast_probe 迷雾段记忆墨对比 ≥4.5:1〉←§1.4 - **迷雾过渡边:硬边(逐格二值)**:灯光区边界 = **整格二值切换**(区内全渲染 / 区外全黑或记忆态),**不做渐变过渡带、不做半透明晕边**。理由:①边界是信息边界不是氛围晕——渐变中间态 =「看得见但看不清」,破数字可读硬指标与记忆态明度档;②现行事实源验收断言(边界格呈态、两态逐位一致)须格级二值可判;③与砖面整格表达(§3.2 高墙瓦片体系)、ITB 格内信息分层气质同轴。无动画,减动效无涉。←现行事实源;§1.2 原则一;§3.2 - **与结算期去饱和的叠加共存**:结算期去饱和偏移(settlement_fx_view,同族先例)与迷雾调制叠加规则 = **记忆态为终态档**——区外已开格在结算期保持记忆态档、**不再叠加**结算去饱和(灰显已含去饱和语义,二次调制无信息增量且明度不可控);灯光区内格照常吃结算去饱和;全黑格两态无差。叠加态随实施批共存校验 + 探针断言(provisional,实机目检可代拍)。验收:机检〈叠加态下记忆态灰显不被二次调制〉 -- **§2 明度禁令自查**:迷雾遮蔽与记忆态灰显属 §2 明度分层**光照氛围允许域**(洞穴举灯的空间光照呈现,与 Moonlighter 取列「亮地板/暗深渊/发光体」光照层次同族),非情绪压暗(§9.2 Darkest 反面条款不触——那禁的是情绪表达)、非状态明暗编码(格态语义仍由形+色相承载,灰度下三态可辨不受扰)。←§2;§9.1;§9.2 --- @@ -516,19 +519,19 @@ - **全局纹理过滤与平滑渐变件例外**:`project.godot` `default_texture_filter=0`(Nearest)全局——像素风 UI 皮(九宫格/主题石纹样式盒/滑轨抓子/勾选/箭头图标)翻 Nearest=意图面;**显式 LINEAR 豁免清单(有意例外)= vignette / gradient_base / beams 三件程序化平滑渐变件**——保平滑连续 alpha 的程序化氛围件(§7.6 三已裁);新增平滑件须同批入册本清单,禁静默挂 LINEAR。翻转面枚举与冒烟断言(6 条)在闸。验收:机检〈过滤面枚举与 LINEAR 清单逐项一致〉 - **显示档登记例外(64 源 0.5×,待素材批消除)**:柜台四枚 `icon_forge/workshop/atlas/keystone`(64×64 源)显示档统一 **32px = 0.5×**;状态九枚(32×32 源)mini(站桩)档 **16px = 0.5×**。两处均系「显示尺寸侧唯一可调、素材一字节禁改」红线下的人工检整数半倍档,登记为**待消除例外**——素材设计出 32px 源后回归 1×。常规档显示一律 1×(状态九枚 32px、手绘十枚 20px/40px 双档、BCard 图标槽 40px=2×、**护甲类型图标三枚 24px=1×**——源 24×24,归甲类整数倍纪律)。验收:机检〈显示档与登记表一致〉 - **乙类·角色与单位精灵**(有机形体、非文字):允许运行时非整数倍缩放(NEAREST 过滤不变),容忍轻度像素宽窄不均;判据 = 实机目检,可感不适即回整数档。乙类免逐案豁免。验收:目检〈立绘无可感拉花〉 - - **站桩立绘槽位=高定宽随**:立绘/精灵槽位只定「高度的整数倍档」,宽度随源图宽高比自适应——**禁止把全部立绘塞进统一方框强拉**(纵横倍率必须恒等)。反面实例:统一方框把窄条生物源(细长本体裁掉透明边)按主角比例横拉压扁发花。乙类的非整数豁免只覆盖**等比**缩放,不含纵横异倍变形。验收:机检〈立绘纵横倍率恒等〉 + - **站桩立绘槽位=高定宽随**:立绘/精灵槽位只定「高度的绝对档(档高取整数像素值)」,宽度随源图宽高比自适应——**禁止把全部立绘塞进统一方框强拉**(纵横倍率必须恒等)。反面实例:统一方框把窄条生物源(细长本体裁掉透明边)按主角比例横拉压扁发花。乙类的非整数豁免只覆盖**等比**缩放,不含纵横异倍变形。验收:机检〈立绘纵横倍率恒等〉 - **1920×1080 档策略**:全局等比(stretch=canvas_items+aspect **keep**)——16:10 设计在 16:9 窗口=等比 1.35×+左右黑边各 ~96px,构图与 1280×800 基准档完全一致;甲类 1.35 非整数缩放例外注记:轻度宽窄不均系本档位接受代价(像素游戏 shipped 常态),实机目检可感不适→回乙案(1920 独立 2× 基准)重议;乙类同前款。验收:目检〈1920 档构图与 1280 档一致〉 - **画布基准(暂定值)**: - **主角人设原图 = 48×72**(1× 基准,暂定;与站姿降采样可读性验证一致); - **棋盘小人 = 32×32 二头身派生版(暂定,允许更小)**——独立资产,自人设定稿压缩派生(character-design §5.4),不吞数字位、占位 ≤ 0.75× 格边长;板越小占比摩擦越大(13×13 / 14×14 更小,算例见 [battle.md](../gdd/ux/battle.md)「棋盘格尺寸公式」),32px 源档的去留已定终值 = **保留 32×32 源档**(沿「独立小源档」路线;N=12 板下显示占位上限 27px = 0.84 倍,正落本节乙类非整数缩放许可范围,**连豁免都不用再办**),待决标注注销; - - **站桩立绘源档 = 八敌逐键定档**:主角 48 不变;八敌源档高 = goblin 36 / giant_spider 38 / duergar 46 / hook_horror 58 / bugbear 62 / ogre_chief 74 / drider 90 / duergar_king 94,显示一律 **×2 整数档(NEAREST)** = 72–188。定档依据 = 生物体型三约束(钩爪恐魔>灰矮人、灰矮人<熊地精、食人魔>熊地精——体量=物种体型,非强度线性映射,见 character-design §5.2);可读性实测门槛 = 源高 ≥32(24 糊/32 可读/48 清楚/64 细节完整),全阶梯 36–94 达标;派生管线 = pixel-1.png 紧裁 → 等比缩至档高 → dom_block_resize 块内众数降采样(tools/pixelize_candidates.py `STANDEE_TIER_H`,`SIZES` 降格为管线上游中间分辨率表);体量存在感经整屏对比校验(B 区高读 `stage_h`/立绘显示上限 188)。验收:机检〈standee_asset_check 逐键档高校验〉 - - **站桩立绘排版**:① 区高 B 区 ≈1/3 屏 / C 区 ≈2/3 屏,**扫雷盘原尺寸不缩、格子不变**(区高事实源 = 布局表 `battle_layout.tres`;压缩由 C 区面板空档吸收);② 站桩内部重排——立绘双脚落石台上缘(弃盒内居中)、**血条+状态/名字行落底排**(立绘→血条→状态 顺序,全场血条对齐一线;血条嵌石板位、台缘线留作地面线、落影保留接地感),状态空时该行退化为名字行;③ 大体档(显示 >150px 级:drider/duergar_king)**允许向上溢出盒顶 N px**(N 由实装批按实测尺寸算定,**与背景/光柱无关**——现行溢出区恰为临时光柱氛围层〔§6.1 方向稿四柱,x 基准 110/900/1055/1210@1280,`battle_stage_view.gd:47-56`〕,正式舞台背景插画(三关变体)到位后该层直接退役(背景不画光柱),**溢出判定不随之变更**;横向禁止压到顶部中央轮次·阶段指示,溢出上限由实装批用真图复算 x 区间定),血条仍落底(落底排的第二个收益=头部探顶不带出血条);意图徽标悬浮头顶上方(探顶档压胸);④ 「血条悬浮头顶+立绘盒内居中」排式已弃——盒顶固定 y 与盒内居中在高盒下拉开血条-立绘空洞。验收:目检〈血条一线对齐、大体档溢出不压轮次指示〉 + - **站桩立绘显示档 = 三档绝对高**:小型 96 / 中型 144 / 大型 188。逐件归档——小:地精、巨蜘蛛、灰矮人;中:主角、钩爪恐魔、熊地精;大:食人魔酋长、蛛化卓尔、灰矮人石君王。**源 = 原稿像素网格**(八敌 `pixel-1`、主角手修 2× 三态稿),紧裁后原样入包,**禁再降采样**;显示倍率 = 档高 ÷ 源高,NEAREST,宽度随源图比例(高定宽随不变,见上条)。定档依据 = 生物体型(体量=物种体型,非强度线性映射,见 character-design §5.2),**顺序由显示档承载、不由源高承载**。已接受项:中型三件与地精/巨蜘蛛的源高(92/94/123/90/81)低于档高,属放大显示;食人魔酋长显示宽 157 超桩盒 150。验收:机检〈standee_asset_check 逐件显示档高与归档一致、纵横倍率恒等〉+目检〈同屏体量顺序成立〉 + - **站桩立绘排版**:① 区高 B 区 ≈1/3 屏 / C 区 ≈2/3 屏,**扫雷盘原尺寸不缩、格子不变**(区高事实源 = 布局表 `battle_layout.tres`;压缩由 C 区面板空档吸收);② 站桩内部重排——立绘双脚落石台上缘(弃盒内居中)、**血条+状态/名字行落底排**(立绘→血条→状态 顺序,全场血条对齐一线;血条嵌石板位、台缘线留作地面线、落影保留接地感),状态空时该行退化为名字行;③ 大体档(显示 >150px 级:食人魔酋长/蛛化卓尔/灰矮人石君王)**允许向上溢出盒顶 N px**(N 由实装批按实测尺寸算定,**与背景/光柱无关**——现行溢出区恰为临时光柱氛围层〔§6.1 方向稿四柱,x 基准 110/900/1055/1210@1280,`battle_stage_view.gd:47-56`〕,正式舞台背景插画(三关变体)到位后该层直接退役(背景不画光柱),**溢出判定不随之变更**;横向禁止压到顶部中央轮次·阶段指示,溢出上限由实装批用真图复算 x 区间定),血条仍落底(落底排的第二个收益=头部探顶不带出血条);意图徽标悬浮头顶上方(探顶档压胸);④ 「血条悬浮头顶+立绘盒内居中」排式已弃——盒顶固定 y 与盒内居中在高盒下拉开血条-立绘空洞。验收:目检〈血条一线对齐、大体档溢出不压轮次指示〉 - **站桩石板地台件**:`scene_stage_plaza.png`,源 48×12、九宫格横向拉伸、顶缘受光线 2px 不随拉伸变形;跨三关恒定、不吃 §4.3 `wall_ambient` tint(独立理由见 §6.1 近景地台独立件条)。验收:机检〈地台件按九宫格拉伸后顶缘受光线宽度恒为 2px〉 ### 8.3 导出格式与命名规范 - **归档纪律**:图片素材**不入 git 版本管理**——仓库只保留运行时引用资产(game/assets);生成链路原始产物(AI 原图/中间产物/候选版本)归档至 `archive/` 并择机上对象存储备份;主文档(圣经/GDD/清单)**禁引用 artwork/ 散文件路径**——定稿成图以 game/assets 为唯一事实源,过程稿引用一律用归档包路径或描述性出处。验收:机检〈主文档 grep 无 artwork/ 散文件路径〉 -- **入包与对账检查器(挂点已立,实现随 PRD 工具批)**:①**色板检查器**——扫描新素材色板,报新增色/近色告警/超 §4.1 上限(48)拦截,挂素材流入包步(asset-path-map §2 第 3 步);②**路径核对器**——扫描 asset-path-map 声明的全部路径,悬空/未清即报,随大批与审计例行跑;③**standee_asset_check 硬闸升级规格**——按 §8.2 逐键定档校验体量与档高、像素域色数 ≤32、无非整数倍缩放痕迹、描边亮度达标(亮描边明度档);把「高定宽随」教训变成代码闸而非文字。验收:机检〈三检查器在闸可跑〉 +- **入包与对账检查器(挂点已立,实现随 PRD 工具批)**:①**色板检查器**——扫描新素材色板,报新增色/近色告警/超 §4.1 上限(48)拦截,挂素材流入包步(asset-path-map §2 第 3 步);②**路径核对器**——扫描 asset-path-map 声明的全部路径,悬空/未清即报,随大批与审计例行跑;③**standee_asset_check 硬闸升级规格**——按 §8.2 显示档逐件校验显示档高与归档、纵横倍率恒等、像素域色数 ≤32、描边亮度达标(亮描边明度档);把「高定宽随」教训变成代码闸而非文字。验收:机检〈三检查器在闸可跑〉 - **交付格式**:PNG 透明底;动画 = 序列帧或引擎精灵表(SpriteFrames),帧尺寸恒定、横向等宽排列(候选)。验收:目检〈交付件透明底无杂边〉 - **命名规范(候选草案)**:`<域>_<对象键>_<状态|变体>[_<序号>].png`,全小写 snake_case;**对象键 = 数据表主键**(effect_id/reward_id/cell_type/enemy_id——图标键契约 §4.6 的文件侧延伸:资产文件名键 = 图标键,全局恒定禁运行时换图);图类型变体后缀 = board_type 键(`_dungeon`/`_underdark`/`_deep_underdark`);候选评审件与终稿分目录(`artwork/candidates/` 承载评审件)。验收:机检〈命名与目录检查器零红〉 @@ -557,7 +560,7 @@ | 参考 | 取 | 弃 | |---|---|---| | **Into the Breach** | 格内信息分层、攻击预告上格范式、战棋地块质感骨架(§1.2 原则一;§3.2) | 冷暗军事色调、压暗信息板、斜切 HUD(原则二;§3.3) | -| **Moonlighter** | 暖质地砖与砖缝质感、亲和冒险者气质、木石暖色道具(原则二/原则三);**光照层次与明度纵深**(亮地板/暗深渊/发光体三档,§2 明度分层) | 全拟物倾向(§3.3 半拟物边界);Darkest 式情绪压暗(§9.2) | +| **Moonlighter** | 暖质地砖与砖缝质感、亲和冒险者气质、木石暖色道具(原则二/原则三);**光照层次与明度纵深**(亮地板/暗深渊/发光体三档,§2 明度分层) | 全拟物倾向(§3.3 半拟物边界);Darkest 式压暗(§9.2 反面基准) | | **Peglin** | 明快全年龄洞穴色彩、胖体量亲和怪(§5.1 普通怪原型) | 色块依赖——先读轮廓后读颜色(§5.1) | - **反面条款已成文**(§9.2);反面参考**图证**待本作素材生成后增补。验收:方向性 @@ -566,7 +569,7 @@ | 反面参考 | 违反条款 | 立法理由 | |---|---|---| -| **Darkest Dungeon** 式压暗 | §2 情绪明暗禁令(明度分层下仍禁) | 状态与情绪只走色相/饱和/运动/元素四手段,不以变暗表达情绪(失败重开,世界无光暗记忆) | +| **Darkest Dungeon** 式压暗 | §9.2 反面基准(风格取向记录,非禁令——压暗属普通设计决策,逐案走样张与目检) | 失败重开,世界无光暗记忆——明亮基调下不以整屏变暗作常态表达 | | **传统扫雷白牌/贴纸式数字承载** | §1.2 原则二(明度分档为骨) | 数字由格底明度分档承载、直画入世界;色牌仅复杂格底后备——满屏白牌=电子表格观感,非游戏画面 | | **Enter the Gungeon** 式粒子与色相爆炸 | §3.4 焦点预算;§4.2 色相纪律 | 信息层禁止被特效与杂色吞没,特效入画先过焦点预算 | | **Hades** 式特效密度 | §2.2 兑现爽感的上限 | 爽感靠逐行因果归因,不靠满屏特效;承载元素以 §2.2 清单为界 | diff --git a/design/art/art-pipeline-tools.md b/design/art/art-pipeline-tools.md index 07459558..cc52a794 100644 --- a/design/art/art-pipeline-tools.md +++ b/design/art/art-pipeline-tools.md @@ -176,7 +176,7 @@ python tools/shot_checker.py <截图目录> python tools/shot_checker.py <截图目录> shot_menu.png shot_battle.png ``` -**判据或口径**:A 屏级骨架——PNG 存在、任一边 1280、灰度 std 不低于 8、唯一色数不低于 64。B 文字对比——战斗 C 区面板与明细带提示的 WCAG 不低于 4.5:1。C 明度三档——战斗屏信息面高于世界中,世界中高于世界底。D 文字禁压纹理——文字框背景中带灰度 std 不高于 18。F 文字在——菜单标题框内与中位灰度差大于 60 的像素占比落在 2% 到 55%。B/C/D 只在清单含 `shot_battle.png` 时跑,F 只在含 `shot_menu.png` 时跑,其余屏只跑 A。全过 0,缺参数或任一失败 1。 +**判据或口径**:A 屏级骨架——PNG 存在、任一边 1280、灰度 std 不低于 8(取值在圣经 §7.2 文字 4.5:1 推论下界之下、正常实测最低 19.3 之上)、唯一色数不低于 40(正常实测地板 60 的 2/3,低于一切正常屏;色数异常回落=画面异常信号)。B 文字对比——战斗 C 区面板与明细带提示的 WCAG 不低于 4.5:1。C 明度三档——战斗屏信息面高于世界中,世界中高于世界底。D 文字禁压纹理——文字框背景中带灰度 std 不高于 18。F 文字在——菜单标题框内与中位灰度差大于 60 的像素占比落在 2% 到 55%。B/C/D 只在清单含 `shot_battle.png` 时跑,F 只在含 `shot_menu.png` 时跑,其余屏只跑 A。全过 0,缺参数或任一失败 1。 **已知坑与适用边界**:截图必须由窗口化 `shot_probe` 产出;headless 没有渲染面,截图是空的。`shot_meta.json` 缺失时 B/C/D 直接判 meta 几何缺失,不会跳过。尺寸断言按「任一边等于 1280」放行;1920×1080 截图两边都不等于 1280,会被判非工程档,与文件头「1920 档 1.5×」说明不一致,按源码为准。焦点预算是目检项,机检不判。 diff --git a/design/art/art-prompts.md b/design/art/art-prompts.md index 0a32a712..76b27d71 100644 --- a/design/art/art-prompts.md +++ b/design/art/art-prompts.md @@ -1,4 +1,4 @@ -# 生图提示词卡(角色级资产)v2.12 +# 生图提示词卡(角色级资产)v2.13 > **性质**:美术清单生图通道(✦ 用户自跑,现走线上 API)的执行侧文件——每资产一段**自包含完整提示词**:正向 = 通用底座+主体+动作已拼妥、负向 = 通用底座+增补已并妥,整段复制直接贴进工作流即可,**不需要读其他文件、不需要拼装**。人物规格转写自 [character-design.md](character-design.md)(人物设计 v1.0,自 art-bible §5 迁出,圣经 §5 为存根),风格/色彩条款转写自 [art-bible](art-bible.md)(§4.1 主色板 / §4.2 语义色规则);冲突时人物规格以 character-design 为准、色彩以 art-bible 为准。 > **边界**:本文件只管**角色级**资产的生图通道。图标/格面/样张走脚本管线(⚙ 代理出),规格在 art-bible §4.6 与 [art-assets-checklist](art-assets-checklist.md),不需要提示词。**场景级资产(营地场景图的背景层与八个物件层)另立 [camp-scene-prompts](camp-scene-prompts.md);战斗舞台背景层与连续地面层另立 [battle-stage-prompts](battle-stage-prompts.md),本文件不覆盖**;两卡的角色/场景分工以「谁的资产谁出卡」为界,同一段提示词不两处维护。战斗舞台的小石台件与护甲类型图标三枚的**出图工单**登记在本文件 §5;§5 只把各权威节的定值收进逐件工单,不立新值。意图动画三档是动画资产,等一屏样张锁方案后另立规格卡,本文件不覆盖。 @@ -290,7 +290,7 @@ Seamless tileable pixel art texture of dry dirt ground, top-down, for a dungeon > **定值纪律(§8 头注 定值单点纪律)**:本节**指路不立值**——色值 = 圣经 §4.1(含场景环境子板)、尺寸与缩放 = §8.2、明度带 = §2、甲档 = character-design §5.3、命名 = §8.3 + asset-path-map。本节新增零定值;凡圣经未定的值,一律进本节 §5.5 缺口,不在本节填空。 > **验收标注纪律**:逐条按三档标 `←机检: <断言>` / `←目检: <判据>` / `←方向性`,照圣经头注 2026-10-06 用户拍板的写法。 > **流程**:出图前后一律走 §0 五步;出图登记义务照 remote-gen-prompts 头注轻量口径(用途+生成时间必注,其余参数有则记),随候选图存 `artwork/candidates/<资产名>/`;登记不作正稿遴选前置。 -> **产出状态**:组二地台件与组三护甲三枚已按各节 ⑤「程序化产出即终稿」产出入包(`scene_stage_plaza.png` 48×12、`ui_armor_light/ward/heavy.png` 24×24,路径见各组 ① 字段;登记=战斗一屏样张批,合并提交 3b66d1a6);组一背景插画已迁至 [battle-stage-prompts](battle-stage-prompts.md)(仍待出图),组四立绘重产仍待出图。 +> **产出状态**:组二地台件与组三护甲三枚已按各节 ⑤「程序化产出即终稿」产出入包(`scene_stage_plaza.png` 48×12、`ui_armor_light/ward/heavy.png` 24×24,路径见各组 ① 字段;登记=战斗一屏样张批,合并提交 3b66d1a6);组一背景插画见 [battle-stage-prompts](battle-stage-prompts.md)(三张背景+共用地面已入包,四柱/平色底退役归代码批),组四改按档派生(不重画,待实装批落位)。 ### 5.1 组一 · B 区舞台背景插画(1 件) @@ -375,25 +375,27 @@ Seamless tileable pixel art texture of dry dirt ground, top-down, for a dungeon - ←方向性: 冷灰与全作暖底成材质对比(§5.3),不靠明度差与地台 `#968264`(L≈0.234)抢读——立绘与地台的可辨归 §5.1 轮廓通道 - 来源与工艺:♻ 素材站 plate armor 肩甲/胸甲类图标改色 → 闸四道;⚙ 兜底 24×24 内肩 + 胸两块甲板,与全作暖底成材质对比(§5.3 冷灰金属与暖底对比) -### 5.4 组四 · 主角与三 Boss 立绘重产(4 件) +### 5.4 组四 · 站桩立绘按档派生(9 件,不重画) -**四件共用字段** +> 本节是站桩立绘的**按档派生**工单:现有形象即终稿、禁改形象;清晰度靠保留原稿分辨率+显示按三档绝对高缩放解决,不重画、不生成。 + +**九件共用字段** | 字段 | 值 | |---|---| | ① 路径与命名 | `game/assets/art/character/character_hero_portrait.png` + `game/assets/art/character/character_enemy_.png`(域键 `character`,对象键 = `hero` / enemy_id,命名照 §8.3 与 asset-path-map §3 现役写法) | -| ② 尺寸档与像素网格 | **源档高逐键** = 主角 48 / ogre_chief 74 / drider 90 / duergar_king 94(§8.2 立绘源档表,逐件值见本节 5.4.1–5.4.4);**宽随源图宽高比,纵横倍率恒等**(§8.2 站桩立绘槽位 = 高定宽随条,禁把立绘塞进统一方框强拉);九宫格 = 否;显示一律 **×2 整数档** = 96 / 148 / 180 / 188;**乙类**(角色与单位精灵)——乙类允许非整数,本批按 §8.2 定案走 ×2 整数档 | -| ③ 色板约束 | 进**语义/UI token 板**(§4.1 分层①);**48 余量 0**(2026-10-28 用户裁:本组新增卓尔浅紫灰皮 1 枚,全板余量 2 → 0,额度已用尽)。逐件沿用 character-design §5.4 / §5.5 已登记色值;该两节只给形容词未给色值的部件,**2026-10-28 用户裁已落值**——四处换色合并(零额度)+ 卓尔浅紫灰皮新增 1 枚,逐件取值见本节 5.4.1–5.4.4,额度账见 §5.5 缺口 4。**石君王岩石板甲 = 重甲甲材质色、与 §5.3.3 同一枚,工单直接引 `#868C9A`、不另计额度**。单张像素域色数 ≤32。第二道门同本节 5.1 | +| ② 尺寸档与像素网格 | **源 = 原稿像素网格**(八敌 `pixel-1`、主角手修 2× 三态稿),紧裁后原样入包,**禁再降采样**;**显示档 = 三档绝对高**——小 96(地精/巨蜘蛛/灰矮人)、中 144(主角/钩爪恐魔/熊地精)、大 188(食人魔酋长/蛛化卓尔/灰矮人石君王),定值单点 = art-bible §8.2;显示倍率 = 档高 ÷ 源高,NEAREST,宽随源图比例(高定宽随、纵横倍率恒等,禁方框强拉);九宫格 = 否 | +| ③ 色板约束 | 色值以**现役稿**为准,本批零新增色、零换色;单张像素域色数 ≤32(`pixel-1` 与手修 2× 稿实测均 ≤32)。`#A79CB8` 保留在板、本批不消费,色板额度议题另批讨论 | | ④ 明度带归属 | **世界中层 L 0.22–0.45**(§2 世界中层 = 格底顶面 / 角色 / 物件)——判定对象 = 角色体块主色。描边与落影底盘属轮廓通道(character-design §5.1)、紫赤点缀属 §4.2 色相独占的语义色,两者都不按明度带判定 | -| ⑤ 是否程序化件 | 否 → **须手绘**。口径 = **精细手绘像素**(2026-10-14 用户裁:仍是像素风,手绘像素簇 + 更高源密度;不是插画、不是 HD-2D、不回退高清图);**禁 AI 降采样当终稿**。现行 AI 降采样立绘 = 占位态,按 §7.1 占位完成条款须在终稿闸前换代 | +| ⑤ 是否程序化件 | 否 → **零绘制**:源 = 现有原稿,本批不生成、不重画(现有形象即终稿)。§7.1 占位完成条款对本组不适用——现役稿即终稿 | | ⑥ 验收判据 | 见下方共用验收 | -| ⑦ 出图操作要点 | 见下方工艺要点(手绘,不产生图提示词) | +| ⑦ 操作要点 | 见下方派生要点(零绘制,不产生图提示词) | **共用验收(四件都要过)** -- ←机检: 源档高逐位等于 48 / 74 / 90 / 94,显示 = 源 ×2(96 / 148 / 180 / 188),过滤 = NEAREST +- ←机检: 逐件显示档高与归档一致(小 96 / 中 144 / 大 188),过滤 = NEAREST,纵横倍率恒等;源高低于档高者按已接受放大项登记(主角 92 / 钩爪 94 / 熊地精 123 / 地精 90 / 巨蜘蛛 81) - ←机检: 单张像素域色数 ≤32 -- ←机检: 脚底基线对齐(派生管线四条:等比整数缩放 + 降色 ≤32 + 脚底基线对齐 + 命名合规) +- ←机检: 脚底基线对齐(紧裁 + 底中锚;命名合规、像素域色数 ≤32 同旧) - ←机检: 主角描边 = `(40,19,13)`;敌方描边取暖白族(非黑、非深褐)—— character-design §5.1 主角描边例外条 - ←机检: Alpha 直出——不透明区外缘 1px 环内无生成底残留(无 R/G/B 三通道均 ≥230 且 alpha > 0 的像素),防抠图白边 - ←机检: 零 HSV 300°–345° 像素(drider / duergar_king 两 Boss 除外,§4.2 独占) @@ -401,48 +403,39 @@ Seamless tileable pixel art texture of dry dirt ground, top-down, for a dungeon - ←目检: 放大 4 倍,轮廓与衣服是成组的像素,不是降采样噪点(三判据①) - ←目检: 显示 96–188px 下脸、铲、旗、物种能认出来,不必先读名字(三判据②) - ←目检: 显示仍用邻近采样,不出现插画那种平滑渐变(三判据③) -- ←方向性: 精细手绘像素气质——不是插画、也不是半像素半高清 +- ←方向性: 现有形象即终稿,本批禁改形象 三判据出处 = `reports/美术审计-cursor会话存档-2026-10-14.md` §2.2。 -**工艺要点(手绘)** +**派生要点(零绘制)** -1. 出件顺序 = 先主角、再三 Boss(Alpha 范围 = 主角 + 三 Boss 重产,其余敌种当前可读则保留到 Beta)。 -2. **源密度判据 = 三判据②**:显示 96–188px 下脸、铲、旗、物种可认——照这条反推源档即可,逐键定档已完成(§8.2),本批不必再猜档位。 -3. 手绘起稿顺序 = 剪影(§5.1 archetype)→ 体块主色 → 暗部与受光 → 描边 → 落影底盘。 -4. 逐件 2–3 版候选;登记照 remote-gen-prompts 头注轻量口径(用途+生成时间必注,手绘作者有则记),随候选图存 `artwork/candidates/<资产名>/`。 -5. 候选评审 = 并排横评,**隐去文件名与来源后按三判据逐条判读**(§0 五步第 1 步「便于横评」的手绘侧落法),不靠记忆与印象拍板。 -6. 出件 = 透明 PNG(Alpha 直出,禁先出白底图再抠);入包前过 §8.3 色板检查器(报新增色 / 近色告警 / 超 48 上限拦截)。 +1. 出件顺序 = 先主角三态,再三 Boss,再其余四敌(同管线,无绘制差异)。 +2. 每件 = `pixel-1`/手修 2× 稿紧裁(去透明边、底中锚)→ 原样落 `game/assets/art/character/character_*`;**不做 `dom_block_resize`**。 +3. 入包前过 §8.3 色板检查器与 standee_asset_check(按 §8.2 显示档校验逐件档高与纵横倍率)。 +4. 桩盒宽 150 与 >150 溢出档的实装口径归代码批(art-bible §8.2 排版条);食人魔超宽 8px 为已接受项。 -**5.4.1 主角(源 48 / 显示 96)** +**5.4.1 主角(中档 144)** -- 形象 = character-design §5.4 形象锚逐字执行:蓝兜帽取下披肩、暖米白上衣、深棕工装裤、额前护目镜、半指手套、卷裤脚皮护膝、圆头挖掘铲、结构式冒险背包配朱红矩形旗、腰挂提灯 -- 已登记色:兜帽 `#2E86DE` / 上衣 `#EFE3C8` / 长裤 `#6B4A2E` / 皮革 `#8A5A34` / 眼 `#33261B` / 旗 `#C63D22` / 描边 `(40,19,13)` -- 已落值(2026-10-28 用户裁):**铲刃浅铁灰 = `FOG_MEMORY_INK #C4C4C4`**;**提灯铜色 = `GOLD_DEEP #B07A14`**——两件均走换色合并、零额度(character-design §5.4 对这两件只有形容词,账见 §5.5 缺口 4)。代价已随裁定接受:`#C4C4C4` 一色两岗(语义岗 = 迷雾记忆墨 §6.5)、`#B07A14` 属金族(§4.2 金只说收益与兑现);两者均为角色随身件材质色,不进信息层与语义物件岗 -- 破例记账:背包 + 旗 = 主角对 §5.1「对称」的唯一破例组,旗面朝向恒定画右;轮廓凹凸预算按背包 + 旗整组记账 -- 朝向:战斗画面的侧身面向怪物形象属状态图(§5.4 生成顺序口径);重产沿用现役朝向,不重新裁定 +- 形象 = 现役稿即终稿,character-design §5.4 形象锚已兑现于现役素材;朝向沿用现役,不重新裁定 +- 色 = 以现役稿为准(§5.5 缺口 4 的额度账随色板议题另批处理) +- 源 = `hero-ref/edit/normal_2x.png`(内容 88×92);attack/hit 用 `attack_2x.png`/`hit_2x.png` -**5.4.2 食人魔酋长 ogre_chief(源 74 / 显示 148)** +**5.4.2 食人魔酋长 ogre_chief(大档 188)** -- 档位 = 精英档(形状仍守精英档:普通怪形 + 恰一处垂直延伸 = 头顶骨与羽冠,底盘不变;第一关关底 Boss 战,不升 Boss 形) -- 甲档 = 轻甲 → 甲面覆盖率 ≈ 0:皮条 / 骨饰点缀、裸身为主,零甲板零符纹 -- 主色域 = 暖褐皮、圆肚;**暖褐皮 = `暖石 #B8A582`**(2026-10-28 用户裁:换色合并、零额度;体块主色带 §5.4 ④ L 0.22–0.45 校验 L≈0.387 ✓;character-design §5.5 该行原只有形容词) +- 档位 = 大型(三场 Boss 战全归大型);形状仍守精英档剪影——普通怪形 + 恰一处垂直延伸(头顶骨与羽冠),底盘不变 +- 甲档 = 轻甲(皮条/骨饰点缀、裸身为主,零甲板零符纹)——现役稿已如此 +- 源 = `ogre_chief/pixel-1.png`(158×189);显示宽 157 超桩盒 150 为已接受项 -**5.4.3 蛛化卓尔精灵 drider(源 90 / 显示 180)** +**5.4.3 蛛化卓尔精灵 drider(大档 188)** -- 档位 = Boss(敌类中唯一允许锐角与不对称者,体量最大) -- 甲档 = 魔法护甲 → 符纹饰带(暖白,覆盖率居中);蛛腹几丁质属天然甲壳,不计甲档 -- 独占:紫赤 `#8F2F6A`(色相 323°)+ 形状独占双通道;全项目色相 300°–345° 只许本件与 5.4.4 出现 -- **卓尔上体浅紫灰皮 = `#A79CB8`**(2026-10-28 用户裁:**新增 1 枚**,入 §4.1 分层①——在册紫族四枚全部语义岗占用且 L <0.22,无一可复用)。体块主色带 L 0.22–0.45 校验 L≈0.355 ✓;色相 264° 避 300°–345° 禁入带,紫赤独占仍归 `#8F2F6A`。**对比实测(本节新算,此前未给值)**:对深素底 `#282220` **6.04:1**、对舞台底 `#3E362C` **4.57:1**——两处均过 §4.1 图形 ≥3:1 门槛 -- 大体档:显示 180 > 150 → 允许向上溢出盒顶(§8.2 站桩排版③ 甲案;溢出量 N 由实装批用真图复算 x 区间定,血条仍落底) +- 档位 = 大型;紫赤 `#8F2F6A` 色相独占 + 形状独占双通道维持现役稿 +- 甲档 = 魔法护甲(符纹饰带)——现役稿已如此 +- 源 = `drider/pixel-1.png`(140×189);皮色 `#A79CB8` 保留在板、本批不消费 -**5.4.4 灰矮人石君王 duergar_king(源 94 / 显示 188)** +**5.4.4 灰矮人石君王 duergar_king(大档 188)** -- 档位 = Boss(锐角与不对称,体量最大档) -- 甲档 = 重甲 → 金属甲板(冷灰,覆盖率最大) -- 独占:紫赤 `#8F2F6A` + 形状独占双通道;大地 / 岩石主题 -- 岩石板甲与灰皮(2026-10-28 用户裁,character-design §5.5 该行原只有形容词):**岩石板甲 = 重甲甲材质色,与 §5.3.3 同一枚 → 直接引 `#868C9A`,不另计额度**;**灰皮 = `STONE #786E62`**(按**次级皮**口径——石君王重甲覆盖率最大、板甲视同体块主色,故灰皮属次级皮、不受 L 0.22–0.45 约束;换色合并、零额度) -- 大体档:显示 188 > 150 → 溢出盒顶同 5.4.3 +- 档位 = 大型(锐角与不对称);紫赤独占 + 岩石板甲维持现役稿色 +- 源 = `duergar_king/pixel-1.png`(133×189) ### 5.5 缺口(四条 · 缺口 1/2/4 于 2026-10-28 已裁转指路,缺口 3 结论已立) diff --git a/design/art/art-status-checklist.md b/design/art/art-status-checklist.md index 8f42ca4c..e338fadc 100644 --- a/design/art/art-status-checklist.md +++ b/design/art/art-status-checklist.md @@ -17,8 +17,8 @@ | 素材 | 状态 | 需求文档 | |---|---|---| -| 主角战斗小人(待机/攻击/受击三态) | ✅ B区站桩三态全接(2026-09-29 迭代 6 T3:normal/attack/hit 48px 档入包+挂事件切换+结算回 idle,短驻自回;棋盘 1.5×/脚锚25%/椭圆影在役不变;hit 态源=new-hit.pxo 已程序导出) | [character-design](character-design.md) + [art-prompts](art-prompts.md) §2 | -| 八敌种形象(L2 熊地精=bugbear 复用,不单列) | ✅ B区站桩八敌真图服役(2026-09-29 迭代 6 T1/T2:pixel-1 源→48px 档统一比例/底中锚/众数投票降采样,character_enemy_<键>.png 按常量入位,字形回退退役为缺位兜底;素材不入 git 本地在盘)。八敌源档已定(36–94,art-bible §8.2),旧统一 48 档为过渡形态,新档重产落位归 PRD(tools/pixelize_candidates.py `STANDEE_TIER_H` 已改,产出与定档总图一致) | [art-bible](art-bible.md) §5 + [art-prompts](art-prompts.md) §3 | +| 主角战斗小人(待机/攻击/受击三态) | ✅ B区站桩三态全接(2026-09-29 迭代 6 T3:normal/attack/hit 48px 档入包+挂事件切换+结算回 idle,短驻自回;棋盘 1.5×/脚锚25%/椭圆影在役不变;hit 态源=new-hit.pxo 已程序导出;2026-11-01 显示档改中档 144(源=手修 2× 三态稿,art-bible §8.2 v3.32),按档派生落位归本条实装批) | [character-design](character-design.md) + [art-prompts](art-prompts.md) §2 | +| 八敌种形象(L2 熊地精=bugbear 复用,不单列) | ✅ B区站桩八敌真图服役(2026-09-29 迭代 6 T1/T2:pixel-1 源→48px 档统一比例/底中锚/众数投票降采样,character_enemy_<键>.png 按常量入位,字形回退退役为缺位兜底;素材不入 git 本地在盘)。2026-11-01 显示档换代=三档绝对高 96/144/188(art-bible §8.2 v3.32),源 = 原稿不降采样,按档派生落位归本条实装批 | [art-bible](art-bible.md) §5 + [art-prompts](art-prompts.md) §3 | | 意图准备动画三档 | ◐ | [art-bible](art-bible.md) §4.6.4 | ## P2 图标与格面(可与样张并行) diff --git a/design/art/character-design.md b/design/art/character-design.md index 494df172..0bb507fe 100644 --- a/design/art/character-design.md +++ b/design/art/character-design.md @@ -42,7 +42,7 @@ - **兜帽披肩**:兜帽**不戴在头上**,取下披于肩上——露出棕色短发与整脸(表情可读),蓝色兜帽披在肩头仍是最近的"己方"识别点;三态同款披肩。 - **圆头挖掘铲(武器)**:持铲不持剑——**铲 = 本作核心动词"挖安全格"的角色化**,挖掘与攻击共用同一动作语义(攻击表现即挥铲,后续攻击类表现优先围绕铲展开)。画法:圆头铲刃 + 木柄(木柄走木色族 `#8A5A34`,铲刃浅铁灰、不做冷灰重甲质感);**待机态 = 铲插立在地上、一只手扶在铲柄顶端**;攻击/受击态仍为手持。刀光/铲击光效/弹道不进精灵图(归战斗演出另立资产)。 - **冒险背包与背包旗(身份件)**:背负**结构式冒险背包**——翻盖+皮扣带的帆布背包(暖卡其布面,皮革件走木色族),**宽 ≈1.5× 体宽**:双肩背负、两侧各略超出身形一点;**禁圆麻袋化**(措辞弃"鼓胀掳获袋")、**禁特里式 3× 超宽**(反面参照:旷野之息特里;正面参照:合金弹头双主角大背包、超级马里奥奇诺比奥队长)。**旗杆插在背包一侧**(不要求完整可见,**被头部遮挡一部分亦可**),旗子**尺寸大于头部**,短杆**矩形**旗旗面 = **旗朱红 `#C63D22`**(人设背包旗与棋盘封印色**脱钩**——封印色仅作用于棋盘格封印旗,色史归 art-bible §4.1;人设旗形为矩形非三角,以 normal/hit 定稿成图为基准),把"宣告落旗"的角色化焊在人设上,主角即背包旗持有者(**动作呈现名 = 封印**,见 art-bible §3.2;背包旗**不**视作封印印记的携带形态——旗面旗朱红矩形,与棋盘封印黑旗形色均不同,仅保留"主角即背包旗持有者"的身份叙事)。三条纪律:①旗面红=旗朱语义**仅旗非服饰**(负向 `no red clothing` 不拦截正向 `red flag`——红服饰禁令与红旗的边界由正向句显式锁色值;封印黑仍为棋盘格封印旗专属色,圣经 §4.1 不变);②背包+旗 = 主角对 §5.1"对称"的**唯一破例组**(语义配件非装饰),旗面朝向恒定画右、跨素材一致;③轮廓凹凸预算按"背包+旗"整组记账,样张(圣经 §1.4)验证背负后剪影仍窄、仍可辨、不超格宽。 -- **护目镜与腰灯**:**护目镜推在额前**(兜帽披肩后直接戴于额上,不戴眼上——眼睛是表情载体;皮革带+圆镜片,防尘挖掘者的职业信号);**提灯挂腰间,定案不手持**(小号铜色提灯,**不点亮**;空间光照属圣经 §2 明度分层允许域,**提灯点亮为候选**,点亮形制(光晕半径/暖色值/与舞台光照关系)归整屏样张重议;头部饰品唯一化,头灯方案已弃)。 +- **护目镜与腰灯**:**护目镜推在额前**(兜帽披肩后直接戴于额上,不戴眼上——眼睛是表情载体;皮革带+圆镜片,防尘挖掘者的职业信号);**提灯挂腰间,定案不手持**(小号铜色提灯,**不点亮**;空间光照走圣经 §2 明度分层,**提灯点亮为候选**,点亮形制(光晕半径/暖色值/与舞台光照关系)归整屏样张重议;头部饰品唯一化,头灯方案已弃)。 - **衣着细节**:**棕色半指手套**(挖土护手,露指保灵巧读感)+ **裤脚卷起、棕色皮护膝**(挖掘跪地的工装感)——小件走皮革木色族,不占剪影凹凸预算,不新增语义色。 - **三态**:① 待机 = 窄、直立、对称(§5.1 小人原型,含背包、旗与提灯记账);② 攻击 = 允许破对称,整体仍窄、不超格宽;③ 受击 = 无血红、无伤害数字(伤害数字归 HUD 层,不进精灵图)。 - **随身件 = 秘宝形象候选池**:铲、旗、背包、提灯四件随身件是未来秘宝设计的**形象候选池**——道具实装可借用主角身上已有的同款(彩蛋闭环:玩家在道具栏认出主角身上的物件);具体道具语义/数值归秘宝 GDD,人设侧义务 = 四件画得出来、认得出。 @@ -67,7 +67,7 @@ - **主色域 = 物种本色**,不受圣经 §4.2 语义色禁则约束(该禁则管格面与 UI 的逻辑色,角色身体主色豁免);**两例外**:禁入带 300°–345° 全角色禁入(仅 drider/duergar_king 两 Boss 独占)、蓝族禁入敌方主色(§5.4 同款)。 - **L2 熊地精 = bugbear 复用**(第二关三行,显示名熊地精系,非独立键):同剪影**换色板不换形**(色板替换走脚本管线——原则三"先换色板"的角色侧应用);变体主色避小人蓝族与禁入带。 - 每敌种出 2–3 版候选(清单 §2.2);受击反馈/死亡表现/顺位标记三类呈现下限见圣经 §4.6.4 资产需求行。 -- **立绘源档高(定值单点 = 圣经 §8.2 立绘源档表,本档指路不复述)**:八敌 36–94 逐键定档 + 主角 48 不变、显示一律 ×2 整数档(NEAREST)——**数值权威一律圣经 §8.2**(定值单点纪律,圣经 §8 头注);定档经三体型约束校验(§5.2)确认;派生管线与排版规范同归圣经 §8.2。 +- **立绘显示档(定值单点 = 圣经 §8.2 站桩立绘显示档条,本档指路不复述)**:三档绝对高 96/144/188,逐件归档、源档与缩放规则一律见圣经 §8.2——**数值权威 = 圣经 §8.2**(定值单点纪律,圣经 §8 头注);归档经三体型约束校验(§5.2)确认;派生管线与排版规范同归圣经 §8.2。 - **钩爪恐魔「宽≥高」豁免登记(待样张终审)**:定档源 58 高窄条束状剪影(长臂圆钩),宽高比 <1,与 §5.1 普通怪「近圆墩形宽≥高」冲突——按体量=生物天性(§5.2)登记豁免:以长臂束状轮廓为识别锚,不强行压成墩形;样张(圣经 §1.4)终审复验灰度剪影可辨性。 ## 5.6 意图准备动画三档(规格承载节) diff --git a/design/gdd/08-Alpha版本标准.md b/design/gdd/08-Alpha版本标准.md index e3de01e2..a3dc8fc1 100644 --- a/design/gdd/08-Alpha版本标准.md +++ b/design/gdd/08-Alpha版本标准.md @@ -2,7 +2,7 @@ > **一句话定位**:本文定义这个项目的 **Alpha 版本包含哪些东西**——它是里程碑 M3 的完成标准,也是判断"还差什么"的对照表。 > **本文只列条目,不写内容**:每样东西是什么、规则怎么走,一律归各自的权威文档,本文只给指路链接。想知道某样东西的定义,请点链接,不要在本文里找解释。 -> **状态**:**已定稿(v1.21)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。 +> **状态**:**已定稿(v1.22)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。 > **成文**:2026-10-13。 ## 本文怎么用 @@ -147,7 +147,7 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战 | 棋盘瓦片与格面资源图标 | [美术圣经](../art/art-bible.md) | 在役 | | 未开格类型微光(五组色相+明度档) | [HUD框架](systems/表现与支撑/HUD框架.md) | 在役(明度档 provisional 值登记见 art-bible 的 git 提交史,复核转正归战斗一屏样张) | | 棋盘观感(第二 / 三关亮度与对比度) | [待办清单](../../待办清单.md) | 待做(开工前置=先做素材轴/UI 轴对照截图定性,再按定轴修复;旧卡 v1.4 存 reports/ 作素材、非已写卡状态,重启须重新立卡;出口=用户实机目检第二、三关不再判「看着费劲」) | -| 立绘清晰度回退评估(是否改用高清图) | [角色设计](../art/character-design.md) | 待做(评估已结——2026-10-14 用户裁维持像素风、升级精细手绘像素、不回退高清图,裁决录=[美术审计-cursor会话存档](../../reports/美术审计-cursor会话存档-2026-10-14.md) §2.2;Alpha 范围=主角+三个 Boss 按新口径重产,其余敌种当前可读则保留到 Beta;出口=用户目检八敌体量关系通过且主角与三个 Boss 重产完成) | +| 立绘显示清晰度(原稿分辨率+三档显示) | [角色设计](../art/character-design.md) | 待做(评估已结——不回退高清、维持像素风;终态方案=保留原稿分辨率、入包禁降采样、显示按三档绝对高 96/144/188 缩放、现有形象即终稿;裁决录=待办清单本条+art-bible §8.2;出口=9 件按档落位+用户目检清晰度与同屏体量顺序通过) | | 敌人立绘(全敌种) | [角色设计](../art/character-design.md) | 在役 | | 主角立绘三态 | [角色设计](../art/character-design.md) | 在役 | | 状态图标 | [美术圣经](../art/art-bible.md) | 在役 | diff --git a/design/gdd/ux/battle.md b/design/gdd/ux/battle.md index 5c2f5747..b71ed645 100644 --- a/design/gdd/ux/battle.md +++ b/design/gdd/ux/battle.md @@ -366,7 +366,7 @@ - [ ] 两种格态(已开格 / 未开格)灰度截图下一眼可辨(排雷玩法×6②) - [ ] 悬停光标区分移动/挖/封印三语义;可挖域(8 向相邻)常驻指示;非相邻格悬停显禁止反馈(排雷玩法×6③) - [ ] 已引爆危险格呈"可通行可读"(排雷玩法×6④) -- [ ] 全部数字对所在格底对比 ≥4.5:1;明度分层规则无违例(art-bible §2/§4.1,v3.0——状态区分不走明度,格底功能分档合法) +- [ ] 全部数字对所在格底对比 ≥4.5:1;明度分层规则无违例(art-bible §2/§4.1——格底功能分档合法,格态语义由形与色相承载) **交互与反馈** diff --git a/design/gdd/ux/camp.md b/design/gdd/ux/camp.md index ba9a09a0..72170a73 100644 --- a/design/gdd/ux/camp.md +++ b/design/gdd/ux/camp.md @@ -1,6 +1,6 @@ # 营地场景 UX spec(camp) -> 状态:v2.2(现行) +> 状态:v2.3(现行) > 事实源:本 spec(呈现)+ [元进度](../systems/跨局循环/元进度.md)(机制) > 美术画法:[art-bible](../../art/art-bible.md) §6.2/§7.5;素材命名与路径:[asset-path-map](../../art/asset-path-map.md) > 相邻:[level-map.md](level-map.md)(主菜单语境) @@ -42,7 +42,7 @@ ## 叠层与开合 -各界面开合走模态栈单口,层序按模态栈契约登记。**承载形态(独立全屏页 vs 单一内页切换)与叠层规则归卡④ §9 代拍板域,本 spec 不预设值**;派生规则:独立全屏页=场景根隐藏/单一内页切换=场景根留底(「缩放虚化」为第三形态,禁批内自选)。ESC 浮窗(返回主菜单/设置/退出游戏)归卡⑤。 +各界面开合走模态栈单口,层序按模态栈契约登记。**承载形态已定稿(2026-11-01 用户裁)**:五个功能界面(锻造工坊/秘宝匣/天赋树/奖励格图鉴/生涯记录)各以**功能窗口**打开——场景根留底可见,窗口之下垫半透明压暗遮罩(交互聚焦用,复用既有模态遮罩件,现值锚黑色 0.6;观感随样张目检校准,属普通设计决策)。**五窗互斥单开**(模态栈深恒 1,不开窗叠窗);各窗自带关闭钮(卡④ v1.1 承诺面)。ESC 优先序:有功能窗口开着 → 先关最上层窗;无窗 → 才进卡⑤ ESC 浮窗(返回主菜单/设置/退出游戏)。 ## 口径 diff --git a/design/gdd/ux/level-map.md b/design/gdd/ux/level-map.md index d6fe55d3..7e1b2e82 100644 --- a/design/gdd/ux/level-map.md +++ b/design/gdd/ux/level-map.md @@ -234,6 +234,6 @@ | [HUD框架](../systems/表现与支撑/HUD框架.md) | 模态 overlay 层级纪律、订阅纪律(推进信号两线之一) | Navigation Position + Data Requirements 架构注记 | | HUD框架 | 可访问性基线全量(对比/色弱/字号/闪烁/减动效/纯鼠标/中文字体) | Accessibility | | [battle.md](battle.md) OQ14 二轮拍板 | GP = 关卡画面常驻总量 | 顶栏 GP 常驻徽章 | -| [art-bible](../../art/art-bible.md) | 方块地牢观感(§3.2 圆角方形世界侧)、色板冻结(§4.1)、半拟物(§7.1)、明度分层(§2,v3.0——状态不走明度、空间光照可走) | 图区组件 + Accessibility 对比条 | +| [art-bible](../../art/art-bible.md) | 方块地牢观感(§3.2 圆角方形世界侧)、色板冻结(§4.1)、半拟物(§7.1)、明度分层(§2) | 图区组件 + Accessibility 对比条 | --- diff --git a/game/presentation/camp_shop_presenter.gd b/game/presentation/camp_shop_presenter.gd index 07094d3b..f57a8a31 100644 --- a/game/presentation/camp_shop_presenter.gd +++ b/game/presentation/camp_shop_presenter.gd @@ -42,6 +42,7 @@ func open_camp() -> void: meta.refresh_treasure_unlocks() # 条件解锁刷新 start_overlay.visible = false _open_modal.call(views.camp_scene) # 模态栈单口(场景根开——选档层被栈遮挡挂起) + views.refresh_bus.refresh(camp_data()) # 进档动线尾显式刷新一闸(卡⑤ 契约 5 时机②——HUD 读数重读) _refresh_presentations.call() diff --git a/game/presentation/main.gd b/game/presentation/main.gd index 8d10c7ae..8e277baf 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -528,6 +528,25 @@ func _on_camp_object_pressed(key: StringName) -> void: MainOverlayFlow._on_camp_object_pressed(self, key) # 场景点选路由(卡④ T3——薄委托,实现归覆盖层流程承接件) +# Esc 输入入口(产品码首个键盘入口——卡⑤ T1 契约 9 接线定稿:事件驱动 _unhandled_input、 +# KEY_ESCAPE 键值判定配 physical_keycode、pressed 且非 echo、禁 Input 单例轮询、不挂 ui_cancel) +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventKey and event.pressed and not event.echo and (event.keycode == KEY_ESCAPE or event.physical_keycode == KEY_ESCAPE): + MainEscFlow.on_esc_input(self) + + +func _on_esc_return() -> void: + MainEscFlow._on_return_to_menu(self) + + +func _on_esc_settings() -> void: + MainEscFlow._on_settings(self) + + +func _on_esc_quit() -> void: + MainEscFlow._on_quit(self) + + func _camp_data() -> Dictionary: return MainOverlayFlow._camp_data(self) diff --git a/game/presentation/main_esc_flow.gd b/game/presentation/main_esc_flow.gd new file mode 100644 index 00000000..9ec94068 --- /dev/null +++ b/game/presentation/main_esc_flow.gd @@ -0,0 +1,56 @@ +## 组合根 Esc 流程承接件(产品码首个键盘输入入口——main._unhandled_input 同名薄委托落地): +## Esc 四态路由(契约 9 判据单点=ModalStack 登记册现开集合,禁手枚名单)+三出口动线。 +## 静态承接件零成员态(仿 main_overlay_flow 形态——main 侧留同名薄委托,探针 main.X 路径零改动)。 +class_name MainEscFlow +extends RefCounted + + +## 营地语境判据(Q1 甲——场景根 visible;子界面开态抑制由契约 9① 现开集合承载,不并入本谓词) +static func is_camp_context(root: Variant) -> bool: + return root.ui.modals.camp.scene != null and root.ui.modals.camp.scene.visible + + +## Esc 优先序(camp.md v2.3 定稿 2026-11-01 用户裁——有功能窗开着→先关最上层窗,覆盖卡⑤ 契约 9① +## 的 Q1 甲无反馈;设置开在浮窗之上仍无反馈=契约 3 保留): +## ①功能窗开着→close 最上层窗→①'设置开在浮窗之上→无反馈→②浮窗开→close(Q2 同键单义)→ +## ③营地语境→open→④非营地→无反馈 +static func on_esc_input(root: Variant) -> void: + var esc: Control = root.ui.modals.camp.esc_overlay + var window := _topmost_camp_window(root) + if window != null: + root.ui.modals.flow.close(window) # ① 先关最上层功能窗(v2.3 定稿) + return + if root.ui.modals.settings_overlay.visible: + return # ①' 设置开在浮窗之上 → 无反馈(浮窗不隔层关闭——契约 3) + if esc.visible: + root.ui.modals.flow.close(esc) # ② 再按 Esc 关窗 + return + if is_camp_context(root): + root.ui.modals.flow.open(esc) # ③ 营地语境唤起 + # ④ 非营地语境 → 无反馈 + + +# 五功能窗现开查询(camp.md v2.3 五窗互斥单开——模态栈深恒 1,至多一窗在开;生涯页入窗集) +static func _topmost_camp_window(root: Variant) -> Control: + for w: Control in [root.ui.modals.camp.forge, root.ui.modals.camp.treasure, root.ui.modals.camp.tree, + root.ui.modals.camp.codex, root.ui.modals.career_overlay]: + if w != null and w.visible: + return w + return null + + + +## 返回主菜单动线(契约 4):首步 close 浮窗(缺此步浮窗残留主菜单上方)→营地与选档层同收+开始层恢复 +static func _on_return_to_menu(root: Variant) -> void: + root.ui.modals.flow.close(root.ui.modals.camp.esc_overlay) + root._camp_pres.on_camp_closed() # 关层收闭单口(卡④ T3——营地层与选档层同收+开始层恢复) + + +## 设置出口(浮窗登记在设置层之下——open 只隐上方层,浮窗由树序遮挡非属性隐藏;关后重现=栈语义) +static func _on_settings(root: Variant) -> void: + root.ui.modals.flow.open(root.ui.modals.settings_overlay) + + +## 退出出口(_quit_game 原样复用——settings_store.save_settings+quit,零语义副作用) +static func _on_quit(root: Variant) -> void: + root._quit_game() diff --git a/game/presentation/main_esc_flow.gd.uid b/game/presentation/main_esc_flow.gd.uid new file mode 100644 index 00000000..261aac57 --- /dev/null +++ b/game/presentation/main_esc_flow.gd.uid @@ -0,0 +1 @@ +uid://caa868un7dnt4 diff --git a/game/presentation/main_overlay_flow.gd b/game/presentation/main_overlay_flow.gd index bf8d5a4d..7df4e973 100644 --- a/game/presentation/main_overlay_flow.gd +++ b/game/presentation/main_overlay_flow.gd @@ -10,7 +10,11 @@ static func _open_settings(root: Variant) -> void: static func _on_settings_closed(root: Variant) -> void: root.ui.modals.flow.close(root.ui.modals.settings_overlay) # 模态栈单口 - root.ui.screens.start_overlay.visible = true + # 语境分支(卡⑤ 契约 3——谓词=camp_esc_overlay.visible,谁开的设置谁收): + # 营地浮窗路径关设置回浮窗不回主菜单(栈语义:浮窗登记在下、由树序遮挡非属性隐藏); + # 菜单路径保留开始层恢复硬副作用。 + if not root.ui.modals.camp.esc_overlay.visible: + root.ui.screens.start_overlay.visible = true # ---- 局内状态面板·只读(入口角标在两屏装配段;开合与数据喂入归组合根)---- diff --git a/game/presentation/main_ui_build.gd b/game/presentation/main_ui_build.gd index 15172e8d..09164e42 100644 --- a/game/presentation/main_ui_build.gd +++ b/game/presentation/main_ui_build.gd @@ -110,6 +110,15 @@ static func _build_overlays(root: Variant) -> void: var codex := CodexView.new() root.add_child(codex) root.ui.modals.camp.codex = codex + # Esc 浮窗(卡⑤——登记于设置层之前的模态;三钮意图经 MainEscFlow 路由) + var esc_overlay := CampEscOverlay.new() + esc_overlay.setup_buttons() + esc_overlay.bind_signals() + root.add_child(esc_overlay) + root.ui.modals.camp.esc_overlay = esc_overlay + # 营地顶栏 HUD 栏(卡⑤——钥石余额常驻;挂卡④场景根顶栏预留位+入刷新单口目标册) + var hud_band := CampHudBand.new() + root.ui.modals.camp.scene.set_hud_band(hud_band) # 屏壳/子界面插位由 LAYER_CONTRACT 槽统一落位——禁散落 move_child root.ui.modals.legend_overlay.closed.connect(root.ui.modals.flow.close.bind(root.ui.modals.legend_overlay)) root.ui.modals.node_overlay.continue_pressed.connect(root._on_node_continue) @@ -178,7 +187,8 @@ static func _build_menu_wiring(root: Variant) -> void: # 营地刷新单口(各写口尾→现开界面+场景根 HUD 一闸完成——卡④ T3;卡⑤ HUD band 随卡⑤挂册) var camp_bus := CampRefreshBus.new() camp_bus.bind_targets([root.ui.modals.camp.forge, root.ui.modals.camp.treasure, - root.ui.modals.camp.tree, root.ui.modals.camp.codex] as Array[Control]) + root.ui.modals.camp.tree, root.ui.modals.camp.codex, + root.ui.screens.camp_screen.camp_scene.hud_band] as Array[Control]) root._camp_pres = CampShopPresenter.new(CampFlowContext.new(root.db, {"camp_scene": root.ui.modals.camp.scene, "forge_view": root.ui.modals.camp.forge, "treasure_view": root.ui.modals.camp.treasure, "tree_view": root.ui.modals.camp.tree, @@ -226,6 +236,10 @@ static func _build_debug_and_resolvers(root: Variant) -> void: root.ui.modals.confirm_dialog.confirmed.connect(root._on_confirm_accepted) root.ui.modals.confirm_dialog.secondary_confirmed.connect(root._on_confirm_secondary) # 三钮次确认(卡④ 大门「开始新冒险」出口) root.ui.modals.confirm_dialog.cancelled.connect(root._on_confirm_declined) + # Esc 浮窗三出口接线(卡⑤——意图信号经薄委托归 MainEscFlow 动线;输入入口=main._unhandled_input) + root.ui.modals.camp.esc_overlay.return_requested.connect(root._on_esc_return) + root.ui.modals.camp.esc_overlay.settings_requested.connect(root._on_esc_settings) + root.ui.modals.camp.esc_overlay.quit_requested.connect(root._on_esc_quit) # 调试浮窗(主菜单三散件收一:随机种子/数值调整/批量模拟/两层调试入口; # 全局可开浮窗:调试会话恒开=启动即开〔_ready〕+两屏角标再开+当局数据只读区块; diff --git a/game/presentation/ui_camp_modals.gd b/game/presentation/ui_camp_modals.gd index 12297b74..69cbd2a3 100644 --- a/game/presentation/ui_camp_modals.gd +++ b/game/presentation/ui_camp_modals.gd @@ -9,3 +9,4 @@ var forge: ForgeView # 锻造工坊子界面 var treasure: TreasureView # 秘宝匣子界面 var tree: TreeView # 天赋树子界面 var codex: CodexView # 奖励格图鉴子界面(占位挂起态) +var esc_overlay: CampEscOverlay # Esc 浮窗(卡⑤——终态六枚落满) diff --git a/game/presentation/ui_registry.gd b/game/presentation/ui_registry.gd index 67358424..ad4db46b 100644 --- a/game/presentation/ui_registry.gd +++ b/game/presentation/ui_registry.gd @@ -27,6 +27,7 @@ const LAYER_CONTRACT: Array[Dictionary] = [ {"key": "treasure_view", "kind": "modal", "tags": []}, {"key": "tree_view", "kind": "modal", "tags": []}, {"key": "codex_view", "kind": "modal", "tags": []}, + {"key": "camp_esc_overlay", "kind": "modal", "tags": []}, # Esc 浮窗(卡⑤——登记于营地层与设置层之间,契约 3 栈语义正解) {"key": "settings_overlay", "kind": "modal", "tags": []}, {"key": "status_panel", "kind": "modal", "tags": []}, {"key": "career_overlay", "kind": "modal", "tags": []}, @@ -67,6 +68,7 @@ func node(key: String) -> Node: "treasure_view": return modals.camp.treasure "tree_view": return modals.camp.tree "codex_view": return modals.camp.codex + "camp_esc_overlay": return modals.camp.esc_overlay "settings_overlay": return modals.settings_overlay "status_panel": return modals.status_panel "career_overlay": return modals.career_overlay diff --git a/game/presentation/views/camp_esc_overlay.gd b/game/presentation/views/camp_esc_overlay.gd new file mode 100644 index 00000000..44e4ac2e --- /dev/null +++ b/game/presentation/views/camp_esc_overlay.gd @@ -0,0 +1,32 @@ +## Esc 浮窗视图(营地语境 Esc 唤起):返回主菜单/设置/退出游戏三钮(裁决 9——三项且仅三项)。 +## 壳=UiKit.modal_shell(居中模态壳,ui_kit 工厂单点);退出钮=UiKit.danger_button;零新素材零新色值。 +## Q2 再按 Esc 关窗=组合根 Esc 路由直呼 flow.close(本视图无自关通路);三钮 pressed 外发意图不内含动线。 +## 零动效(契约 6——直开直关,子树零 AnimationPlayer、源码零动效令牌)。 +class_name CampEscOverlay +extends Control + +signal return_requested ## 返回主菜单意图(动线归 MainEscFlow._on_return_to_menu——首步 close 浮窗) +signal settings_requested ## 设置意图(开设置层——浮窗登记在其下,栈语义关后重现) +signal quit_requested ## 退出游戏意图(_quit_game 原样复用) + +var _return_btn: Button +var _settings_btn: Button +var _quit_btn: Button + + +func setup_buttons() -> void: + var box: VBoxContainer = UiKit.modal_shell(self, Color(UiKit.DIM, 0.55), Vector2(360, 0), 12, + UiKit.panel_skinned(Vector4(14, 12, 14, 12))).box + _return_btn = UiKit.button("返回主菜单") + box.add_child(_return_btn) + _settings_btn = UiKit.button("设置") + box.add_child(_settings_btn) + _quit_btn = UiKit.danger_button("退出游戏") + box.add_child(_quit_btn) + visible = false # 登记模态初始隐(开合走栈——模态纪律) + + +func bind_signals() -> void: + _return_btn.pressed.connect(func() -> void: return_requested.emit()) + _settings_btn.pressed.connect(func() -> void: settings_requested.emit()) + _quit_btn.pressed.connect(func() -> void: quit_requested.emit()) diff --git a/game/presentation/views/camp_esc_overlay.gd.uid b/game/presentation/views/camp_esc_overlay.gd.uid new file mode 100644 index 00000000..17d1a1a1 --- /dev/null +++ b/game/presentation/views/camp_esc_overlay.gd.uid @@ -0,0 +1 @@ +uid://col25elh1utw5 diff --git a/game/presentation/views/camp_hud_band.gd b/game/presentation/views/camp_hud_band.gd new file mode 100644 index 00000000..a228626a --- /dev/null +++ b/game/presentation/views/camp_hud_band.gd @@ -0,0 +1,27 @@ +## 营地顶栏小 HUD 栏(裁决 10——钥石余额常驻,最小集形态):承载 UiKit.keystone_badge(工厂单点)。 +## 读数只经 camp_data() 投影单口(禁第二账本、禁视图自算);刷新挂卡④ CampRefreshBus 单口 +## (bus 目标册成员——显式触发才变,禁 _ready 自刷/自持第二入口,契约 5);载体=PRESET_TOP_WIDE 48px 浮层。 +class_name CampHudBand +extends Control + +var _badge: PanelContainer + + +func _init() -> void: + set_anchors_preset(Control.PRESET_TOP_WIDE) + custom_minimum_size = Vector2(0, 48) # 高 48px 浮层覆盖、不挤压画面(camp.md §顶栏) + mouse_filter = Control.MOUSE_FILTER_IGNORE # HUD 栏不挡场景命中区(浮层覆盖语义) + _badge = UiKit.keystone_badge("钥石 0") + _badge.set_anchors_preset(Control.PRESET_CENTER_RIGHT) + _badge.position = Vector2(-160, 8) # 顶栏右位次(UiKit 现行件域内——代拍板 3) + add_child(_badge) + + +## 余额写入(格式串=既有消费面同款「钥石 %d」——badge 工厂约定单点,禁第二格式串) +func set_balance(v: int) -> void: + _badge.value_label.text = "钥石 %d" % v + + +## 刷新单口落点(CampRefreshBus 目标册成员——显式触发才变,契约 5 刷新时机①②③同一闸) +func refresh_camp(camp_data: Dictionary) -> void: + set_balance(int(camp_data.get("balance", 0))) diff --git a/game/presentation/views/camp_hud_band.gd.uid b/game/presentation/views/camp_hud_band.gd.uid new file mode 100644 index 00000000..6153c82b --- /dev/null +++ b/game/presentation/views/camp_hud_band.gd.uid @@ -0,0 +1 @@ +uid://by6ugjfdicgud diff --git a/game/presentation/views/camp_scene_view.gd b/game/presentation/views/camp_scene_view.gd index eb0f563b..921a7a1c 100644 --- a/game/presentation/views/camp_scene_view.gd +++ b/game/presentation/views/camp_scene_view.gd @@ -46,6 +46,7 @@ var _press_key := &"" # 当前按住命中键 var _float_tween: Tween # 悬停浮动补间(逐级整像素吸附,禁 _process 逐帧移 UI) var _desat_mat: ShaderMaterial # 禁用态共享材质(strength 恒 1,材质挂/摘承载开关) var _hud_slot: Control # 顶栏预留位(卡⑤ set_hud_band 填值) +var hud_band: Control # 顶栏 HUD 栏句柄(卡⑤ CampHudBand——装配后 bus 目标册取用面) func _init() -> void: @@ -94,6 +95,7 @@ func set_feedback_state(key: StringName, state: FeedbackState) -> void: func set_hud_band(band: Control) -> void: if _hud_slot != null: _hud_slot.add_child(band) + hud_band = band func _gui_input(event: InputEvent) -> void: diff --git a/game/presentation/views/camp_sub_view_base.gd b/game/presentation/views/camp_sub_view_base.gd index 1cc78727..20f2d152 100644 --- a/game/presentation/views/camp_sub_view_base.gd +++ b/game/presentation/views/camp_sub_view_base.gd @@ -12,12 +12,8 @@ var _balance_label: Label # 钥石徽数值行(探针直读面——ui_probe ## 壳构建(子类 _init 调用一次):content 由子类先建好传入(列容器/滚动容器皆可) func _build_shell(title: String, icon_path: String, content: Control) -> void: - # 实底暖亮档(半透 dim 会透出底下场景图——CampOverlay 同案;遮蔽语义由组合根输入锁兜底) - var dim := UiKit._modal_dim(self, UiKit.BG_BRIGHT) - var bd := UiKit.backdrop_tile() - if bd != null: - dim.add_child(bd) - dim.add_child(UiKit.vignette_rect()) + # 半透明压暗遮罩 0.6(camp.md v2.3 定稿——场景根留底可见,窗口之下垫遮罩;交互聚焦由遮罩 STOP 兜底) + var dim := UiKit._modal_dim(self, Color(UiKit.DIM, 0.6)) var margin := MarginContainer.new() margin.set_anchors_preset(Control.PRESET_FULL_RECT) margin.add_theme_constant_override("margin_left", 16) diff --git a/game/presentation/views/career_overlay.gd b/game/presentation/views/career_overlay.gd index 796935b5..c5487a1c 100644 --- a/game/presentation/views/career_overlay.gd +++ b/game/presentation/views/career_overlay.gd @@ -18,6 +18,7 @@ var _keystone_badge: UiKit.KeystoneBadge # 钥石余额(badge 工厂件— func _init() -> void: # 全屏页壳(T6/T7 对齐批先例——暖亮底+石纹弱质感+暗角+56px 通栏顶条+内容列) var page: Dictionary[Variant, Variant] = UiKit.page_shell(self, true) + page.base.color = Color(UiKit.DIM, 0.6) # 功能窗口化(camp.md v2.3 定稿——场景根留底+半透明压暗遮罩 0.6;观感随样张目检校准) var top: HBoxContainer = page.top_row top.add_child(UiKit.label("生 涯",UiKit.FS_TITLE, true, UiKit.WARM)) var top_sp := Control.new() diff --git a/game/probe/screen_flow_probe.gd b/game/probe/screen_flow_probe.gd index 1f939d5e..b2232b59 100644 --- a/game/probe/screen_flow_probe.gd +++ b/game/probe/screen_flow_probe.gd @@ -27,6 +27,7 @@ func _ready() -> void: await _step_boot_menu() await _step_menu_to_camp() await _step_camp_back_to_menu() + await _step_camp_esc_and_hud() # 卡⑤——Esc 四态路由/三出口/设置语境分支/HUD 读数 await _step_save_select_open_back() # 迭代 33 卡③ sl10——选档开合+返回路径+ESC 语境不响应 await _step_menu_to_adventure() await _step_level_to_battle_and_back() @@ -122,7 +123,9 @@ func _step_camp_back_to_menu() -> void: return main.ui.modals.camp.scene.object_pressed.emit(&"campfire") await _frames() - main.ui.modals.confirm_dialog.confirmed.emit() # 二次确认离场(回主菜单——卡④ T4) + if not main.ui.modals.confirm_dialog.visible: + _problems.append("③篝火:二次确认弹窗未现(camp.md v2.2 必须先确认)〔营地图批 V7〕") + main.ui.modals.confirm_dialog.confirmed.emit() # 二次确认离场(confirmed 先于关层——卡④ T4) await _frames() _expect_exclusive("③营地→菜单(回退)", "菜单") @@ -229,3 +232,73 @@ func _step_end_back_to_menu() -> void: _expect_exclusive("⑦终局→菜单", "菜单") if main.run_scope != null and main.run_scope.is_adventure: _problems.append("⑦终局→菜单:冒险态未收束(run_scope 仍标 is_adventure)") + + +# ---- ③' 营地 Esc 浮窗+HUD(卡⑤——真实键盘合成路径 push_input;四态路由+三出口+语境分支+余额单口)---- +func _step_camp_esc_and_hud() -> void: + ProbeUiUtil.isolate_save(main, "smoke_screen_flow_esc", false, false, true) + if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_esc"): + _problems.append("[esc] 营地入口缺失(选档层新档钮驱动中断)〔ESC批 V1〕") + return + await _frames() + _push_esc() + await _frames() + if not main.ui.modals.camp.esc_overlay.visible: + _problems.append("[esc] 营地根态 Esc 未唤起浮窗(契约 9③)〔ESC批 V1〕〔ESC批 B1〕") + _push_esc() + await _frames() + if main.ui.modals.camp.esc_overlay.visible: + _problems.append("[esc] 再按 Esc 未关浮窗(Q2 同键单义切换失守)〔ESC批 V1〕") + _push_esc(true) # echo 连发(真实键盘长按形态) + await _frames() + if main.ui.modals.camp.esc_overlay.visible: + _problems.append("[esc] echo 事件唤起浮窗(触发沿 pressed 且非 echo 失守)〔ESC批 V1〕") + main.ui.modals.camp.scene.object_pressed.emit(&"dummy") # 子界面开态 + await _frames() + _push_esc() + await _frames() + if main.ui.modals.camp.tree.visible: + _problems.append("[esc] 子界面开态 Esc 未关窗(camp.md v2.3 定稿——先关最上层窗)〔ESC批 V1〕") + if main.ui.modals.camp.esc_overlay.visible: + _problems.append("[esc] 关窗同拍唤起浮窗(先关窗后浮窗——两拍应分离)〔ESC批 V1〕") + await _frames() + # HUD 余额(契约 5 时机③——夹具直写后显式触发才变;禁 band 自刷假设) + main.meta.meta_state._add_keystone(9999) + main._camp_pres.views.refresh_bus.refresh(main._camp_data()) # 显式触发刷新单口 + var band: Control = main.ui.modals.camp.scene.get_node("HudBandSlot").get_child(0) + if not String(band._badge.value_label.text).begins_with("钥石 9999"): + _problems.append("[esc] HUD 余额读数≠存档单口现值(直写+显式触发未变)〔ESC批 V6〕〔ESC批 B2〕") + # 设置开在浮窗之上→Esc 无反馈且浮窗不误关(契约 9①);关设置回浮窗不回主菜单(契约 3 语境分支) + _push_esc() + await _frames() + main._on_esc_settings() + await _frames() + if not main.ui.modals.settings_overlay.visible: + _problems.append("[esc] 浮窗设置出口断裂〔ESC批 V4〕") + _push_esc() + await _frames() + if not main.ui.modals.camp.esc_overlay.visible: + _problems.append("[esc] 设置开态 Esc 误关浮窗(契约 9①——浮窗不隔层关闭)〔ESC批 V1〕") + main._on_settings_closed() + await _frames() + if not main.ui.modals.camp.esc_overlay.visible or main.ui.screens.start_overlay.visible: + _problems.append("[esc] 关设置后未回浮窗或回弹主菜单(契约 3 语境分支失守)〔ESC批 V4〕〔ESC批 B3〕") + # 返回主菜单动线(契约 4——浮窗自收+营地隐+选档收+菜单显) + main.ui.modals.camp.esc_overlay.return_requested.emit() + await _frames() + if main.ui.modals.camp.esc_overlay.visible or main.ui.modals.camp.scene.visible or main.ui.modals.save_select_overlay.visible or not main.ui.screens.start_overlay.visible: + _problems.append("[esc] 返回主菜单动线失守(浮窗自收/营地隐/选档收/菜单显)〔ESC批 V3〕〔ESC批 B3〕") + # 非营地语境(boot 菜单)Esc→无响应(契约 9④ 回归面) + _push_esc() + await _frames() + if main.ui.modals.camp.esc_overlay.visible: + _problems.append("[esc] 非营地语境 Esc 唤起浮窗(契约 9④ 失守)〔ESC批 V1〕") + + +func _push_esc(echo := false) -> void: + var ev := InputEventKey.new() + ev.keycode = KEY_ESCAPE + ev.physical_keycode = KEY_ESCAPE + ev.pressed = true + ev.echo = echo + main.get_viewport().push_input(ev, true) # 真实键盘合成路径(:153 先例——push_input 不更新 Input 单例动作态) diff --git a/game/probe/ui_click_probe.gd b/game/probe/ui_click_probe.gd index 309e8526..9871f175 100644 --- a/game/probe/ui_click_probe.gd +++ b/game/probe/ui_click_probe.gd @@ -88,11 +88,11 @@ func _ready() -> void: buy_btn.pressed.emit() # 合成购买点击 → _on_camp_tree_buy → meta.tree_buy(写调用唯一归组合根) await get_tree().process_frame if int(iso_c.meta_state.keystone_balance()) != bal_before - price: - _problems.append("营地树购买未出账(%d→%d 应 −%d)〔句柄子容器批 V1〕" % [bal_before, iso_c.meta_state.keystone_balance(), price]) + _problems.append("营地树购买未出账(%d→%d 应 −%d)〔句柄子容器批 V1〕〔营地图批 V4〕" % [bal_before, iso_c.meta_state.keystone_balance(), price]) var iso_chk = load("res://core/save_manager.gd").new("user://smoke_click_probe_camp_slot_1.json") iso_chk.load_from_disk() if int(iso_chk.meta_state.tree_state().nodes.get("sp_hp", 0)) != 1: - _problems.append("营地树购买未持久(reload 后级 != 1)〔句柄子容器批 V1〕") + _problems.append("营地树购买未持久(reload 后级 != 1)〔句柄子容器批 V1〕〔营地图批 V4〕") # Fork 双态切换点击路径(V20——购=解锁默认 A,钮切 B;前置=同调位 1,先点亮) var socket_btn: Button = null for card in main.ui.modals.camp.tree._tree_buy_btns: @@ -177,10 +177,10 @@ func _ready() -> void: _collect_labels_by_text(main.ui.modals.camp.codex, codex_labels) var atlas_locks := _labels_with_text(codex_labels, "结构位预留") if atlas_locks.is_empty(): - _problems.append("营地灰字:图鉴锁文 label 未找到(wc4 定位锚失守——锚随形态订正去『柜台』)〔句柄子容器批 V1〕") + _problems.append("营地灰字:图鉴锁文 label 未找到(wc4 定位锚失守——锚随形态订正去『柜台』)〔句柄子容器批 V1〕〔营地图批 V6〕") for l in atlas_locks: if l.get_theme_color("font_color") != UiKit.STONE_DEEP: - _problems.append("营地灰字:图鉴锁文未用 STONE_DEEP(wc4 :167)〔句柄子容器批 V1〕") + _problems.append("营地灰字:图鉴锁文未用 STONE_DEEP(wc4 :167)〔句柄子容器批 V1〕〔营地图批 V6〕") main.ui.modals.camp.codex.closed.emit() await get_tree().process_frame main._on_camp_closed() # 关层收闭(营地与选档层同收+开始层恢复——卡④ T3) @@ -702,7 +702,7 @@ func _ready() -> void: main.ui.modals.confirm_dialog.confirmed.emit() # 「是」→开始新冒险 await get_tree().process_frame if not main.run_scope.is_adventure or main.ui.modals.camp.scene.visible: - _problems.append("大门确认:冒险未发起或营地场景屏未隐藏〔营地图批 V3〕") + _problems.append("大门确认:冒险未发起或营地场景屏未隐藏〔营地图批 V3〕〔营地图批 B1〕") # 有断点三出口(选路停点形注入——同开场行③ set_breakpoint 先例) main.save_manager.set_breakpoint({ "master_seed": 42, "rng_counter": 0, "hero_hp": 30, "gp": 10, "keystone": 0, diff --git a/game/probe/ui_struct_probe.gd b/game/probe/ui_struct_probe.gd index bf485e30..aa2e73e4 100644 --- a/game/probe/ui_struct_probe.gd +++ b/game/probe/ui_struct_probe.gd @@ -104,6 +104,51 @@ func _ready() -> void: _settle() if main.ui.modals.career_overlay.visible or main.ui.screens.start_overlay.visible: problems.append("[career] 关闭后页未隐藏或开始层回弹(营地语境分支失守)〔营地图批 V5〕") + # ---- Esc 浮窗结构段(卡⑤——三钮在位且仅三+零动效契约+登记序在册+debug_badge 不波及)---- + main._camp_pres.open_camp() + _settle() + main.ui.modals.camp.scene.object_pressed.emit(&"gate") + _settle() + main.ui.modals.confirm_dialog.cancelled.emit() # 关大门弹窗(清场——浮窗段前提) + _settle() + var push_esc := func() -> void: + var ev := InputEventKey.new() + ev.keycode = KEY_ESCAPE + ev.physical_keycode = KEY_ESCAPE + ev.pressed = true + main.get_viewport().push_input(ev, true) + push_esc.call() + _settle() + if not main.ui.modals.camp.esc_overlay.visible: + problems.append("[esc] 浮窗未唤起(结构段前提——营地语境 Esc 路由)〔ESC批 V1〕") + var esc_btns := _buttons(main.ui.modals.camp.esc_overlay).size() + if esc_btns != 3: + problems.append("[esc] 浮窗三钮在位且仅三(实得 %d——禁第四钮)〔ESC批 V2〕" % esc_btns) + var esc_static := FileAccess.get_file_as_string("res://presentation/views/camp_esc_overlay.gd") + FileAccess.get_file_as_string("res://presentation/main_esc_flow.gd") + if esc_static.contains("create_tween") or esc_static.contains("UiKit.motion"): + problems.append("[esc] 浮窗双件源码存在动效令牌(契约 6 零动效——直开直关)〔ESC批 V7〕") + var esc_anim := _count_animplayers(main.ui.modals.camp.esc_overlay) + if esc_anim != 0: + problems.append("[esc] 浮窗子树 AnimationPlayer 非零(契约 6 零动效)〔ESC批 V7〕") + var esc_src := FileAccess.get_file_as_string("res://presentation/views/camp_esc_overlay.gd") + FileAccess.get_file_as_string("res://presentation/main_esc_flow.gd") + if esc_src.is_empty(): + problems.append("[esc] 零动效扫描面为空(源文件读失败——非空前置失守)〔ESC批 V7〕") + # 退出项接线断言(卡⑤ V5——绑信号连接与调用链;headless 不可真退=静态判据+观测面局限申报) + var quit_wired := false + for c in main.ui.modals.camp.esc_overlay.quit_requested.get_connections(): + if c.callable.get_method() == "_on_esc_quit": + quit_wired = true + if not quit_wired: + problems.append("[esc] 退出钮接线断链(quit_requested 连接目标≠_on_esc_quit)〔ESC批 V5〕") + var quit_chain := FileAccess.get_file_as_string("res://presentation/main.gd") + FileAccess.get_file_as_string("res://presentation/main_esc_flow.gd") + if not quit_chain.contains("MainEscFlow._on_quit(self)") or not quit_chain.contains("root._quit_game()"): + problems.append("[esc] 退出调用链断裂(_on_esc_quit→_on_quit→_quit_game)〔ESC批 V5〕") + if main.ui.screens.debug_badge.visible: + problems.append("[esc] 浮窗开态 debug_badge 可见(发布态恒隐——float 类不注册 ModalStack 应零波及)〔ESC批 V8〕") + push_esc.call() + _settle() + if main.ui.modals.camp.esc_overlay.visible: + problems.append("[esc] 再按 Esc 未关浮窗(结构段收尾——Q2 单义切换)〔ESC批 V1〕") main._on_camp_closed() # 关营地复归菜单语境(后续选档段前提) _settle() @@ -756,3 +801,13 @@ func _start_columns_contract(main: Node) -> void: if box.get_global_rect().intersects(right.get_global_rect()): problems.append("[start][columns] 左列 %s 与右列 %s 相交(双列叠放回归——M2 缺陷闸)" % [ box.get_global_rect(), right.get_global_rect()]) + + +# AnimationPlayer 全子树收集(零动效契约扫描面——_buttons 同款递归形态) +func _count_animplayers(node: Node) -> int: + var out := 0 + if node is AnimationPlayer: + out += 1 + for child in node.get_children(): + out += _count_animplayers(child) + return out diff --git a/game/tests/README.md b/game/tests/README.md index dc273539..a6e8689a 100644 --- a/game/tests/README.md +++ b/game/tests/README.md @@ -134,6 +134,7 @@ tests/ | 地形瓦片套与格面数字可读 | HUD框架 | `TilePalette.digit_ink_mode()`/`TilePalette.normalize_floor_luma()` | `terrain_tile_sets_test.gd:_test_set_completeness`;`terrain_tile_sets_test.gd:_test_hue_domains`;`terrain_tile_sets_test.gd:_test_digit_ink_modes` | | 站桩敌人呈现与结算演出落点 | 战斗表现 | `BattleStageView.enemy_standee_center()`/`BattleEndOverlay.open_victory()` | `standee_fx_sweep_test.gd:_init`;`pacing_queue_test.gd:_init` | | 站桩呈现定值与素材绑定 | 战斗表现 | `UiKit.load_tex()`/`StandeeBody.name_line_probe()` | `standee_present_values_test.gd:_init` | +| 站桩显示档与素材分辨率绑定 | 战斗表现 | `StandeeBody.portrait_probe()`/`StandeeMotion.PORTRAIT_DISPLAY_H` | `standee_present_values_test.gd:_check_display_tier` | | B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) | HUD框架 | `BattleStageView.set_board_type()` | `stage_background_test.gd:_test_background_selection`;`stage_background_test.gd:_test_ground_layer_geometry`;`stage_background_test.gd:_test_beams_retired` | | 战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) | HUD框架 | `BoardView.set_cell_area()`(D 区可用面积 → 格边长);读面 `BoardView.cell_size` | `layout_probe.gd:_ready`;`board_gen_reward_test.gd:_smoke_layout_cell_formula` | | 调参测速批量模拟(逐帧步进与统计读数) | 调参测量 | `TuneSimController.run()`(调试浮窗批量模拟入口) | `tune_sim_batch_parity_test.gd:_init`(配对对拍套件,随测速循环批建) | @@ -162,6 +163,7 @@ tests/ | 难度修饰套乘:空表零行为/套乘生效/越域 clamp | 难度曲线与Boss | `UnitContainer.spawn()`/`ConfigDbResolver.resolve_difficulty_modifiers()` | `table_structure_guard_test.gd:_smoke_difficulty_table`;`config_db_resolver_test.gd:_test_difficulty_clamp` | | 锻造表 schema 正反与几何价格梯 | 锻造工坊 | `ForgeTable.level_price()`/`ForgeTable.route_rows()` | `forge_table_test.gd:_test_production_rows`;`forge_table_test.gd:_test_price_ladder`;`forge_table_test.gd:_test_negative_cases` | | 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理 | 战斗结算×数据配置×增益状态 | `DamageController.open_ticket()`/`StatusContainer.apply_effect()` | `system_contracts_test.gd:_test_damage_controller_vocabularies`;`system_contracts_test.gd:_test_rng_tag_closure`;`system_contracts_test.gd:_test_status_boolean_acceptance` | +| 同名状态合并策略(叠加/累加/并存)与剩余次数语义 | 战斗循环×增益状态 | `StatusContainer.apply_effect()`(编排宿主 begin_battle 链) | `roll_multiplier_test.gd:_smoke_armor_roll` | | 敌人技能池跨表链接校验 | 数据配置×敌人系统 | `ConfigDbCrossValidator.validate_skill_pool_links()` | `config_db_cross_validator_test.gd:_test_all_links_valid`;`config_db_cross_validator_test.gd:_test_dangling_skill_id`;`config_db_cross_validator_test.gd:_test_cast_side_mismatch` | **覆盖域表**(`design/gdd/systems/` 逐篇对照——状态三档:已覆盖/部分覆盖/未覆盖;部分与未覆盖行的缺口指待办清单条目,覆盖面提升时同批改本表): @@ -174,9 +176,9 @@ tests/ | 冒险循环 | 奇物.md | 专长(奇物)授予与凭证保底;奖励三选一候选/刷新付费/呈现 | 已覆盖 | — | | 冒险循环 | 难度曲线与Boss.md | Boss 半血解锁技门控;行集寻址、行序保序与难度乘数 clamp;难度修饰套乘:空表零行为/套乘生效/越域 clamp | 部分覆盖 | 难度曲线整链与 Boss 出场门控无专项断言;见待办清单「能力清单覆盖缺口补齐」条 | | 战斗循环 | 地图战斗资源.md | 清图奖励双份与零路径;GP 钱包/escrow/商店收口/共享池;封印与极性路由/不可逆 | 已覆盖 | — | -| 战斗循环 | 增益状态.md | 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理;封印与极性路由/不可逆 | 部分覆盖 | 增益叠层/衰减/清除结算链无断言;见待办清单「能力清单覆盖缺口补齐」条 | +| 战斗循环 | 增益状态.md | 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理;同名状态合并策略(叠加/累加/并存)与剩余次数语义;封印与极性路由/不可逆 | 部分覆盖 | 增益叠层/衰减/清除结算链无断言;见待办清单「能力清单覆盖缺口补齐」条 | | 战斗循环 | 战斗结算.md | 伤害公式与掷点乘区;伤害单据编排与回放;轮内流与结算五段全序 | 已覆盖 | — | -| 战斗循环 | 战斗表现.md | 站桩敌人呈现与结算演出落点;站桩呈现定值与素材绑定 | 部分覆盖 | 死亡灰化与减动效演出档仅探针与人工目检;见待办清单「能力清单覆盖缺口补齐」条 | +| 战斗循环 | 战斗表现.md | 站桩敌人呈现与结算演出落点;站桩呈现定值与素材绑定;站桩显示档与素材分辨率绑定 | 部分覆盖 | 死亡灰化与减动效演出档仅探针与人工目检;见待办清单「能力清单覆盖缺口补齐」条 | | 战斗循环 | 敌人系统.md | 技能池数据面与回放独立;Boss 半血解锁技门控;敌人技能池跨表链接校验 | 已覆盖 | — | | 排雷循环 | 地形变异.md | 变异布置门控;表结构守卫:域校验/行序键/跨字段互锁/配额锚 | 已覆盖 | — | | 排雷循环 | 排雷玩法.md | 装板与开局免费展开(封锁格无资源、计入清图);挖/封印合法性与可辨拒绝(拒绝零副作用);封印不可逆与挖开封印格放行(兑付改判四情况) | 已覆盖 | — | diff --git a/reports/iter47-反哺点-2026-11-01.md b/reports/iter47-反哺点-2026-11-01.md new file mode 100644 index 00000000..c2152102 --- /dev/null +++ b/reports/iter47-反哺点-2026-11-01.md @@ -0,0 +1,19 @@ +# 迭代 47 反哺点清单(实现批未写 design/ 与根规则文件——逐条待用户裁决后由文档批落文) + +- 接收方:待办清单「营地交互重做·五张需求卡片」条目(裁决后逐条清掉)+各 owner 文档 +- 依据:卡⑥/卡④/卡⑤ §5 关联文档同步面全表义务格=反哺点·列清单 + +| # | 文档 | 位置 | 原句/现状 | 拟改 | 依据 | +|---|---|---|---|---|---| +| 1 | architecture.md | 呈现层模块清单/测试与质量域 | 无 UiCampModals/四子界面/CampRefreshBus/MainEscFlow/CampHudBand/CampSceneView 六新件行 | 增六件归属行(呈现层/组合根拆件)+LAYER_CONTRACT 槽变化(camp_overlay→camp_scene+四子界面+camp_esc_overlay)+产品码首个键盘输入入口(main._unhandled_input 契约 9 接线)注记 | 卡⑥/④/⑤ 落地实况 | +| 2 | camp.md | §顶栏 :39-41 / §叠层与开合 :43-45 | 「刷新入口=营地刷新单口(卡⑤同口挂接)」未记实装;承载形态「归卡④ §9 代拍板域,本 spec 不预设值」 | 回填实装状态(单口=CampRefreshBus 已挂/时机清单三条)+承载形态=单一内页切换(场景根留底)拍板值落文 | 卡④ T2/T3+卡⑤ 实装 | +| 3 | art-bible.md | §6.2 :393 围墙细条句 / §4.1 场景环境子板 | 「围墙层落盘按细条 (0,240,1280,70) 裁」;环境子板色值待登记 | 细条句补实装值 (0,261,1280,49)(Y 压缩桩身 43 锁定值精确,备选 A′ 在档);登记营地 32 色主色板(色值清单=artwork/2026-11-01-营地终稿后处理/换算式登记.txt,两道门合规零违例对) | 卡④ T1 实测+§0.3-3⑤ | +| 4 | camp-scene-prompts.md | §2.3 坐标表 / §4 验收 | 贴图矩形=规划值(130×140 等);单张 ≤32 量化后 | 八物件 contain 实测尺寸表(board 130×121 等——呈报备案追认值)+量化实况注记 | 卡④ T1 换算式登记 | +| 5 | 生涯.md | :72 营地行(P6 条带去向) | 「营地条带的去留是本提纲必答项——见 §五 P6」 | P6 注销(Q4=甲:条带随四柜台拆解撤下,逐局历史回看归生涯——本批已撤) | 卡④ Q4 裁定落地 | +| 6 | 08-Alpha版本标准.md | :193 「键盘 / 手柄输入(排 Beta)」 | Beta 行未注记 Esc 已落地 | 行内加注「例外:营地语境 Esc 浮窗已落地(用户明示裁决,澄清⑤裁决 9;键盘面仍排 Beta——本批只落 Esc 一项)」 | 卡⑤ 契约 2/9 | +| 7 | 待办清单.md | 营地交互重做条+UI 贴图重构条+图鉴挂起 | 条目状态「已编迭代 47」;贴图重构条对象注记;图鉴挂起 | 状态推进(完成即整条删除)+实况换代(三卡收口凭据);贴图重构条「四柜台对象变化」注记更新(柜台形态已退役);图鉴挂起条入口改挂注记 | 三卡实装 | +| 8 | 体验验证清单.md | 新增目检条 | — | 登记 §实现报告 §6 五条(场景观感/点选反馈/大门篝火/Esc HUD/四子界面)——登记不阻塞 | 卡④ V11+卡⑤ V9 | +| 9 | roadmap.md | 迭代 47 行+当前位 | 状态「待开工」 | 行换代(三卡实现报告列+状态)+当前位三行换代 | 迭代收口 | +| 10 | shot_checker 色数判据 | tools/shot_checker.py A 段 | camp 屏唯一色数 ≥64 | L3 呈报在案(读法 A/B 待裁)——裁决后判据修正随批+待办清单登记条 | 停机呈报 2026-11-01 | +| 11 | asset-path-map.md §3 / art-assets-checklist.md §3.5 | 营地 10 张路径行 | 登记超前注记 | 实装入库确认(scene_camp_* 十件在役+TEX_CAMP_* 十键消费)+终稿置换待用户游戏内终审注记 | 卡④ T1 | +| 12 | ui_kit CAMP_HEADER_BAND 令牌 | ui_kit.gd :178 邻域+ui_contrast 表 | 令牌在役(营地域柜台头带消费随形态退役) | 令牌退役评估(消费面仅剩 keystone_badge 工厂与关卡屏/商店——营地域测点对已注销;随令牌批处置,非本批强删;审计记档 2 订正) | 卡④ T5 核签+审计记档 | diff --git a/reports/iter47-实现报告-2026-11-01.md b/reports/iter47-实现报告-2026-11-01.md new file mode 100644 index 00000000..57aa6e59 --- /dev/null +++ b/reports/iter47-实现报告-2026-11-01.md @@ -0,0 +1,126 @@ +# 迭代 47 实现报告(卡⑥ 营地模态句柄子容器批+卡④ 营地场景图新建批+卡⑤ Esc 浮窗与营地顶栏批) + +- 接收方:roadmap.md 迭代 47 行(实现报告列)+待办清单「营地交互重做·五张需求卡片」条目 +- 性质:代码实现批产出物(实现批唯一可写目录=reports/;design/ 与根规则文件零写入——反哺点清单另立) +- 分支:iter47(worktree g-plan2-iter47)· 基线 5ad72f44 · 收口提交史见 §9 + +## 1. 各卡状态 + +| 卡 | 状态 | 提交 | 出口验证 | +|---|---|---|---| +| 卡⑥ 句柄子容器批 | 收口 | 3a9c6ff4 | --code 全套闸 all_green;V1/V2/V3 留痕齐 | +| 卡④ 营地场景图批 | 施工完成(T6 出口闸等 shot_checker 裁决重跑) | aa4aa1dd/4b5e3f27/98470adc/5a0e7069/1243ffe6/52296872 | 七探针+system_test 全绿;V14 11 项绿;--code 闸 01-04/09/10 绿、05 渲染闸红=L3 呈报在案 | +| 卡⑤ Esc 浮窗与顶栏批 | 施工完成(T4 出口闸同上) | 4e4232d8 | 冒烟 PASS+system_test 69/0+七探针全绿 | + +## 2. 卡⑥ 实际改动—验收对照表(尾缀〔句柄子容器批 Vn〕) + +| 需求点 | 改动 | 验收测试 | 层级 | 真实入口 | 判据绑定面 | 结果 | +|---|---|---|---|---|---|---| +| V1 句柄迁移零行为漂移 | ui_camp_modals.gd 新件;ui_modals 持 camp 删平铺;main_ui_build 装配 10 处;改指面 8 文件 43 处 | 五探针营地段+system_test V1c:94-106+句柄同一性链 :108 | 探针+系统 | 现役营地断言逐件复跑(断言零改寻址新) | 全段绿=零漂移;全仓 grep 零 modals.camp.overlay 残留 | 绿(V1 尾缀 34 处 grep 在位) | +| V2 层序合同零漂移 | ui_registry node() 返回链改写(key 平铺不改名) | system_test V1c 合同树序链 | 系统 | LAYER_CONTRACT 单一事实源 | 树序链绿=合同落位零漂移 | 绿(V2 尾缀 :106 在位) | +| V3 S13 读数 | ui_modals 类变量 14→14 | gdstyle gate+grep -c '^var ' 计数 | 静态 | static_scan.sh | gate 绿零 NEW+计数=14 留痕(观测面局限:闸对 14/15 同零命中,人工计数承载) | 绿(143 件零 NEW;计数 14) | + +## 3. 卡④ 实际改动—验收对照表(尾缀〔营地图批 Vn/Bn〕) + +| 需求点 | 改动 | 验收测试 | 层级 | 真实入口 | 判据绑定面 | 结果 | +|---|---|---|---|---|---|---| +| V1 场景图形态 | camp_scene_view 10 层铺底+layout.tres+camp_screen 改挂 | shot_probe camp 段(截图=场景图)+ui_struct 场景层序段+shot_checker 结构段 | 探针 | 进存档→选档→进档→营地场景屏 | 截图实拍=场景图形态(十层合成/门洞透路/七物件就位);子节点序=表 z 序逐层;贴图矩形逐值 | 绿(截图目检+层序段 11 层断言) | +| V2 七物件可达+叠层退避 | 七命中区+object_pressed+组合根路由 | ui_probe/ui_click/ui_struct 场景点选段 | 探针 | 命中区→_gui_input→object_pressed→路由 | 锻炉/宝箱/木桩/布告板/笔记本/篝火/大门逐一 object_pressed 驱动可见性 | 绿(七件路由断言分散六探针全绿) | +| V3 大门两分支+开局收闭 | confirm_dialog 三钮化+消费方编排扩展+main_overlay_flow 路由 | ui_click 大门两分支段 | 探针 | 场景点选 gate→确认弹窗→分派 | 点大门不直接进冒险(is_adventure 翻转只在 confirmed 后);cancelled 写口零调用+营地根 visible;开局后营地隐藏 | 绿(无断点两出口+有断点三出口 set_breakpoint 注入全过) | +| V4 五界面功能+写口零回归 | 四 view 抽出+presenter 承接面+bus 单口 | forge_workbench_test(承载类同迁断言零改)+ui_click 购买链 | 单元+探针 | 意图信号→presenter→MetaProgression 写口 | 树购买出账+持久(reload 后级=1)/Fork 持久/锻造三意图——全链复跑绿 | 绿(12 项+点击链 0 问题) | +| V5 生涯只读契约 | career 入口改挂笔记本(本体零改) | ui_struct career 段(笔记本真实路由) | 探针 | 笔记本命中→object_pressed→_open_career | 生涯页可达+三契约不破+营地语境关生涯不回开始层 | 绿 | +| V6 图鉴挂起态 | codex_view 占位壳 | ui_click 灰字段(锚=结构位预留) | 探针 | 布告板命中→codex 开 | 占位锁文锚定+零激活禁行+非禁用态 | 绿 | +| V7 篝火动线 | 路由 campfire→二次确认→on_camp_closed | screen_flow 回退段+ui_click? | 探针 | 篝火命中(只下半)→确认→主菜单 | 二次确认 confirmed 先于关层;确认后营地+选档同收+菜单显 | 绿(screen_flow ③步+T4 孤检) | +| V8 顶栏位+刷新单口 | set_hud_band 预留位+camp_refresh_bus 新件 | ui_struct 顶栏位段+卡⑤ HUD 段 | 探针 | 写口尾→bus.refresh→现开界面+HUD | 顶栏位 48px 在座;写口尾一闸刷新(八尾改路由) | 绿 | +| V9 反参照纪律 | 场景根态零按钮 | ui_struct 反参照段 | 探针 | 场景根子树 Button 计数 | 根态零文字按钮(禁文字按钮列表形态) | 绿 | +| V10 美术约束 | shot_checker camp 骨架段+素材二器 | ui_contrast 令牌表+palette_check 读数 | 机检 | camp 截图+素材文件 | 见 §7 遗留读数义务(A 段色数判据=L3 呈报在案) | 部分(令牌 36 对绿;A 段红待裁) | +| V11 目检登记 | 实机目检总清单 | 件核对(§6) | 目检 | 用户实机 | 登记即义务了结(不阻塞) | 已登记(§6) | +| V12 探针迁移留痕 | F8 全量位点 | 件核对(本表+§8 迁移留痕) | 件核对 | 探针 diff 对账 | 逐点改前→改后 | 绿(§8) | +| V13 反哺点清单 | §5 同步面 | 件核对 | 件核对 | 反哺点文档逐条 | 每条有落点 | 绿(反哺点文档) | +| V14 layout 数据件校验 | schema validate+fail-fast 钩子 | camp_scene_layout_test.gd:_test_layout_hotspot_geometry(manifest 登记) | 单元 | 单测载入 .tres+ConfigDB 装载链 | 校验通过+七命中区几何红线+关系谓词零坐标字面量 | 绿(11 项) | +| B1 组合根接线总改造 | main.gd 路由/三钮编排/篝火/收闭+bus | ui_click 大门段+screen_flow 篝火段 | 集成 | 确认分派/_resume/_start/bus.refresh | 三钮消费方编排 open 前设后分派;cancelled 零写口;篝火确认离场 | 绿 | +| B2 CampOverlay 退役+四界面抽出 | overlay 删除+四 view+五句柄子容器 | forge_workbench_test+全仓件核 | 集成 | 五界面 open/close→模态栈单口 | 旧件零残留(件核一);承载类同迁断言零改 | 绿 | + +## 4. 卡⑤ 实际改动—验收对照表(尾缀〔ESC批 Vn/Bn〕) + +| 需求点 | 改动 | 验收测试 | 层级 | 真实入口 | 判据绑定面 | 结果 | +|---|---|---|---|---|---|---| +| V1 Esc 唤起四态 | camp_esc_overlay+main_esc_flow+main._unhandled_input | screen_flow Esc 步 | 探针 | push_input 合成 Esc(真实键盘路径) | 根态唤起/再按关窗/echo 零响应/子界面无反馈/设置开态不误关/菜单语境不唤起 | 绿(10 项) | +| V2 浮窗三项 | setup_buttons 三钮 | ui_struct 浮窗段 | 探针 | 浮窗视图实例化 | 三钮在位且仅三(_buttons 递归计数) | 绿 | +| V3 返回主菜单 | _on_return_to_menu(首步 close 浮窗) | screen_flow 返回动线段 | 探针 | return_requested→动线 | 浮窗自收+营地隐+选档收+菜单显(四可见性) | 绿 | +| V4 设置双路径 | _on_settings+语境分支 | screen_flow 设置段 | 探针 | settings_requested→open→closed | 设置开浮窗恒 visible(树序遮挡非属性隐藏);关后回浮窗不回主菜单 | 绿 | +| V5 退出项 | _on_quit→_quit_game 复用 | 连接链断言(main_ui_build 接线在位) | 静态 | quit_requested→_on_esc_quit→_quit_game | headless 不可真退=静态判据+观测面局限申报(本表) | 绿(接线段随装配绿证) | +| V6 HUD 余额 | camp_hud_band+bus 挂册+进档尾刷新 | screen_flow HUD 段 | 探针 | 隔离档直写 _add_keystone(9999)→显式触发 bus.refresh | badge 文本=「钥石 9999」(单口现值,显式触发才变) | 绿 | +| V7 零动效 | 直开直关 | ui_struct 浮窗段 | 探针 | 双件源码+子树扫描 | 零动效令牌+AnimPlayer=0(扫描面>0 非空前置) | 绿 | +| V8 层序与遮挡 | contract 第六槽+node() | system_test V1c 复跑+ui_struct badge 段 | 系统+探针 | 合同表单一事实源 | 树序链含新槽逐对保序;badge 零波及 | 绿 | +| V9 目检登记 | 实机目检总清单 | 件核对(§6) | 目检 | 用户实机 | 登记即义务了结 | 已登记(§6) | +| V10 反哺点清单 | §5 同步面 | 件核对 | 件核对 | 反哺点文档 | 每条有落点 | 绿 | +| B1 Esc 接线与浮窗 | 输入入口/薄委托/视图/新槽 | screen_flow+ui_struct | 集成 | 合成 Esc→路由→flow.open/close | 四态路由绑现开集合与调用记录(ui_struct 大门段 confirm_dialog._secondary_btn 直查申报:三钮化即被测改动本体、两/三出口形态唯一直观观测面、无公开访问器——审计 ⚠️ 项补注) | 绿 | +| B2 HUD 落位与刷新 | band 新建/set_hud_band/bus 挂册 | screen_flow HUD 段+ui_struct 顶栏段 | 集成 | bus.refresh→band.refresh_camp→badge | badge=单口取值;顶栏位结构在座 | 绿 | +| B3 设置语境分支与三出口 | _on_settings_closed 分支+三出口动线 | screen_flow 设置段+返回段 | 集成 | 三钮 pressed→MainEscFlow | 关设置回浮窗禁弹主菜单(反向断言);退出连接链 | 绿 | + +## 5. 实现决定记录(代拍板追认单——随 commit 留痕汇总) + +1. **承载形态=单一内页切换(场景根留底)**(卡④ §9-2 域内):模态栈 open 只隐上方登记层(modal_stack.gd:27 实测),四子界面登记于场景根之上且实底遮挡——双开互斥靠遮挡天然成立;V2 断言按留底派生(子界面开=场景根 visible 保持)。 +2. **围墙层处理路线 A″**(用户裁 A 后处理实现):去底(边界泛洪+奶油描边屏障 BG_TOL=50)→门洞手术(门柱内移+克隆桩列,缺口 675→480 源=240 终稿精确)→Y 轴压缩(桩身 609→86 源=43 终稿锁定值精确,整带 692→98 落盘 (0,261,1280,49) 底锚 y310);备选 A′(带高 70/桩身 62)存档 artwork 同目录。竖向克隆接缝 3× 放大可辨、1× 游戏尺度不可辨(申报)。 +3. **八物件 contain 落位尺寸**(呈报备案追认):board 130×121/gate 240×211/dummy 120×180/forge 240×193/tent 251×170/chest 106×90/notebook 100×66/campfire 160×149(锁定矩形 contain,命中矩形按锁定值);贴图锚定=底中心(帐篷/锻炉/宝箱/篝火/笔记本)+顶锚(门扇悬挂/布告板挂墙)。 +4. **营地主色板 32 色**(§4.1 场景环境子板两道门合规):各层独立量化→并集 272→最近对合并 120 轮→32 色零违例对;十层按终版色板重量化回写。色值清单=换算式登记.txt,登记 art-bible §4.1 走反哺点。 +5. **codex 锁文称谓订正**(L2):「柜台结构位预留」→「结构位预留」(零新文案——『柜台』随形态退役)。 +6. **set_close_path 未落独立方法**(L2 API 面):Q2 关闭路径=组合根 Esc 路由直呼 flow.close(浮窗),视图无自关通路——卡面「关闭由组合根路由」直译;bind_signals 承载三钮意图外发。 +7. **契约 9 分支序实证修正**:①先于②(设置开在浮窗之上态先命中无反馈)——首装②先被 screen_flow Esc 段实机场景证伪(2 红),按卡面编号归位后全绿。 +8. **CampSceneView 初始隐**:_init visible=false(登记模态初始隐——boot 态场景根盖菜单三红同源修复)。 +9. **ui_modals 头注/迁移面**:卡⑥ 头注换代(十二平铺+营地域子容器)✓;ui_struct 层序注释换代(camp_scene 代言)✓。 +10. **卡④ T0 预算预案兑现**:main.gd 15/15 恰贴上限——T3/T4/T5 实现零新增成员(路由走 MainOverlayFlow 静态件+薄委托)✓。 +11. **camp.md v2.3 定稿换代吸收**(2026-11-01 用户裁,后于卡面):①承载形态=五功能窗口·场景根留底+半透明压暗遮罩 0.6(实现初版实底屏——按定稿换装,四子界面壳+生涯页基底同批换);②Esc 有功能窗开着→先关最上层窗(覆盖卡⑤ 契约 9① 的 Q1 甲「子界面开态无反馈」——MainEscFlow ①分支改写,_other_modal_open 退役);③五窗互斥单开(遮罩 STOP 挡场景点击自然成立,零代码)。设置开在浮窗之上仍无反馈(契约 3 保留)。 + +## 6. 实机目检总清单(登记不阻塞——体验验证清单入册条目由文档批落) + +1. 营地场景观感:十层构图/围墙门洞/纵深(V11——纵深稿「中景 2/3」可辨性)。 +2. 七物件辨识与点选反馈:悬停轮廓+浮动+名牌/按下位移/锻炉宝箱禁用态(未解锁档)。 +3. 大门两分支弹窗(三出口文案与位次)+篝火二次确认动线。 +4. Esc 浮窗三动线+HUD 余额观感+浮窗视觉面(卡⑤ V9)。 +5. 四子界面视觉(米板身壳/行板/返回钮位次)。 + +## 7. 遗留读数义务 + +1. **shot_checker A 段色数判据互斥**=L3 呈报在案(reports/停机呈报-shotchecker色数判据互斥-2026-11-01.md)——读法 A/B 待裁;裁决后判据修正随批+闸重跑追绿。 +2. palette_check 读数(V10 素材级):15 张 0 红灯 0 新增色(只读模式)——48 令牌 baseline 目录在库缺位,双门机检化=工程批事项(反哺点登记)。 +3. 用户在游戏内终审十层素材(2026-10-31 裁定预留)——终稿置换(若有)走反哺点。 + +## 8. 探针迁移留痕表(V12——F8 全量位点改前→改后) + +| 位点 | 改前 | 改后 | +|---|---|---| +| screen_flow :54 营地旗标 | modals.camp.overlay | modals.camp.scene | +| screen_flow 回退段 :119-125 | overlay.closed.emit()+手动关选档 | 篝火动线(object_pressed campfire+confirmed) | +| screen_flow Esc 段(新增) | —(选档语境零响应段保留) | 十断言步 _step_camp_esc_and_hud | +| ui_probe 营地段 :26-57 | overlay 余额/树钮/秘宝行 | 场景点选路由→tree/treasure 视图成员 | +| ui_click 营地段 :60-250 | overlay 树链/灰字六源位 | 树链 tree view+灰字分扫 treasure/codex(锚去『柜台』)+savesel 三处场景根 | +| ui_click 断点段(卡② 移交) | lvbtn 驱动(已随卡② 撤) | 大门两分支断言段(V3 落位——无断点/有断点 set_breakpoint 注入) | +| ui_struct :45 audit | audit("camp",[overlay]) | audit("camp",[camp.scene]) | +| ui_struct 源扫描 :48-50 | camp_overlay_view.gd 单件 | 营地域六件合计(场景根+四子界面+公共壳) | +| ui_struct 生涯段 :54-69 | 函数直调 _open_career | 笔记本真实路由(open_camp 重入+object_pressed notebook+营地语境分支断言) | +| ui_struct 场景段(新增) | — | 层序/矩形逐值+锻炉可达+顶栏位+反参照+Esc 浮窗段 | +| ui_contrast 令牌表 :48-55 | 头带两行+铭牌副题+最近冒险 | 四行随形态注销(CAMP_HEADER_BAND 零消费随退);ROW_PLATE/PANEL_DATA 行保留 | +| shot_probe :120-135 | 关闭营地钮收闭 | 截图=场景图+篝火动线收闭 | +| system_test V2/:108/:121 | camp_overlay 成员/句柄 | camp_scene 三处机械随迁(T3) | +| system_test V3g camp 分支 | overlay 开合 | 场景根开合自适配(on_camp_closed 关层收闭) | +| forge_workbench_test :33 | 直载 camp_overlay_view+._forge._X | 直载 forge_view+扁平成员(断言零改 12 项绿) | +| theme_projection :711-716/:801-810 | 等高源码断言+最近冒险投影 | 注销(卡面削弱申报授权——旧形态断言失去对象/条带 Q4 甲撤下) | + +## 9. 提交史与闸况 + +3a9c6ff4 卡⑥T1 → aa4aa1dd 卡④T1 进度 → 4b5e3f27 卡④T2 → 98470adc 卡④T3 → 5a0e7069 卡④T4 → 1243ffe6 卡④T5 → 52296872 卡④T5 补 → 4e4232d8 卡⑤T1-T3。 +闸况:卡⑥ 出口 --code all_green(3a9c6ff4 对齐);卡④ T6 出口闸 01-04/09/10 绿、05 渲染闸红=shot_checker 判据互斥(L3 呈报在案——合回前重跑)。 + +## 10. 独立验收审计结论 + +独立审计报告=reports/iter47-验收审计-2026-11-01.md(未参与实现子代理执行;六条自跑抽查全绿:system_test 69/0、V14 11 项、forge_workbench 12 项、screen_flow 含 Esc 段、static_scan S13 零新增、ui_contrast 36 对)。 + +- 审计算术:对照表 42 行全查(✅33/⚠️8/❌1);判据绑定面重点四项全过;测试削弱=授权 6 件在案、未授权零;直查例外 5 处全有据(1 处补注记)。 +- 缺漏处置回执(实现方,审计处方最窄单元): + 1. 卡⑤ V5 退出项断言缺位→ui_struct Esc 段补静态接线断言(quit_requested 连接表目标=_on_esc_quit+调用链 _on_esc_quit→_on_quit→_quit_game 源扫描)+〔ESC批 V5〕尾缀——孤跑复验绿。 + 2. 尾缀覆盖缺口→V4(购买出账/持久两行)/V6(图鉴锁文两行)补〔营地图批 V4/V6〕;V7 补显式二次确认断言(screen_flow 回退段)+〔营地图批 V7〕;B1/B3 补〔ESC批 B1/B3〕、B2 补〔ESC批 B2〕;卡④ B1/B2 各补一行。V4 的 forge_workbench 部分按审计处方记豁免(断言零改申报约束——补尾缀即违零改)。 + 3. 记档项处置:V7 长度非空守卫已补一行;反哺点 #12 订正(CAMP_HEADER_BAND 消费面仅剩 keystone_badge 工厂等);V9 扫面注记(直接子层非递归——本段更正);confirm_dialog._secondary_btn 直查补申报(三钮化即被测改动本体、两/三出口形态唯一直观观测面、无公开访问器)。 +- 处置后结论:**通过**(缺漏 1 补齐+轻微尾缀补齐+记档 4 项处置;孤跑复验回执见下)。 +- 孤跑复验:ui_struct_probe 退出码 0(含 V5 新断言与 V7 守卫);screen_flow_probe 退出码 0(含 V7 显式断言与 B 尾缀段)。 diff --git a/reports/iter47-验收审计-2026-11-01.md b/reports/iter47-验收审计-2026-11-01.md new file mode 100644 index 00000000..a6257beb --- /dev/null +++ b/reports/iter47-验收审计-2026-11-01.md @@ -0,0 +1,128 @@ +# 迭代 47 独立验收审计(卡⑥ 营地模态句柄子容器批+卡④ 营地场景图新建批+卡⑤ Esc 浮窗与营地顶栏批) + +- 接收方:`reports/iter47-实现报告-2026-11-01.md` §10(独立验收审计结论回填行) +- 审计身份:未参与实现的独立审计方——只读三张需求卡、实际对照表、diff、测试件与实现报告,自跑最窄测试抽查,不采信报告「已全绿」 +- 审计对象:worktree `D:\code\g-plan2-iter47`(分支 iter47);diff 范围=基线 5ad72f44..HEAD(65b2a574),重塑后提交=469d856f 卡⑥/2ce70ac7 卡④/399ed3ad 卡⑤/65b2a574 文档收尾(原史在 backup/iter47-20261101-185917,审计只对 master..iter47 净 diff 负责) +- 审计口径:test-conventions §8.7 四件事+卡④ §7/卡⑤ §7「独立验收审计」条;对照表逐行核对(三表全行,非抽样下限)、判据绑定面重点四项、削弱逐处核对、直查例外逐行核对 +- 本审计唯一写入件=本报告(reports/);产品码/测试码零改动 + +## 1. 对照表逐行抽查(实现报告 §2/§3/§4——三表全行) + +判定标记:✅=通过(测试在役+尾缀可 grep+真实入口未绕改动点)/⚠️=通过但附注记/❌=缺漏。 + +### 1.1 卡⑥ §2(3 行全查) + +| 行 | 判定 | 依据 | +|---|---|---| +| V1 句柄迁移零行为漂移 | ✅ | 尾缀〔句柄子容器批 V1〕grep 34 处(六文件逐处);改指面实测 8 文件 43 处 `modals.camp_overlay` 删除位逐一有 `modals.camp.*` 替换行(main_ui_build 10/ui_click 16/ui_probe 8/screen_flow 3/shot_probe 2/system_test 2/ui_struct 1/ui_registry 1——与 F4 清单全等);全仓 grep `camp.overlay` 零命中(探针残留清零核实);句柄同一性链 system_test :109(camp.scene==camp_screen.camp_scene)在役且当轮跑过;ui_camp_modals 六枚实件零空占位(契约 4);camp_overlay_view.gd 整件删除零悬挂 | +| V2 层序合同零漂移 | ✅ | system_test :106 V1c 合同树序链带〔句柄子容器批 V2〕尾缀;ui_registry LAYER_CONTRACT key 平铺(camp_scene/forge_view/…/camp_esc_overlay)+node() 全部经 `modals.camp.*` 二层返回、`camp_overlay` 分支已删;ui_struct `_modal_registry_contract` 登记册逐点名含新槽 | +| V3 S13 读数 | ✅ | `grep -c '^var '` ui_modals.gd=14(审计人工复核与报告留痕一致);ui_camp_modals.gd=6;static_scan gdstyle 闸绿(基线外新违规 0)——卡面「观测面局限申报」(闸对 14/15 同零命中)如实 | + +### 1.2 卡④ §3(16 行全查) + +| 行 | 判定 | 依据 | +|---|---|---| +| V1 场景图形态 | ✅ | ui_struct :58-70 层序段(子节点序==layout 表 z 序逐层+各层贴图矩形逐值)带〔营地图批 V1〕;shot_probe camp 段截图改场景图+收闭改篝火动线(真实入口=进存档→选档→进档) | +| V2 七物件可达+叠层退避 | ⚠️ | 七件逐一驱动核实:forge(ui_struct :71-74)/dummy→tree(ui_probe)/chest→treasure(ui_probe)/notebook(ui_struct :95-98)/board→codex(ui_click :174)/gate(ui_click :688)/campfire(screen_flow :124)——驱动形态全为 `object_pressed.emit()` 信号发射(卡面 V2 判据绑定面明文「绑 object_pressed 信号发射面」,信号即视图公开提交面,合规);注记:`_gui_input` 命中判定段(topmost/press-release 同区/禁用过滤)无合成鼠标点击断言面——新件内部路径无旧断言被绕,判据按卡面钉信号面成立 | +| V3 大门两分支+开局收闭 | ✅ | ui_click :679-722 大门两分支段七断言全带〔营地图批 V3〕——真实路由(object_pressed gate→组合根分派→ConfirmDialog);无断点两出口(次钮隐藏);cancelled 恒无变更(余额读数恒等+营地根 visible+is_adventure 恒假=写口零调用);confirmed 后 is_adventure 翻转+营地隐;有断点三出口(次钮现形)+secondary_confirmed 出口 | +| V4 五界面功能+写口零回归 | ⚠️ | forge_workbench_test 承载类同迁(diff 逐 hunk 核实:仅 load 目标 camp_overlay_view→forge_view+`_forge.` 前缀扁平化,断言判据零改)实跑 12 项绿;ui_click 树购买链(出账/持久/Fork 切态持久)在役;注记:无〔营地图批 V4〕尾缀(见 §6 缺漏 2)——tree/fork 链断言带〔句柄子容器批 V1〕尾缀(卡⑥ 波先行改指所留) | +| V5 生涯只读契约 | ✅ | ui_struct :89-106 笔记本真实路由(object_pressed notebook→_open_career)+三契约(只读巡检/零动效/零跳转)复跑+营地语境关生涯不回开始层双向断言;〔营地图批 V5〕尾缀两处在位 | +| V6 图鉴挂起态 | ⚠️ | ui_click :174-183 布告板→codex 开+锁文「结构位预留」锚定+STONE_DEEP 取色——在役实跑;注记:无〔营地图批 V6〕尾缀(尾缀=〔句柄子容器批 V1〕);「零激活禁行+非禁用态」判据中非禁用态由 codex 可开承载、零激活无独立断言面(占位壳本无内容可钉——新断言绑不上属卡面「静态判据+注记申报」情形,报告未单列注记) | +| V7 篝火动线 | ⚠️ | screen_flow :117-127 回退段(object_pressed campfire→confirmed→屏级互斥复归菜单)+shot_probe 收闭改接同动线——在役实跑;注记:无〔营地图批 V7〕尾缀(=〔句柄子容器批 V1〕,同 V4 成因) | +| V8 顶栏位+刷新单口 | ✅ | ui_struct :75-77 HudBandSlot 结构断言(48px)带〔营地图批 V8〕;camp_refresh_bus 新件+presenter 八写口尾全改路由(diff 逐处核实 8 处 refresh_bus.refresh);on_camp_attune_toggle 口尾保持只刷不调 _refresh_presentations(契约 4「禁顺手统一」核实);bus 目标册=四子界面+HUD 栏(main_ui_build 装配) | +| V9 反参照纪律 | ⚠️ | ui_struct :78-83 场景根零 Button 断言带〔营地图批 V9〕;注记:扫面=get_children 直接子层非递归(报告称「子树」)——HudBandSlot 在扫面内,嵌套 Button 不计(新断言范围注记,见 §6 记档 4) | +| V10 美术约束 | ✅(如实「部分」) | ui_contrast 令牌段审计自跑绿(36 对测点全绿,与报告读数一致);A 段色数判据互斥红=L3 呈报在案(§6 记档 1)——报告「部分」判定诚实 | +| V11 目检登记 | ✅ | 实现报告 §6 五条目检清单在案(登记不阻塞) | +| V12 探针迁移留痕 | ✅ | 报告 §8 迁移表与 diff 逐位点对上(审计抽样七个位点全核实) | +| V13 反哺点清单 | ✅ | reports/iter47-反哺点-2026-11-01.md 12 条逐条有落点(注:#12 事实性偏差见 §6 记档 2) | +| V14 layout 数据件校验 | ✅ | camp_scene_layout_test.gd 11 断言实跑全绿(详见 §2);manifest 已登记 run_all.gd(+1 行) | +| B1 组合根接线总改造 | ⚠️ | main.gd/main_overlay_flow/confirm_dialog 三钮编排与篝火动线 diff 全核实(gate/gate_new/campfire_leave 三消费方+cancelled 零写口);判据承载=V3 断言+screen_flow 回退段;注记:无〔营地图批 B1〕尾缀 | +| B2 CampOverlay 退役+四界面抽出 | ✅ | camp_overlay_view.gd 整件删除(655 行)+四 view+camp_sub_view_base 抽出、全仓零残留(S12 旧件零残留闸绿+grep 核实);承载迁移断言零改实跑绿 | + +### 1.3 卡⑤ §4(13 行全查) + +| 行 | 判定 | 依据 | +|---|---|---| +| V1 Esc 唤起四态 | ✅ | screen_flow `_step_camp_esc_and_hud` 十断言全带〔ESC批 V1〕——push_input 真实键盘合成路径(非直呼 on_esc_input)、根态唤起/再按关窗/echo 零响应/子界面开态无反馈/设置开态不误关/关设置回浮窗/boot 菜单不唤起;ui_struct Esc 结构段另证唤起与再按关窗 | +| V2 浮窗三项 | ✅ | ui_struct :124-126 `_buttons` 递归计数恰三带〔ESC批 V2〕;camp_esc_overlay 三钮+danger_button 源码核实 | +| V3 返回主菜单 | ✅ | screen_flow :284-287 return_requested 真实信号→四可见性断言(浮窗自收/营地隐/选档收/菜单显)带〔ESC批 V3〕 | +| V4 设置双路径 | ✅ | screen_flow :270-283 设置开→浮窗恒 visible(遮挡非属性隐藏)+关→回浮窗+start_overlay 恒假反向断言带〔ESC批 V4〕;语境分支谓词=camp_esc_overlay.visible(main_overlay_flow diff 核实,与契约 3 一致) | +| V5 退出项 | ❌ | **缺漏 1(详见 §6)**——卡面验收测试=「ui_struct_probe 退出钮接线结构断言〔ESC批 V5〕」,全仓 grep 零该断言;报告改称「连接链断言(main_ui_build 接线在位)/静态判据」但静态断言未落码 | +| V6 HUD 余额 | ✅ | screen_flow :263-267 隔离档直写 _add_keystone(9999)→显式触发 refresh_bus.refresh→badge 文本「钥石 9999」带〔ESC批 V6〕——单口取值+显式触发才变(契约 5 时机③) | +| V7 零动效 | ⚠️ | ui_struct :127-132 双件源码令牌扫描+子树 AnimationPlayer 计数带〔ESC批 V7〕;注记:源码扫描无长度非空守卫(报告称「扫描面>0 非空前置」名实差——见 §6 记档 3) | +| V8 层序与遮挡 | ✅ | 登记册逐点名(_modal_registry_contract)+system_test V1c 树序链含 camp_esc_overlay 新槽+badge 零波及断言带〔ESC批 V8〕;LAYER_CONTRACT 槽位=codex_view 与 settings_overlay 之间(契约 3 栈语义正解核实) | +| V9 目检登记 | ✅ | 实现报告 §6 第 4 条在案 | +| V10 反哺点清单 | ✅ | 反哺点清单 #6/#8/#1 在案有落点 | +| B1 Esc 接线与浮窗 | ⚠️ | main._unhandled_input(KEY_ESCAPE+physical+pressed 非 echo)→MainEscFlow 四态路由 diff 全核实、判据单点=登记册现开集合;判据承载=V1/V2/V7/V8 断言;注记:无〔ESC批 B1〕尾缀 | +| B2 HUD 落位与刷新 | ⚠️ | camp_hud_band 新件/set_hud_band 填值/bus 挂册 diff 全核实;判据承载=V6 断言;注记:无〔ESC批 B2〕尾缀 | +| B3 设置语境分支与三出口 | ⚠️ | main_esc_flow 三出口+main_overlay_flow 语境分支 diff 全核实;判据承载=V3/V4 断言;注记:无〔ESC批 B3〕尾缀 | + +## 2. 判据绑定面抽查(重点四项+一般项) + +| 抽查项 | 判定 | 核实内容 | +|---|---|---| +| 卡④ V14(11 断言) | ✅ | 实跑 11 项全 PASS;断言全部为表内关系谓词——两两不相交(Rect2.intersects)、不越画面/不侵顶栏(y≥hud_band_h 表字段)、篝火只取下半(命中贴贴图底且严格小于贴图)、门扇对齐 gate_gap 表字段、布告板挂围墙带(与 wall 贴图带关系谓词)、层数=10+bg/wall 占 z0/z1、ConfigDB 装载链(load_tables fail-fast 钩子+is_ready);**零坐标字面量**核实(唯一常量=七键名与层数 10,非坐标;(520,760) 等值全部取自表字段输出) | +| 卡④ V3(大门两分支段) | ✅ | 七断言从真实路由进入(object_pressed gate 信号=卡面钉定发射面);cancelled 写口零调用以「余额读数恒等+营地根 visible+is_adventure 恒假」三重可观测面钉死;confirmed 后 is_adventure 翻转+营地隐;三出口经 set_breakpoint 注入(同开场行③先例,非伪造红——注入的是前置数据非破坏断言) | +| 卡⑤ V1(Esc 步) | ✅ | push_input(ev, true) 真实键盘合成路径(不更新 Input 单例动作态——与契约 9 禁轮询互证);echo=true 合成零响应;设置开态再按 Esc 浮窗不误关(契约 9① 先于②的分支序);关设置回浮窗+禁弹主菜单反向断言;boot 菜单语境不唤起(契约 9④) | +| 卡⑥ V3(计数=14) | ✅ | 审计人工 grep 计数=14 与报告留痕一致;闸面(gdstyle 零 NEW)自跑绿;卡面观测面局限申报如实 | +| 一般:V2 七物件分布 | ✅ | 六探针分散驱动逐一核实(§1.2 V2 行) | +| 一般:卡⑤ V2/V7/V8 | ✅/⚠️ | 三钮恰三/零动效/登记序——V7 非空前置注记(§6 记档 3) | +| 加跑:ui_contrast 探针 | ✅ | 审计自跑 PASS「36 对测点全绿」——与报告 V10「令牌 36 对绿」读数一致 | + +## 3. 测试削弱核对(diff 全量删改断言逐处对卡) + +**授权项清单(卡面在案,核对通过)**: + +| # | 削弱处 | 授权依据 | 核实 | +|---|---|---|---| +| 1 | theme_projection_test 等高源码断言 3 条注销(min 高 336/SIZE_FILL×4/SHRINK_CENTER≥3) | 卡④ §7 削弱申报表行 1+F8 位点(:710-717,CampOverlay 四柜台形态退役断言失去对象) | ✅ | +| 2 | theme_projection_test `_camp_recent_projection` 最近冒险投影段注销 | 卡④ §10 Q4=甲(2026-10-18 用户裁:最近冒险条带随四柜台拆解撤下)+F13——申报表未单列成行,报告 §8 迁移表已归并申报(「卡面削弱申报授权」句);授权链=卡面用户裁定,认 | ✅(注记:申报落点在 Q4+§8,非削弱表独立行) | +| 3 | ui_contrast 四行注销(头带两行/铭牌副题/最近冒险行,43→39 对) | 卡④ §7 削弱申报表行 2「核签后段留或随注销」——核签事实:CAMP_HEADER_BAND 新营地域界面零消费(grep 核实,新界面只消费 ROW_PLATE/PANEL_DATA)、最近冒险行随 Q4 撤 | ✅ | +| 4 | ui_click 断点确认段改走大门(卡② 移交接收) | 申报表行 3 | ✅(V3 落位) | +| 5 | ui_probe 深员改指/screen_flow 营地键与回退段改指/shot_probe 收闭段改篝火/生涯段驱动改接 | 申报表行 4/5/6/7 | ✅(diff 逐处核实为改指非删除) | +| 6 | forge_workbench_test 承载类同迁 | 申报表行 8「断言零改只换承载类」 | ✅(12 项判据逐字未动,仅 `_forge.` 前缀与 load 目标) | + +**未授权项清单:零。** 全 diff 删除断言行 31 处逐条核对均有同判据替换行(探针断言计数 56 增:31 删;shot_probe 21=21、system_test 51=51、ui_contrast 结构断言 7=7、forge_workbench 12=12);无放宽阈值、无缩小在役扫描面、无真实入口换下层直调(object_pressed 信号发射面=卡面 V2 明文钉定,不属直调削弱)。卡⑤「零削弱申报」成立。 + +## 4. 内部字段直查受控例外核对 + +| 直查行 | 依据 | 判定 | +|---|---|---| +| ui_probe camp.tree._balance_label/_tree_buy_btns、camp.treasure._workshop_rows;ui_click treasure._workshop_holder | 卡④ §7 削弱申报表行 4(深员改指新界面成员——历史既有口径) | ✅ | +| screen_flow band._badge.value_label.text | 卡⑤ §7 V6 判据绑定面明文钉 value_label.text(badge 工厂约定单点) | ✅ | +| ui_click :694/:717 confirm_dialog._secondary_btn.visible | 本批新增成员(三钮化即被测改动本体)、两/三出口形态唯一直观观测面、无公开访问器 | ⚠️(对照表未注明直查理由——建议随缺漏补差补一句申报,不构成判红项) | +| main_esc_flow :31 读 flow.stack._list(产品码跨类私有读) | 卡⑤ 契约 9 判据单点=ModalStack 登记册现开集合 sanctioned 读法(ModalStack 无公开现开集合访问器;代码注记自陈) | ✅ | +| screen_flow HUD 段 main._camp_pres.views.refresh_bus 直呼 | 卡⑤ 契约 5 时机③「夹具直写后探针显式触发」授权 | ✅ | + +## 5. 自跑抽查回执(worktree 内实跑;六条全绿) + +| # | 命令 | 退出码 | 关键行 | +|---|---|---|---| +| 1 | `python tools/run_system_test.py` | 0 | 「69 项检查,0 项失败」「PASS(退出码/摘要失败数/脚本错误扫描 三闸全过)」 | +| 2 | `godot --headless --path game --script res://tests/unit/presentation/camp_scene_layout_test.gd`(V14) | 0 | 11 条 [PASS] 逐条在案+「all green (11 checks)」 | +| 3 | `godot --headless --path game --script res://tests/unit/presentation/forge_workbench_test.gd`(承载类迁移) | 0 | 12 条 [PASS]+「all green (12 checks)」——断言零改实证 | +| 4 | `godot --headless --path game res://probe/screen_flow_probe.tscn`(含 Esc 段) | 0 | 「PASS — 六步主流程+回退路径全绿」(_ready 序含 `_step_camp_esc_and_hud`,Esc 段红即 FAIL) | +| 5 | `bash game/tests/static_scan.sh`(S13 基线) | 0 | 「S13 ok」「基线外新违规 0 条,较登记值恶化 0 条」 | +| 6(加跑) | `godot --headless --path game res://probe/ui_contrast_probe.tscn` | 0 | 「PASS — 对比度 36 对测点全绿」(与报告 V10 读数一致) | + +render_gate 按审计范围禁跑(05 红=L3 呈报在案,见 §6 记档 1);MC 零跑(零数值零行为,符合卡面闸口径)。 + +## 6. 总结论 + +**不通过(限项)——缺漏 1 项+轻微缺漏 1 项+记档核对 4 项;缺漏 1 补齐并复核后可转通过。** 除下列缺漏外,三卡对照表、判据绑定面、削弱申报、直查例外、自跑抽查全部通过;无未授权测试削弱。 + +### 缺漏清单 + +1. **卡⑤ V5 退出项验收断言缺位**(对照表 ❌ 行)。卡面 §7 V5 验收测试=「ui_struct_probe.gd:_ready(退出钮接线结构断言)〔ESC批 V5〕」,判据绑定面=「钮 pressed 连接目标=_on_quit→_quit_game(绑信号连接与调用链)」;实际全仓 grep 零该断言(quit_requested/_on_esc_quit 连接链无任何落码检查),〔ESC批 V5〕尾缀零命中。报告对照表该行改称「连接链断言(main_ui_build 接线在位)」——接线代码在位属实(main_ui_build :242),但「静态判据」并未落码,「绿」的实质=装配期 connect 不报错的间接承载,不满足卡面「绑信号连接」的断言要求,对照表该行名不副实。卡面已申报 headless 不可真退的观测面局限并给出可行静态形态。**补法(最窄单元)**:ui_struct Esc 结构段加一条静态断言(如 quit_requested 连接表非空且连接目标=_on_esc_quit)+〔ESC批 V5〕尾缀,孤立验证后并套件复跑。 +2. **(轻微)尾缀覆盖缺口**。卡④ V4/V6/V7/B1/B2 与卡⑤ B1/B2/B3 无卡面 §7 规定的〔营地图批 Vn/Bn〕〔ESC批 Bn〕尾缀(grep 零命中);对应验证本体全部在役且当轮实跑(V4=forge_workbench 12 项+ui_click 购买链;V6=ui_click 灰字段;V7=screen_flow 回退段;B 行=对应 V 行断言承载),缺的是卡面「断言尾缀与卡片清单互相 grep」的对账形式。成因=卡⑥ 波先行改指保留〔句柄子容器批 V1〕尾缀+V4 受「断言零改」申报约束(补尾缀即违反零改,可申报豁免)。**补法**:V6/V7/B 行断言消息文本可在后续批补尾缀;V4 记录豁免依据即可。 + +### 记档核对项(在案事项复核,不算缺漏) + +1. **05 渲染闸红(shot_checker A 段色数判据互斥)**=L3 呈报文件在盘(reports/停机呈报-shotchecker色数判据互斥-2026-11-01.md),但该文件 git **未跟踪**(?? 状态)——合回合并不携带至 master,归档链注意;合回前须用户裁决读法 A/B+闸重跑(实现报告 §7/反哺点 #10 已登记)。 +2. **反哺点 #12 事实性偏差**:称 CAMP_HEADER_BAND「现役消费面=ui_contrast 表注销四行后零消费」——实测 keystone_badge 工厂(ui_kit.gd :629-631)在役消费、新 CampHudBand 经该工厂消费、level_map_screen/shop_overlay_view 亦有消费;令牌退役评估前提失实,文档批裁决前须订正(ui_contrast 删行授权不受影响——删的是营地域头带/铭牌/条带测点对,非令牌本身)。 +3. **卡⑤ V7 名实差**:报告称源码扫描「扫描面>0 非空前置」——ui_struct :127-129 实现无长度非空守卫(FileAccess 读失败=空串静默通过);子树扫描面在浮窗实例在座前提下非空成立。建议后续批补一行长度守卫。 +4. **卡④ V9 扫面注记**:反参照断言扫面=场景根直接子层(get_children 非递归),报告称「场景根子树」;HudBandSlot 在扫面内,嵌套 Button 不计。新立断言无削弱对象,范围注记即可。 + +### 审计范围声明 + +本审计执行上列六条最窄抽查与静态读数+全量 diff/卡面/报告逐行核对;未跑 render_gate(在案红待裁)、未跑 MC、未跑 ui_probe/ui_click/ui_struct/shot_probe 单件直跑(其营地段断言经 system_test+screen_flow_probe+ui_contrast 实跑间接覆盖,且逐行静态核实);审计过程零产品码/测试码改动。 diff --git a/reports/复核-双审-grilling与godot-master-立绘显示档批-2026-11-01.md b/reports/复核-双审-grilling与godot-master-立绘显示档批-2026-11-01.md new file mode 100644 index 00000000..f9b535d4 --- /dev/null +++ b/reports/复核-双审-grilling与godot-master-立绘显示档批-2026-11-01.md @@ -0,0 +1,50 @@ +# 双审复核 · 立绘显示档批(grilling + godot-master,2026-11-01) + +> **性质**:卡片 v1.0 的独立复核产出物(req-card 纪律「grilling 复核门」+迭代 47 双审先例)。两个未参与撰写的会话各自只读复核,本报告记发现与处置去向。 +> **被审对象**:`reports/需求卡片-立绘显示档批-2026-11-01.md` v1.0。 +> **总判**:方案本体成立(引擎语义、乙类条款、闸纪律全部咬合),卡片**改后可开工**——两条阻断均为「补执行步骤」级,不动设计。 + +--- + +## 一、阻断(两条,双审同指) + +| # | 发现 | 证据 | 处置 | +|---|---|---|---| +| B1 | **原稿输入面在实现 worktree 必然缺位,且管线对缺件静默零产出**:`artwork/` 整目录不入 git,`sync_worktree_assets.sh` 只同步 `game/assets/art`+`.import`,不同步 artwork;`pixelize_candidates.py` 缺件走 `isfile` 跳过,exit 0、零文件、零报错 | `tools/sync_worktree_assets.sh:26-34`;`tools/pixelize_candidates.py:474-478,507-508` | 卡 v1.1 T1 补「显式传主区原稿根路径」+「产物计数自证 = 9 件,不足即停」 | +| B2 | **素材落递主工作区无收口步,合回后验收有洞**:素材不入 git、worktree 合回即删;本地 CI 在主区跑,主区仍是旧 46×48 稿,只有 V16「主角源高 ≥92」会报警,敌侧「原稿分辨率落位」在册闸件 `standee_asset_check` 不在闸清单,等于无人看守 | `game/tests/run_all.gd:191`;`tools/run_all_gates.sh`(grep 无 standee_asset_check);盘上主区素材实测 | 卡 v1.1 ①V13 逐件加钉源高=原稿表值(旧降采样稿必红);②T3 补「9 件落递主区再触发 CI」收口步 | + +--- + +## 二、建议(已并入卡 v1.1) + +| # | 发现 | 出处 | 卡片处置 | +|---|---|---|---| +| S1 | 样张脚本 A4 硬锁 `PORTRAIT_SRC.size==(46,48)`,T1 换代必红;另有 `:1501` 强制 96×96 方框 mockup | `tools/render_sample_sheet_v3.py:1135-1139,1501` | 列入 F11 现状与 T3 随动步(显式解冻重校) | +| S2 | T1 未明写主角源从 `*_1x.png` 切 `*_2x.png` | `tools/pixelize_candidates.py:476,481` | T1 补独立步 | +| S3 | `PORTRAIT_DISPLAY_H.get(key, 96.0)` 兜底字面量 = 档值第二处散落,与契约 2/6 自相矛盾 | 卡 v1.0 §7.3 | 改「查表必中+键集覆盖自检」,禁静默兜底 | +| S4 | 灰矮人 126→96 是全批唯一 <0.8 档(0.76× 真降档,NEAREST 抽行约每 4 行断 1px 描边),不在已接受清单 | 双审同指 | 补进契约 5 已接受项+目检①点名(头号回退候选) | +| S5 | 关卡地图头像由 ≈1× 变 0.52× 降采样,是全消费面降级最狠一处 | `level_map_screen.gd:176-190` | §4 不做面点名+目检③专列 | +| S6 | 主角三态宽度不一(88/92/88)且 `apply_hero_state` 换纹理不重摆,态切换有约 3–6px 横跳(现行 2px 的放大版) | `standee_motion.gd:85-86` | §4 明列不做(重摆=行为改动,禁实现批顺手加)+目检清单登记 | +| S7 | T1/T3 闸件口径切换时点三处互斥(T1 说「T2 未就绪允许红」、闸件排在 T3、§15 说已提前到 T1) | 卡 v1.0 §7.2/§7.4/§15 | 统一:闸件口径改造并入 T1(素材与闸件同批),删矛盾句 | +| S8 | 注释随动面漏 `standee_motion.gd:38-39,59,65`(反向引用已不存在的「禁非整数缩放」禁令)与 `level_map_screen.gd:176` | 双审同指 | T2 补点名 | +| S9 | 「两表同值」观测面局限申报说重了:grilling 判 Godot editor 版 `FileAccess` 可读 `../tools/`,godot-master 判无稳定通路——两审相左 | 双审 §6/§O5 | 卡 v1.1 改「尝试真断言(读 `../tools/pixelize_candidates.py` 逐键对账),读不到走 L2 记录退回双端字面钉值+审计对账」,禁把争议当定论 | +| S10 | §14 所核 `gdstyle_baseline.txt` 无该测试键,且 gdstyle 扫描面只含 `game/core|data|presentation`(tests 不在面) | `tools/gdstyle_gate.py:49` | §14 改口径:测试文件不在扫描面,只核 `standee_motion.gd` 在面件 | +| S11 | 卡片头行引用待办状态「待写卡」已过时;§7 交叉引用「见 §9 行 V1–V4」应为 §8 | 卡 v1.0 | 就地修正 | + +## 三、观察(不改卡,记录在案) + +- **几何实测**:立绘落位只在换纹理拍执行、按缺省盒高 96 算——大档顶 y=−2、中档 20、小档 44;溢出 2px < VBox 间距 4px,**恒不碰顶部轮次指示**(卡 L3#3 的「碰邻位」实际难触发,仍留作停机条款);立绘链上无 ClipControl,不被裁;意图徽标 y=86 在中/大档为「压胸」,符合圣经③;大档脚底越盒底由明细带面板遮住(现行卓尔/石君王已如此,本批食人魔加深 40px)。 +- **1920 档**:三档是 1280 基准壳坐标绝对高,`stretch=canvas_items`+aspect keep 下整壳 ×1.35 等比,构图恒等,无需新条款。附带发现:`project.godot` 未显式声明 `window/stretch/aspect`,依赖引擎缺省——**与本批无关,建议另立工程批钉死**。 +- **未登记 enemy_id**(如 hobgoblin 缺口行)无立绘 → `load_tex` 返回 null → 字形回退,不进 `_place_portrait`,显示档不涉,非待裁点。 +- **素材侧健康度**:九件原稿色数 30–32、alpha 二值、底缘不透明、敌侧暖白描边 68.4–98.9%(阈值 40% 全过)——T3「其余四断言不变」可保绿。 +- **事实核对**:F1–F15 逐条复核通过(F3 的 :197 实为 :198、F10 断言②止于 :100,属微差);F7 降采样等值由 grilling 独立重跑四件字节级复现。 +- **浮点判据**:0.99/1.57 档回程有 ULP 级残差,V13/V15 须 `is_equal_approx`,禁裸 `==`。 + +--- + +## 四、呈用户裁决项(卡片不动,等发令) + +1. **是否把 `standee_asset_check` 编进代码域闸**(`run_all_gates.sh` 闸件增减属工程改动,另批走)。 +2. **灰矮人 0.76× 与关卡地图头像 0.52× 两处降采样**:本卡按「已接受+目检」处理;若实机判不可受,回退路径只有「灰矮人改归中档」或「地图头像出 48 专件」,均须另裁。 +3. **主角态切换横跳**(S6):本卡不做重摆;若要修,另立小批。 +4. **`project.godot` 显式声明 stretch/aspect**(观察项):另立工程批。 diff --git a/reports/需求卡片-状态合并累加制批-2026-11-01.md b/reports/需求卡片-状态合并累加制批-2026-11-01.md new file mode 100644 index 00000000..1c99de9d --- /dev/null +++ b/reports/需求卡片-状态合并累加制批-2026-11-01.md @@ -0,0 +1,151 @@ +# 需求卡片:状态合并累加制——同名状态重复授予改加时长 + +> 日期:2026-11-01 +> 性质:需求改动实现批卡片;零待裁点,开工门=U0。 +> 来源:待办清单「状态合并改累加制——同名状态重复授予改加时长」条(2026-10-31 用户立案并四点裁决闭合;登记批 git 提交 d216ae04,设计闭合批 870b2f2b)。 +> 唯一事实源:[增益状态](../design/gdd/systems/战斗循环/增益状态.md) v1.3(2026-10-31)——§同名状态再拿到(合并策略表:叠加/累加/并存)· §剩余次数怎么倒数 · 「幅度与量纲」节盾牌加护行与字段表。本卡只实现上述设计,不改设计。 +> 估时:T0–T2 ≈ **1.0~1.25 个工作日**(中值 ≈1.125)。 + +## 一、目标与完成定义 + +本批把状态表六行(attack_up/ac_up/weaken/empower/fortify/defensive_stance)的合并策略由「refresh=重复授予重置剩余次数」改为「accumulate=重复授予在剩余次数上累加本次授予的时长」,状态容器 refresh 臂同步换为累加臂。 + +完成定义: + +1. 表行:六行 `stack_policy` 值 refresh→accumulate;四行 stack 行与其余全部字段值零改动。 +2. 容器:同名重复授予 → 剩余结算次数加上本次授予的生效时长(`duration_override` ≥1 时加覆盖值);层数恒 1;时长不封顶;空授予面消除(每次授予必有剩余次数变化)。 +3. 叠加(stack)与并存(independent)两臂语义零变化;快照纪律不变(首授快照恒定)。 +4. 词表换代:schema 词表改 `["stack", "accumulate", "independent"]`,加载期枚举校验随词表生效(fail-fast 不变)。 +5. 既有断言数值换代两处+断言标签/注释文字换代两处(第十一节申报共四条)+新增累加断言三条,全部真实入口、当轮执行并通过。 +6. 独立验收审计通过(报告落 `reports/iter-验收审计-<日期>.md`,未过不得合并);反哺点两条落反哺点清单;README 能力行批末只核对名字与实际落地一致;本批不写 `design/` 与根规则文件。 + +## 二、设计事实源 + +1. 增益状态.md v1.3 §同名状态再拿到·合并策略表「累加」行:剩余结算次数加上本次授予的时长——技能施放行带覆盖时长时按覆盖值加;层数不变;现行内容行六行用累加。 +2. 同文档 §剩余次数怎么倒数:累加语义下重复拿一次就按本次授予时长多攒一段,同一轮拿几份攒几段。 +3. 同文档「幅度与量纲」节例表(盾牌加护行):层数恒 1、剩余结算次数累加;掷点判定阈值=主角基准+层数——该句为现状描述,AC 读取路径本无「上限 2 层叠读取法」代码(见第三节 8),AC 侧零改动。 +4. 四点裁决(待办清单条目在案):六行 refresh 全改累加/时长不封顶/只加时长、层数与强度不变/累加量=本次授予的生效时长(带覆盖时长时按覆盖值)。 +5. [地图战斗资源](../design/gdd/systems/战斗循环/地图战斗资源.md) 削弱行引用句(:130,2026-10-31 设计闭合批随改、累加语义已落)——待办清单条目闭合凭据的第二件,与条目实况对齐;无实现缺口。 + +## 三、现状事实(代码级,开工自行复核) + +1. 表行:`game/data/tables/status_effects.tres` 十行;六行 `stack_policy: "refresh"`——attack_up :14、ac_up :23、weaken :32、empower :68、fortify :77、defensive_stance :86;四行 `"stack"`——enrage :41、off_guard :50、sapped :59、alert :95;无 independent 行。相关表值:attack_up/ac_up duration 1·max_stack 2;weaken duration 2·max_stack 16;empower/fortify/defensive_stance duration 2·max_stack 1。 +2. 词表:`game/data/schemas/status_effect_table.gd:11` `STACK_POLICIES := ["stack", "refresh", "independent"]`;:55–56 加载期枚举校验(出域致命——fail-fast)。 +3. 容器:`game/core/status_container.gd:28` `apply_effect(effect_id, source, duration_override=-1)` 唯一授予入口(:37 override <1 → 行值 duration_settlements);:40–49 策略 match;:44–45 refresh 臂转发 `_apply_refresh` :61–67——命中 `inst.remaining = dur`(重置)、未命中追加(层数 1)、恒返回 true。 +4. 叠加臂 :72–80(满层拒零写入、未满加层、不触碰 remaining)与并存臂 :41–43(新建独立实例)——本批零改动。 +5. 快照:`_grant_snapshot` :52–57 授予时快照;refresh 臂重授不换快照——本批沿用该口径(第 13 节代拍板 2)。 +6. 衰减:`decay_round` :122–134 每实例 −1、归 0 移除(先兑付后衰减的编排信任在战斗结算)——累加制零改动。 +7. 授予链三路(真实入口全走 `apply_effect` 同口):`game/core/reward_grant.gd:239`(安全格 percent 奖励 → attack_up/ac_up)· `game/core/damage_controller.gd:451`(效果引擎 fx_apply_status)· `game/core/settlement/combat_segment.gd:89`(敌方增益/妨害技施放——:88 `dur = srow.buff_duration`,覆盖时长的真实入口)。 +8. AC 读取:`game/core/damage_controller.gd:616–631` `defender_ac` = 基线(hero 表或合流入参)+Σ ac 型 `effective_value`(层数×快照幅度)——无上限钳制;ac_up 层数恒 1 → 阈值=基准+1。v1.3「上限 2 层叠读取法退役」为现状描述句,代码无该读取路径——AC 侧零改动。 +9. AC11 采样:`game/tests/unit/battle_settlement/roll_multiplier_test.gd:241` 起 `_ac11_tier_samples` 每轮衰减后重授——实例已移除、重授为新建,不触合并臂——累加制下行为与断言不变。 +10. 断言换代点:`roll_multiplier_test.gd:158–161`(削弱重复授予 remaining==2 重置语义断言与 :157–158 注释)+ :221–236 `_weaken_refresh_probe`(:230 重授注释「remaining ← 2」;:159 调用点与 :342 注释引用该探针名——改名随批换代);`game/tests/unit/data_config/table_structure_guard_test.gd:273–275`(ac_up 行断言 `stack_policy == "refresh"`);`game/tests/unit/battle_settlement/damage_controller_test.gd:376`(断言标签「refresh 政策重复授予受理且层数恒 1」——行为面累加制下仍绿〔层数恒 1、池值不变〕,仅标签文字换代)。 +11. 不受影响断言:`damage_controller_test.gd:391`(stack 行过滤)· `seal_polarity_test.gd:684`(sapped=="stack")· `system_contracts_test.gd:_test_status_boolean_acceptance`(布尔受理——attack_up 行,refresh→accumulate 行;单次授予不触合并臂)。 +12. sim/probe 零消费:`stack_policy`/`apply_effect` 于 `game/sim`、`game/probe` grep 零命中;状态实例不落存档断点(战斗域生命周期——`notify_battle_start` 清空,`game/core/breakpoint_store.gd` 无状态片段)。 +13. EV 锚:战斗结算域 EV 抽样对锚(goblin 锚)读战斗真实结算——合并语义改变重复授予的削弱/增益存续时长,EV 有漂移可能(先例:触发器批 git 提交 4868e11b 触发重锚 ba5105aa 归绿)。 +14. S13 基线:status_container/status_effect_table/damage_controller 均不在 `tools/gdstyle_baseline.txt`(默认阈值内);tests 不在 S13 扫描面。 +15. 表批注:status_effects.tres :99–141 为逐批变更叙事批注(含 :129–141 叙述 refresh 语义的历史——本批换代后成陈旧叙事)。批注保留是用户明令现状(git 提交 4a2ed961,2026-11-01:数值表 `; ` 批注全量恢复)——本批零触碰,处置归用户另裁,实现报告留遗留观察记录。 +16. 文档漂移(考证发现,非本批造成):增益状态.md「现在有哪些状态」节记「现行九行」且行表缺 defensive_stance(护身)行——该行 2026-10-27 触发器批落表(git 提交 4868e11b),文档行清单未跟;合并策略表「六行用累加」计数与表实况一致。 + +## 四、设计契约 + +- 🔴 **C1 累加语义单点**:重复授予的合并只发生在状态容器策略臂(match 分派后累加实现)——任何调用方不得自算 remaining 或二次实现合并。 +- 🔴 **C2 表驱动**:累加行集合以 `stack_policy` 字段为唯一依据——禁按 effect_id 白名单另立硬编码集合。 +- 🔴 **C3 只加时长**:累加臂只改 remaining;层数、快照(m/unit/display)、source_class、origin_cell 首授后恒定;时长不封顶(运行期 remaining 无上限,禁自造 clamp)。 +- 🔴 **C4 覆盖时长口径**:`duration_override` ≥1 时累加量=override 值;<1 时=行值 duration_settlements。 +- 🔴 **C5 两臂不动**:stack 臂满层拒零写入与 independent 臂新建实例语义零变化——触碰即 L3。 +- 🔴 **C6 词表唯一**:`stack_policy` 取值集合只在 schema 词表一处定义;tres 六行与词表同批换代,禁留双值兼容(旧值 "refresh" 出词表即加载期致命,同批清干净)。 + +## 五、范围边界 + +不做:衰减节拍改动(先兑付后衰减不变);单体寻址扩展位实现(接口定稿在案、随首个单体效果内容批);叠加/并存行为调整;status_effects.tres 其余字段与四行 stack 行值改动;表批注处置(:99–141 含本批换代后的陈旧叙事——用户 2026-11-01 恢复令 git 提交 4a2ed961 在案,本批零触碰,另裁另批);「增益叠层/衰减/清除结算链」覆盖缺口的其余断言补齐(归待办清单「能力清单覆盖缺口补齐」条);EV 锚重锚(红则停机呈报,重锚归用户档位发起)。 + +反哺去向:第六节两条 → `reports/iter-反哺点-<日期>.md`,用户裁决后归文档批落文。 + +## 六、关联文档同步面 + +| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 | +|---|---|---| +| design/gdd/systems/战斗循环/增益状态.md | 字段表 `stack_policy` 取值行记「stack / refresh / independent」——词表换代后 refresh 值不复存在 | 反哺点(iterN 反哺点清单):取值改「stack / accumulate / independent」,用户裁决后文档批落文 | +| design/gdd/systems/战斗循环/增益状态.md | 「现在有哪些状态」节记「现行九行」且行表缺 defensive_stance(护身)行——本批考证发现的存量漂移,非本批造成 | 反哺点(iterN 反哺点清单):九行→十行+补护身行(敌方输出减益 −25 percent、duration 2、累加、max_stack 1、来源敌方技能「孤注守势」),文档批落文 | +| game/tests/README.md | 能力行新增+覆盖域表「增益状态」行更新 | 写卡段随本卡已入表(实现批禁写该文件红线不变;批末收尾只核对表上名字与实际落地一致) | + +## 七、文件结构图 + +| 文件 | 职责 | 改动性质 | +|---|---|---| +| game/data/tables/status_effects.tres | 状态表十行 | 行为改动:六行 stack_policy 值换代(对照表 R1);表批注零触碰(范围边界在案) | +| game/data/schemas/status_effect_table.gd | 表 schema 与词表加载期校验 | 行为改动:词表换代(对照表 R1) | +| game/core/status_container.gd | 状态容器(授予/合并/衰减唯一落点) | 行为改动:refresh 臂→累加臂(对照表 R2/R3/R4) | +| game/tests/unit/battle_settlement/roll_multiplier_test.gd | 掷点/削弱/AC11 套件 | 行为改动(测试面):削弱累加探针换代+新增三条断言(对照表 R2–R4;申报见第十一节) | +| game/tests/unit/data_config/table_structure_guard_test.gd | 表结构守卫 | 行为改动(测试面):ac_up 行断言换代(对照表 R1;申报见第十一节) | +| game/tests/README.md | 能力清单与覆盖域表 | 写卡段维护件——本卡落位时已入表,实现批零改动 | + +## 八、落位与可复用性预检 + +- **复用面**:零新增文件、零新增函数、零新增数据件——累加臂就地替换 refresh 臂(`_apply_refresh` 改名 `_apply_accumulate`),词表与表行就地换代;合并逻辑唯一落点=容器策略 match(C1/C6),无第二处可复用或需新建的合并实现。 +- **唯一面**:`stack_policy` 词表唯一出处=schema :11;取值**定义面**全仓 grep 仅存于 tres 六行+schema 词表+容器臂+三处断言(第三节 1/2/3/10)——叙事批注与测试注释例外(第三节 15/10 在案),不属定义面。 +- **分层与交互面**:表行(data/tables)→ schema 校验(data/schemas,加载期致命)→ 容器臂(core)→ 消费面(defender_ac 与池乘区——零改动)。Core 零 UI、数值单点经 ConfigDB、RNG 零新增——既有红线零触碰。 + +## 九、实现规范预算 + +- 新增文件:零——新件三查不适用;迁移函数:零(累加臂就地改写,无自存量文件迁入的函数)。 +- 存量触面一查:触碰产品码两件(status_effect_table.gd、status_container.gd)均不在 gdstyle 基线(默认阈值内);预期 S13 键较现状零新增。tests 不在 S13 扫描面。 + +## 十、任务卡 + +**T0 开工门+基线读数(0.25 天)** + +- [ ] worktree 建区+`git status` 归属核对(并行遗留只登记不触碰) +- [ ] S13 触面读数:两产品文件现行键数记录进实现报告(预期零键——不在基线) +- [ ] EV 锚改前读数留底:从最近 CI 回执抄录战斗结算域 EV 锚读数(goblin 现值)进实现报告,作批末对拍锚 + +**T1 累加制单点实装(0.5~0.75 天)** + +- [ ] status_effects.tres:六行 `stack_policy` "refresh"→"accumulate"(:14/:23/:32/:68/:77/:86;保持既有 CRLF 行尾)——可核查:grep '"stack_policy": "refresh"' 零命中(值行限定写法——:129/:139 恢复批注含同词、不属值行,禁触碰)、"accumulate" 恰六处 +- [ ] status_effect_table.gd:11:`STACK_POLICIES` 换代 `["stack", "accumulate", "independent"]`——可核查:加载链全表装载零红(枚举校验随词表生效) +- [ ] status_container.gd::44–45 match 臂 "refresh"→"accumulate";`_apply_refresh` 改名 `_apply_accumulate`——命中 `inst.remaining = int(inst.remaining) + dur`、未命中追加、恒 true;:60 注释换代(累加语义——R += D;L 不变;快照沿首授)——可核查:容器内 stack_policy 语境 "refresh" 零残留 +- [ ] roll_multiplier_test.gd:③段 :157–158 注释与 :160–161 断言换代(重置 2 → 累加 3);`_weaken_refresh_probe` 改名 `_weaken_accumulate_probe`(:159 调用点与 :342 引用注释随改),探针改五段式——授予(2)→衰减(1)→重授(1+2=3,V1)→覆盖值重授(3+3=6,V3)→同轮再授(6+2=8,V2);返回 {layers, pool, after_regrant, after_override, after_extra, snap_magnitude} 六读数(pool 键保留——:163 池读数断言零改动在位) +- [ ] 新增断言三条(尾缀〔状态累加 V1/V2/V3〕):V1=重授后 remaining==3、layers==1、snap_magnitude==−65(首授快照恒定);V3=覆盖值累加后 remaining==6;V2=同轮再授后 remaining==8 +- [ ] table_structure_guard_test.gd:273–275:ac_up 行断言 `stack_policy == "accumulate"`+消息换代(累加语义句)——可核查:断言尾缀〔状态累加 V4〕可 grep、套件绿 +- [ ] 孤立验证:六套件最窄复跑(roll_multiplier/table_structure_guard/system_contracts/damage_controller/seal_polarity/round_flow_skill_pool——EV 锚套件提前曝红)全绿或按 L3②停机、断言尾缀可 grep + +**T2 产出物落位(0.25 天)** + +- [ ] 实现报告:各卡状态+改动—验收对照表结果列+EV 锚改前改后读数对拍+实机目检总清单(同名状态重复授予后状态存续时长延长——登记不阻塞)+遗留观察记录(tres :129–141 refresh 陈旧叙事批注——处置归用户另裁) +- [ ] 反哺点清单:第六节反哺两条逐条落点 +- [ ] 独立验收审计:未参与实现的会话/子代理按 test-conventions §8.7 审计,报告落 `reports/iter-验收审计-<日期>.md`——未过不得合并 +- [ ] 批末按改动域跑闸(代码域)全绿;合回后本地 CI 复验 + +## 十一、验证闸(改动—验收对照表) + +| # | 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 | +|---|---|---|---|---|---|---|---| +| R1 | 六行合并策略换代+词表加载期校验 | status_effects.tres :14/:23/:32/:68/:77/:86;status_effect_table.gd :11 | table_structure_guard_test ac_up 行断言换代〔状态累加 V4〕(值=="accumulate")+全表装载零红 | 接口 | ConfigDB 加载链 → `StatusEffectTable.row_by_id()` | stack_policy 字段取值(加载期枚举校验随行生效) | 新增:同名状态合并策略(叠加/累加/并存)与剩余次数语义 | +| R2 | 同名重复授予累加时长+层数恒 1 | status_container.gd :44–45/:60–67 累加臂 | roll_multiplier_test._smoke_armor_roll 削弱累加断言〔状态累加 V1〕(重授 remaining==3、layers==1、snap_magnitude==−65) | 单元 | `StatusContainer.apply_effect()` 经真实编排宿主 begin_battle | remaining/layers 只读投影(query_active) | 同 R1 新增行 | +| R3 | 同轮双授予累加两段 | 同上 | 〔状态累加 V2〕(同轮再授 remaining==8) | 单元 | 同上 | remaining 累计 | 同 R1 新增行 | +| R4 | 覆盖时长按覆盖值累加 | apply_effect :37 override 入累加臂 | 〔状态累加 V3〕(覆盖值 3 重授 remaining==6) | 单元 | 同上(真实施放链 combat_segment :89 走同口) | remaining 累加覆盖值 | 同 R1 新增行 | +| R5 | 快照纪律不变(首授快照恒定) | 非行为改动——累加臂沿用既有重授不换快照口径,零代码变化 | 〔状态累加 V1〕快照断言(snap_magnitude==−65) | 单元 | 同 R2 | 快照域取值(snap_magnitude) | 同 R1 新增行 | +| R6 | 叠加/并存两臂零变化 | 非行为改动——两臂零代码变化 | damage_controller_test :391+seal_polarity_test :684+system_contracts_test 布尔受理——既有断言零改动复跑即回归证词 | 单元 | 各既有真实入口 | 既有断言零改动 | 既有:系统间契约词表与受理口径 | + +**测试削弱申报**(允许的旧断言改动,全部为语义换代非削弱): + +1. roll_multiplier_test.gd:160–161 削弱续时断言——refresh 重置语义(remaining==2)作废,换代为累加语义(remaining==3)——被测行为就是本批改动本体。 +2. roll_multiplier_test.gd:157–158 注释、:230 探针注释与 :342 探针名引用注释换代(「续时:remaining ← 2」→累加口径;旧函数名 `_weaken_refresh_probe` 全仓清零)。 +3. table_structure_guard_test.gd:274–275 ac_up 行断言值与消息换代(refresh→accumulate)——同上。 +4. damage_controller_test.gd:376 断言标签「refresh 政策重复授予受理且层数恒 1(叠层改续时裁决)——池值不变」——行为面累加制下仍绿(层数恒 1、池值不变,断言数值零改动),仅标签文字换代为累加口径。 + +## 十二、异常分级 + +- **L1 自救**:一次重试(表装载/套件瞬时红)。 +- **L2 记录继续**:同红灯连续 3 次升级。 +- **L3 停机呈报**:①C1–C6 任一触碰;②战斗结算域 EV 锚套件红(累加制有意行为改动的期望值漂移)——锚内子集判红即停,重锚归用户档位发起(先例=触发器批 2026-10-27:EV 0.9148 出带 → 重锚 ba5105aa 归绿);③S13 新增红键=上游缺陷停卡退回写卡段(机检预算互斥)。 + +## 十三、代拍板白名单 + +1. 词表值命名 `accumulate`(实现标识符——语义已由 v1.3 全定;反哺点随批登记文档字段表行换代)。 +2. 合并授予不改快照(沿用既有 refresh 臂口径——首授快照恒定、幅度 override 只作用首授)。 +3. 测试函数改名 `_weaken_refresh_probe`→`_weaken_accumulate_probe` 与新增断言措辞(V 尾缀〔状态累加 Vn〕编号在案)。 + +## 十四、待裁点 + +零待裁点,开工门=U0。(四点裁决 2026-10-31 用户裁闭合——待办清单条目在案;本卡全部实现项与代拍板 1–3 均为该裁决的实现面,无新增设计分叉。) diff --git a/reports/需求卡片-立绘显示档批-2026-11-01.md b/reports/需求卡片-立绘显示档批-2026-11-01.md new file mode 100644 index 00000000..41fb9101 --- /dev/null +++ b/reports/需求卡片-立绘显示档批-2026-11-01.md @@ -0,0 +1,244 @@ +# 需求卡片 · 立绘显示档批(v1.1) + +> **用途**:迭代实现批的实施合同(卡①单卡批)。v1.1=双审(grilling+godot-master)后执行级订正,设计面零改动(复核记录=`reports/复核-双审-grilling与godot-master-立绘显示档批-2026-11-01.md`)。 +> **来源**:待办清单「立绘清晰度回退评估——原稿分辨率+三档显示」条目(状态=美术设计已闭合+已写卡)。 +> **唯一事实源**:`design/art/art-bible.md` §8.2「站桩立绘显示档 = 三档绝对高」条(v3.32)+ `design/art/character-design.md` §5.2/§5.5 指路行。 +> **改动面**:美术素材+游戏代码。 **估时**:≈0.85 个工作日。 + +--- + +## 1. 目标与完成定义 + +**做什么**:把 9 件站桩立绘(八敌 + 主角三态)从「原稿降采样到 48–94 再 ×2 显示」改成「原稿分辨率入包 + 显示按三档绝对高缩放」。 + +| 档 | 绝对显示高 | 归档 | +|---|---|---| +| 小型 | 96 | 地精 goblin、巨蜘蛛 giant_spider、灰矮人 duergar | +| 中型 | 144 | 主角 hero、钩爪恐魔 hook_horror、熊地精 bugbear | +| 大型 | 188 | 食人魔酋长 ogre_chief、蛛化卓尔 drider、灰矮人石君王 duergar_king | + +宽度一律随源图比例(高定宽随),缩放过滤 NEAREST。 + +**什么状态算完**: + +1. 9 件素材 = 原稿紧裁原样落 `game/assets/art/character/`,盘上无任何降采样痕迹; +2. `standee_motion.gd` 硬编码 ×2 退役,显示倍率由逐件档高算出; +3. `tools/standee_asset_check.py` 与 `tools/pixelize_candidates.py` 改按显示档与原稿高校验,全绿; +4. 真实入口断言钉住逐件显示档高、纵横倍率恒等、两表同值; +5. 样张脚本站桩段与探针文案随动; +6. 代码域闸全绿 + 改前/改后并排对照图落盘 + 产出物三份齐。 + +--- + +## 2. 现状事实(代码级,开工复核) + +| # | 事实 | 出处 | +|---|---|---| +| F1 | 显示倍率硬编码:`w/h = tex.get_width/height() * 2.0`、`scale = Vector2(2.0, 2.0)` | [standee_motion.gd:63](game/presentation/views/standee_motion.gd#L63) | +| F2 | 立绘盒几何:`box := Vector2(150, 176)`;立绘盒矩形 `(0,44)-(box.x, box.y-80)` → 立绘区 150×96,高于 96 者按 `(box_h-h)*0.5` 向上溢出 | [standee_body.gd:24](game/presentation/views/standee_body.gd#L24)、[:309](game/presentation/views/standee_body.gd#L309)、[standee_motion.gd:62](game/presentation/views/standee_motion.gd#L62) | +| F3 | 盒宽常量与盒高注入:`_STANDEE_W := 150.0`;`hero_standee.box = Vector2(_STANDEE_W, box_h)`(盒高=行高) | [battle_stage_view.gd:10](game/presentation/views/battle_stage_view.gd#L10)、[:197](game/presentation/views/battle_stage_view.gd#L197) | +| F4 | 主角立绘装载与三态注册(含「48px 档」注释);敌侧 `_enemy_portrait_tex(enemy_id)` 查表后 `set_portrait_texture` | [battle_stage_view.gd:132-140](game/presentation/views/battle_stage_view.gd#L132)、[:252-267](game/presentation/views/battle_stage_view.gd#L252) | +| F5 | 纹理路径常量单点在 UiKit(八敌 + 主角三态) | [ui_kit.gd:233-247](game/presentation/views/ui_kit.gd#L233) | +| F6 | 现行入包稿尺寸:主角三态 46×48 / 48×48 / 46×48;八敌 36×36、48×38、34×46、46×58、51×62、62×74、67×90、66×94 | 盘上 `game/assets/art/character/`(素材不入 git) | +| F7 | **现行入包稿 = 原稿降采样,逐像素相同**:`dom_block_resize(pixel-1, 74/90/94)` 与 ogre_chief/drider/duergar_king 三件 diff 框为空(2026-11-01 会话实测) | 管线 [pixelize_candidates.py:430-457](tools/pixelize_candidates.py#L430) | +| F8 | 原稿在盘:八敌 `pixel-1.png` 高 81–189(地精 89×90/巨蜘蛛 102×81/灰矮人 93×126/钩爪 74×94/熊地精 102×123/酋长 158×189/卓尔 140×189/石君王 133×189);主角手修 2× 三态稿内容 88×92 / 92×92 / 88×92 | `artwork/remote-gen-2026-09-26/`(不入 git) | +| F9 | 派生管线末步即降采样:`build_standee48` 紧裁 → 等比缩至 `STANDEE_TIER_H` → `dom_block_resize` | [pixelize_candidates.py:28](tools/pixelize_candidates.py#L28)、[:38-43](tools/pixelize_candidates.py#L38)、[:459-504](tools/pixelize_candidates.py#L459) | +| F10 | 闸件按源档高校验:`DISPLAY_SCALE=2`、`SRC_W_MAX=75`、断言①档高、断言②源宽×2≤150 | [standee_asset_check.py:50-53](tools/standee_asset_check.py#L50)、[:75-98](tools/standee_asset_check.py#L75) | +| F11 | 样张脚本站桩段硬编码「立绘盒 96px(48 源 ×2)」;另有 A4 尺寸基线硬锁 `PORTRAIT_SRC.size==(46,48)` 与战斗语境 96×96 方框 mockup(脚本自述「换代须显式解冻重校」) | [render_sample_sheet_v3.py:775-791](tools/render_sample_sheet_v3.py#L775)、[:1135-1139](tools/render_sample_sheet_v3.py#L1135)、[:1501](tools/render_sample_sheet_v3.py#L1501) | +| F12 | 探针文案「48px 档」(判据只查 `has_tex`,非尺寸断言) | [ui_probe.gd:139-144](game/probe/ui_probe.gd#L139) | +| F13 | 另两消费面按固定框装载同一素材:标题屏 138×144/46×96/80×96(`STRETCH_KEEP_ASPECT_CENTERED`+NEAREST);关卡地图头像定高 48、宽随源比 | [ui_assembler.gd:170](game/presentation/ui_assembler.gd#L170)、[level_map_screen.gd:176-190](game/presentation/views/level_map_screen.gd#L176) | +| F14 | 能力清单现行行「站桩呈现定值与素材绑定」→ `standee_present_values_test.gd`(V5–V12 在此套件) | [README:136](game/tests/README.md#L136) | +| F15 | 舞台高 252(溢出上限的物理边界) | `game/data/tables/battle_layout.tres` | + +--- + +## 3. 设计契约(违反即返工;标 🔴 触碰=L3 停机呈报) + +1. 🔴 **禁改形象**:9 件素材 = 原稿紧裁原样,禁重画、禁生成、禁 `dom_block_resize` 降档(art-bible §8.2 v3.32)。 +2. 🔴 **显示档定值单点** = art-bible §8.2;GDScript 侧 `PORTRAIT_DISPLAY_H` 与 Python 侧 `STANDEE_DISPLAY_H` 逐键同值、两侧各自钉死字面值,跨语言对账由 V17 承担(读不到文件走 L2,见 §8/§9);禁第三处复写,**禁查表兜底字面量**。 +3. 🔴 **纵横倍率恒等**(高定宽随),禁方框强拉(art-bible §8.2 槽位条)。 +4. 🔴 **体量顺序由显示档承载**:小 < 中 < 大;禁按强度重排(character-design §5.2)。 +5. 🔴 **已接受项不得当缺陷回炉**:①五件源高低于档高属放大显示(主角 92/钩爪 94/熊地精 123/地精 90/巨蜘蛛 81,倍率 1.07–1.57);②灰矮人 126→96 是全批唯一 <0.8 档(0.76× 抽行,NEAREST 描边约每 4 行断点),列目检①头号回退候选;③食人魔酋长显示宽 157 超桩盒 150;④关卡地图头像由 ≈1× 变 0.52× 降采样,列目检③。 +6. 🔴 显示档数值只落显示档表,绘制点与检查器一律读表,禁字面量散落(数值单点纪律)。 +7. 🔴 素材不入 git(art-bible §8.3);本批入 git 的只有代码/工具/测试/文档件,素材落盘由实现批执行并在实现报告逐件留读数。 + +--- + +## 4. 范围边界 + +**做**:9 件素材按档派生落盘;`standee_motion.gd` 显示倍率改造;`pixelize_candidates.py`/`standee_asset_check.py` 改显示档;样张脚本站桩段随动;探针与装载点注释随动;`standee_present_values_test.gd` 增显示档断言。 + +**不做(去向明示)**: + +- 不重画、不生成任何图像(现有形象即终稿)。 +- 不动棋盘小人(`character_hero_idle/walk.png` 32×32 独立资产)——另属棋盘面。 +- 不改标题屏与关卡地图头像的框尺寸(两面只随素材分辨率自动变化;若目检判需专件,另批)。 +- 不动色板与 `#A79CB8`(保留在板、本批不消费;色板额度议题另批讨论)。 +- 不做站桩帧动画(待办清单「站桩帧动画」条)。 +- 不做主角态切换重摆(`standee_motion.gd:85-86` `apply_hero_state` 换纹理不重算 position,三态源宽 88/92/88 → 切换有约 3–6px 横跳,系现行 2px 的放大版;重摆=行为改动,禁实现批顺手加,要修另批)。 +- 不做关卡地图 48px 头像专件(新源在该面为 0.52× 降采样;目检判不可受则另批出专件)。 +- 不做桩盒宽 150 与 >150 溢出档的布局重排(食人魔超宽 8px 按已接受项走;实机若碰邻位则 L3 停机,布局另批)。 + +--- + +## 5. 关联文档同步面 + +| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 | +|---|---|---| +| `design/art/art-bible.md` §8.2 | 显示档条与排版条 >150 举例 | **已落**(前置文档批 v3.32,本区已改)——实现批禁写 `design/`,本批零义务 | +| `design/art/art-bible.md` §8.2 槽位条 | 「高度的整数倍档」与绝对档高+非整数倍率字面冲突 | **已落**(双审后随设计批改「高度的绝对档(档高取整数像素值)」) | +| `design/art/art-assets-checklist.md` §0 分辨率档位行 | 旧口径「站桩源高 48/敌种逐键源档 36–94/整数倍缩放纪律」 | **已落**(改指 §8.2 显示档条) | +| `design/art/character-design.md` §5.5 | 指路行 | 同上,已落 v3.32 配套 | +| `design/gdd/08-Alpha版本标准.md` 覆盖行 | 出口从「重产完成」改「9 件按档落位+目检」 | 已落 v1.22;实现完成后「待做→在役」列**反哺点**呈裁 | +| `待办清单.md` 本条 | 状态推进(已写卡→已编迭代→完成删条) | 各段按状态机推进,非实现批直改 → 列**反哺点** | +| `design/art/art-prompts.md` §5.4 产出状态 | 「待实装批落位」→「已落位」 | 实现完成后 → 列**反哺点** | +| `design/art/art-status-checklist.md`/`art-assets-checklist.md` 站桩行 | 「按档派生落位归本条实装批」→ ✅ 已交付 | 实现完成后 → 列**反哺点** | +| `game/tests/README.md` 能力清单 | 新能力行「站桩显示档与素材分辨率绑定」 | **写卡段已同批补行**(本卡 §9 能力行与之一致);实现批禁写该文件 | +| `design/gdd/术语表.md` | 「显示档」是否立条 | 列**反哺点**呈裁 | +| `体验验证清单.md` | 实机目检项(9 件清晰度、同屏体量顺序、标题屏/地图头像消费面) | 实现批禁写 → 列**反哺点**,目检清单先落实现报告 | + +--- + +## 6. 卡前文件结构图 + +| 文件 | 职责 | 改动性质 | 验收行 | +|---|---|---|---| +| `game/presentation/views/standee_motion.gd` | 显示档表 `PORTRAIT_DISPLAY_H` + `_place_portrait` 按档算倍率 | **行为改动** | V1 V2 V3 | +| `game/presentation/views/standee_body.gd` | 探针 `portrait_probe()` 扩显示读数(几何出口单点) | **行为改动**(观测面扩展,绘制零改) | V3 V4 | +| `game/presentation/views/battle_stage_view.gd` | 「48px 档」注释随动 | 非行为 | — | +| `game/probe/ui_probe.gd` | 文案随动(判据不变) | 非行为 | — | +| `game/tests/unit/presentation/standee_present_values_test.gd` | 增 V13–V16 显示档断言(复用既有套件,禁新增文件) | 新增测试 | V1–V4 | +| `tools/pixelize_candidates.py` | `STANDEE_TIER_H` → `STANDEE_DISPLAY_H`;`build_standee48` 改紧裁不降档 | 工具(非行为) | V5 | +| `tools/standee_asset_check.py` | 断言①改源高=原稿表+显示宽;断言②宽上限按显示宽;表名随动 | 闸件(非行为) | V5 | +| `tools/render_sample_sheet_v3.py` | 站桩 mockup 按显示档取数 | 工具(非行为) | V7 | +| `game/assets/art/character/`(9 件,不入 git) | 原稿紧裁落盘 | 资产 | V5 | +| `artwork/candidates/立绘显示档批-<日期>/`(不入 git) | 改前/改后并排对照图 | 取证 | V6 | + +--- + +## 7. 任务卡 T0..T3 + +### 7.1 T0——改前读数与基线(估时 0.1 个工作日) + +- [ ] 跑 `python tools/standee_asset_check.py` 记录现行 9 件读数(尺寸/档高/色数/描边占比),存实现报告改前基线表。 +- [ ] 跑 `python tools/pixelize_candidates.py --standee48 --standee-out /tmp/precheck` 确认现行管线产物与盘上素材逐件同尺寸(证明 F7 降采样链在位)。 +- [ ] 跑代码域闸确认改前全绿(确切命令见 §9 末注)。 + +**取用**:无。**产出**:改前基线读数表(T3 对照用)。 + +### 7.2 T1——素材按档派生落盘+闸件同批改口径(估时 0.25 个工作日) + +- [ ] `tools/pixelize_candidates.py`:`STANDEE_TIER_H` 改名 `STANDEE_DISPLAY_H`,值改显示档 `{goblin:96, giant_spider:96, duergar:96, hook_horror:144, bugbear:144, ogre_chief:188, drider:188, duergar_king:188}`,主角侧 `STANDEE_SLOT_H` 改 `144`;新增原稿高表 `STANDEE_SRC_H = {goblin:90, giant_spider:81, duergar:126, hook_horror:94, bugbear:123, ogre_chief:189, drider:189, duergar_king:189, hero:92}`。 +- [ ] `build_standee48` 改紧裁不降档:内容紧裁 → 底中锚 → 原样存盘;**删除 `dom_block_resize` 调用路径**(函数与 CLI 旗标改名按档派生);主角源由 `hero-ref/edit/*_1x.png` 改指 `*_2x.png`(canvas 94×112/96×112,紧裁后 88×92/92×92/88×92)。 +- [ ] **原稿输入面显式定径**:`python tools/pixelize_candidates.py D:/code/g-plan2/artwork/remote-gen-2026-09-26 --standee-out game/assets/art/character`——worktree 的 `artwork/` 不含原稿(`sync_worktree_assets.sh:26-34` 只同步 `game/assets/art` 与 `.import`),缺省根路径在本区必**静默空跑**(缺件逐键 `isfile` 跳过、exit 0)。 +- [ ] 产物计数自证:九件逐件尺寸 == `STANDEE_SRC_H` 表值,**计数 ≠ 9 即停(L3#2)**,禁回退用旧降采样稿顶替。 +- [ ] `tools/standee_asset_check.py` 同批改口径(素材与闸件同批,禁中间态报红):import 改 `STANDEE_DISPLAY_H/STANDEE_SRC_H`;断言①「源高 == 原稿表值(禁降档)」;断言②「显示宽 = round(源宽×档高/源高) ≤ 150,食人魔酋长 157 登记例外」;其余四断言(底中锚/色数≤32/alpha 二值/描边占比)不变。跑至九件全 PASS。 +- [ ] 跑 `D:\code\godot\Godot_v4.7.2-stable_win64_console.exe --headless --editor --quit --path game` 刷 `.godot` 导入缓存,确认九件 `.ctex` 在位。 + +**取用**:T0 基线表。**产出**:九件原稿分辨率素材(盘上)+ `STANDEE_DISPLAY_H`/`STANDEE_SRC_H` 两张 Python 表+新口径闸。 + +### 7.3 T2——代码显示倍率改造(估时 0.25 个工作日) + +- [ ] `standee_motion.gd` 增常量表 `PORTRAIT_DISPLAY_H`(九键字面值钉死;**禁 `.get(key, 96.0)` 类兜底字面量**——档值第二处散落即违契约 2/6)。 +- [ ] `_place_portrait` 改:`key` 主角取 `"hero"`、敌取 `_owner.enemy_id()`;查无键 → `push_error` 并按 1× 落位(不崩、不静默兜档),由 V18 键集自检在测试期报警;命中 → `s = disp_h / 源高`、`scale = Vector2(s, s)`、`w/h = 源尺寸 × s`,`position` 式沿用 F2 居中溢出机制。 +- [ ] `standee_body.gd` `portrait_probe()` 扩两读数:`display_size`(Vector2)、`display_scale`(float)。 +- [ ] `standee_present_values_test.gd` 增私有函数 `_check_display_tier()` 承载 V13–V18(断言内写死规格值;**浮点判等一律 `is_equal_approx` 或 `absf(...)<0.01`**——0.99/1.57 档回程有 ULP 级残差,裸 `==` 会假红)。 +- [ ] 注释随动:`standee_motion.gd:38-39,59,65`(旧「盒高 96=48 源整数 2×/§8.2 禁非整数缩放」已反向引用注销条款)、`battle_stage_view.gd:134`、`ui_probe.gd:140,144`、`level_map_screen.gd:176`(「定高 48px=1×」)。 +- [ ] 跑 `standee_present_values_test.gd` 单件至 exit 0。 + +**取用**:T1 素材与 Python 表。**产出**:`PORTRAIT_DISPLAY_H`、`portrait_probe()` 两读数、V13–V18 断言。 + +### 7.4 T3——样张随动、对照取证、素材落递与批末收口(估时 0.25 个工作日) + +- [ ] `render_sample_sheet_v3.py`:站桩段按显示档取数;A4 尺寸基线冻结断言(`:1135-1139` 锁 `PORTRAIT_SRC.size==(46,48)`)与战斗语境 96×96 方框(`:1501`)**显式解冻重校到新档**,禁放宽阈值凑绿。 +- [ ] 出改前/改后并排对照图(同屏站桩区+标题屏看台+关卡地图头像三面)落 `artwork/candidates/立绘显示档批-<日期>/`,路径写进实现报告。 +- [ ] **素材落递主工作区**:合回落地后、删区前,把九件新稿拷回 `D:/code/g-plan2/game/assets/art/character/` 并逐件复核尺寸 == 表值——素材不入 git、worktree→主区无同步通道,漏这步则主区 CI 只有 V16 一处报警、敌侧无人看守。 +- [ ] 跑代码域闸全绿(§9 末注),读数与闸况写进实现报告。 +- [ ] **产出物落位卡**:`reports/iter-实现报告-<日期>.md`(各卡状态+实机目检总清单:①九件清晰度含灰矮人 0.76× 判读、②同屏体量顺序、③标题屏看台与地图头像 0.52×、④酋长超宽不碰邻位、⑤主角态切换横跳读数+遗留读数义务)/`reports/iter-代拍板追认-<日期>.md`/`reports/iter-反哺点-<日期>.md`(§5 每条都有落点)。 +- [ ] 独立验收审计入口与报告:`reports/iter-验收审计-<日期>.md`(未过不得合并)。 + +**取用**:T1 素材+T2 表与探针。**产出**:闸全绿回执+主区素材追平+三份产出物。 + +--- + +## 8. 验证闸(改动—验收对照表) + +| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 | +|---|---|---|---|---|---|---| +| 逐件显示档高 | `standee_motion.gd` 新增 `PORTRAIT_DISPLAY_H` + `_place_portrait` | 「九键显示档实读 = 96/144/188 逐键钉值,且源高 == 原稿表值(旧降采样稿必红)」`standee_present_values_test.gd:_check_display_tier`〔立绘显示档 V13〕 | 单元 | `StandeeBody.new("enemy")` → `set_data(enemy_id)` → `set_portrait_texture(真纹理)` → `portrait_probe()` | `display_size.y` 与 `display_scale × 源高` 双读数 ≈ 档高(`is_equal_approx`);九键逐一 | 新增:站桩显示档与素材分辨率绑定 | +| 硬编码 ×2 退役 | `standee_motion.gd:63-65` | 「`_place_portrait` 体内引用 `PORTRAIT_DISPLAY_H` 且零 `Vector2(2.0, 2.0)`」〔V14〕 | 单元(静态判据) | `FileAccess` 读 `res://presentation/views/standee_motion.gd` | 源锚正证(读表)+反证(无字面 2× 倍率) | 新增:站桩显示档与素材分辨率绑定 | +| 纵横倍率恒等 | 同上 | 「`scale.x == scale.y` 且 `display_size.x == round(源宽×档高/源高)`」〔V15〕 | 单元 | 同 V13 入口 | 探针 `display_scale`/`display_size` 实读 | 新增:站桩显示档与素材分辨率绑定 | +| 主角中档 144(三态) | 素材 = 手修 2× 稿;`register_hero_state` 面 | 「主角三态纹理源高 ≥92 且显示高 = 144」〔V16〕 | 单元 | `BattleStageView` 组合根装载后 `hero_standee.portrait_probe()`,再逐态 `apply_hero_state` 复读 | 探针显示高逐态实读 | 新增:站桩显示档与素材分辨率绑定 | +| 素材不降采样 | 9 件 = 原稿紧裁;`standee_asset_check.py` 新口径 | 「源高 == 原稿表值 +显示宽 ≤150(酋长例外)+色数 ≤32+底中锚+alpha 二值+描边占比」 | 闸(工具) | `python tools/standee_asset_check.py` | 逐件源高/显示宽读数 == 表值 | 既有:站桩呈现定值与素材绑定 | +| 两表同值不漂移 | Python `STANDEE_DISPLAY_H` ↔ GDScript `PORTRAIT_DISPLAY_H` | 「读 `../tools/pixelize_candidates.py` 源文本逐键对账」〔V17〕 | 单元(静态判据) | `FileAccess` 读仓库内 `tools/` 件(双审对此点结论相左,见复核报告 S9) | 两表逐键相等;**读不到文件 → L2 记录、退回双端字面钉值+独立审计对账,禁当红亦禁当绿** | 新增:站桩显示档与素材分辨率绑定 | +| 显示档表键集完整 | 同上 | 「表键集 ⊇ 八敌 ∪ hero 且无多余键」〔V18〕 | 单元 | 读 `PORTRAIT_DISPLAY_H` | 键集对账(防新敌种漏登记被 `push_error` 静默) | 新增:站桩显示档与素材分辨率绑定 | +| 样张口径随动 | `render_sample_sheet_v3.py` 站桩段 | 样张脚本自跑断言(脚本内 CHECKS 全绿)+改前改后并排图 | 工具 | `python tools/render_sample_sheet_v3.py` | 脚本内站桩档高读数 | 既有:站桩呈现定值与素材绑定 | +| 实机观感 | 9 件显示档 + 两消费面 | 用户目检:①9 件清晰度可接受;②同屏体量顺序小<中<大;③标题屏看台与关卡地图头像无可感劣化;④酋长超宽不碰邻位 | 目检(登记不阻塞) | 实机战斗屏/标题屏/地图屏 | 目检总清单落实现报告 | 新增:站桩显示档与素材分辨率绑定 | + +**测试削弱申报**:本批不删不改任何既有断言;`ui_probe` 只改文案(判据 `has_tex` 不变);样张脚本改取数方式,其机检项断言不减。 +**判据口径**:全批无变异类/撤销类取证;每行从真实入口进入、绑被测改动特有的可观测读数。 +**代码域闸命令(里程碑步出口跑一次全套,波内修复只做出红件最窄确认)**:`bash tools/run_all_gates.sh --code`。 + +--- + +## 9. 异常分级 + +- **L1 自救**:`.import`/`.ctex` 缺位 → 重跑 `--editor --quit` 刷缓存;对照图目录不存在 → 建目录。 +- **L2 记录继续**:样张脚本整屏读数偏移但四项机检仍绿 → 读数写实现报告,不返工;V17 读 `../tools/` 路径不通 → 记录后退回「双端字面钉值+独立审计对账」,禁判红。 +- **L3 停机写报告等用户**: + 1. V13–V16 任一断言在真实跑批中做不出(判据绑不上)→ 停卡呈报,禁放宽阈值或换下层直调; + 2. 原稿缺件(任一 `pixel-1`/手修 2× 稿不在盘)→ 停机呈报,**禁回退用旧降采样稿顶替**; + 3. 食人魔酋长实机碰邻位/压到顶部轮次指示 → 停机呈报(布局重排另批); + 4. 机检预算互斥=上游缺陷停卡退回写卡段(新增件契约与闸键冲突时禁自造第三条路)。 + +--- + +## 10. 代拍板白名单(超清单必呈报) + +1. `portrait_probe()` 新读数键名(`display_size`/`display_scale` 之外的等价命名)。 +2. `pixelize_candidates.py` 函数与 CLI 旗标改名措辞(`--standee48` → 按档派生类命名)。 +3. 测试尾缀用词〔立绘显示档 V13〕的括注格式。 +4. 对照图目录名与文件名(保持 `artwork/candidates/立绘显示档批-<日期>/` 形态)。 +5. 主角取 key 的实现写法(`_owner.enemy_id()` 空值判 hero,或经 kind 判定),只要最终表键集为九键。 + +--- + +## 11. 待裁点 + +**零待裁点,开工门 = U0。** 三档绝对高、逐件归档、放大与超宽两项已接受,均由用户在写卡前的设计会话中裁定(凭据见 §2 与待办清单本条实况)。 + +--- + +## 12. 落位与可复用性预检 + +| 新增件 | 复用面(盘上是否已有同职责件) | 唯一面 | 分层与交互面 | +|---|---|---|---| +| `PORTRAIT_DISPLAY_H`(`standee_motion.gd` const) | 无同类——现行倍率是 `_place_portrait` 内字面量(F1),本表是把它从「隐式 ×2」变「显式逐件档高」;不新增文件 | 显示档在 GDScript 侧只落这一张表;绘制点只此一处读表 | 呈现层内部件,不跨层;取 key 走宿主 `StandeeBody.enemy_id()` 既有出口,禁 Core 依赖 | +| `portrait_probe()` 两读数 | 复用既有探针出口(`standee_body.gd:283`),不新建探针件 | 显示尺寸读数唯一出口 | 测试侧只读,不反向驱动绘制 | +| 测试 V13–V16 | **复用既有套件** `standee_present_values_test.gd`(能力=站桩呈现定值与素材绑定,先例=迭代 46 卡B 在同文件加 V10–V12)——不新增测试文件 | 一套件一能力域 | headless 无渲染面,像素采样以探针几何+源锚承载(沿该套件既有口径) | +| `STANDEE_DISPLAY_H`/`STANDEE_SRC_H`(Python) | 改名/扩表,不新增脚本;`dom_block_resize` 保留为管线其他用途件(禁删函数本体) | Python 侧显示档只此一处,`standee_asset_check.py` 经 import 读(沿 F10 现例) | 工具侧,不进游戏运行时 | +| 9 件素材 | 复用原稿(F8),零新增绘制 | 一素材一路径,键名不变(F5 常量单点不动) | 素材不入 git(契约 7) | + +--- + +## 13. 禁为机检文本保留无效成员 + +本批为呈现改造,仍立条款:若 `standee_asset_check.py` 或测试的消息文本要求保留旧键名(`STANDEE_TIER_H`/`STANDEE_SLOT_H`)凑计数或凑正则,一律停卡呈报;闸键与卡片契约互斥时禁自造第三条路,禁为过闸保留无消费方的别名。 + +--- + +## 14. 实现规范预算 + +- **新件三查**:本批**无新增 .gd 文件**(§12 复用面已定),三查不适用;新增常量表 1 个、探针读数 2 个,不触公开方法/var 阈值。 +- **扫描面事实(双审核正)**:gdstyle 只扫 `game/core|data|presentation`(`tools/gdstyle_gate.py:49`),**tests 不在面**,`tools/gdstyle_baseline.txt` 内亦无该测试键——v1.0 所写「核该测试键登记值」属空操作,注销。 +- **存量触面一查(S13 键只降不升,适用在面件)**:`standee_motion.gd`(在面)——只增一个常量表并改 `_place_portrait` 换算式,branches 不变、不产新键;`standee_body.gd:portrait_probe()`(在面)——返回字典扩两键,branches 不变。 +- **测试侧纪律**:V13–V18 提私有函数 `_check_display_tier()` 承载(拆分不改语义,非凑机检);新写测试码按 test-conventions §7 带全类型标注。 +- **指标例外申报**:无。 + +--- + +## 15. 估时与切分预案 + +≈0.85 个工作日(T0 0.1/T1 0.25/T2 0.25/T3 0.25)。 + +切分预案:素材与闸件已在 T1 同批改口径(不留中间态报红窗口);若 T3 三面对照图+主区素材追平压超软盒,切分点=把 T3 的「样张随动」独立成卡②,两卡同迭代合回,不拆迭代;若实机判酋长超宽碰邻位或灰矮人 0.76× 不可受,本卡止于 L3 停机/回设计段裁档,另立新条。 diff --git a/tools/shot_checker.py b/tools/shot_checker.py index 8a6d9542..9fdb5735 100644 --- a/tools/shot_checker.py +++ b/tools/shot_checker.py @@ -6,7 +6,9 @@ r"""shot_checker.py — 整屏样张闸机检(B 档断言骨架扩全)。 = shot_probe 输出的控件实测几何,为文字框/明度带取样坐标源——分辨率档位自适应,禁硬编码像素)。 断言(整屏样张闸 §1.4 四项的机检可判面): - A 屏级骨架: PNG 存在/尺寸=工程档/灰度 std≥8/唯一色数≥64(渲染真实发生); + A 屏级骨架: PNG 存在/尺寸=工程档/灰度 std≥8/唯一色数≥40(渲染真实发生——std≥8 取值在 + 圣经 §7.2 文字 4.5:1 推论下界之下、正常实测最低 19.3 之上;色数 40=正常实测地板 60 + 〔营地场景图,七屏最低〕的 2/3,低于一切正常屏,色数异常回落=画面异常信号,停下人工复查); B 文字对比度: 已知文字框〔主墨/暖白 文字簇 vs 背景簇 p2/p98 极性无关〕WCAG ≥4.5:1 (战斗 C 区面板/结算明细提示等已知文字框——圣经 v3.5 §7.2 全局文字硬指标机检面); C 明度三档带: 战斗屏 信息面(C 区面板均值) > 世界中(棋盘区均值) > 世界底(舞台无光柱区均值) @@ -135,8 +137,10 @@ def main() -> int: colors = len(set(img.getdata())) if std < 8.0: failures.append("%s: 灰度 std %.1f < 8(疑似空白/纯色)" % (name, std)) - if colors < 64: - failures.append("%s: 唯一色数 %d < 64(疑似占位屏)" % (name, colors)) + # 唯一色数下限=正常实测地板 60(营地场景图,七屏最低)的 2/3——低于一切正常屏; + # 色数异常回落=画面异常信号,停下人工复查。 + if colors < 40: + failures.append("%s: 唯一色数 %d < 40(色数异常回落)" % (name, colors)) print("[shot_checker] %s — %s std=%.1f colors=%d" % (name, "x".join(map(str, img.size)), std, colors)) # B+C+D 断言(battle/menu 两屏为机检承载屏;camp/level 走骨架+目检清单) diff --git a/待办清单.md b/待办清单.md index 03e3e9a5..4716a83e 100644 --- a/待办清单.md +++ b/待办清单.md @@ -2,6 +2,16 @@ 本清单是流水线的唯一登记处:以后才做的事在此登记一条,随流水线段推进改状态,做完整条删除(条目记进度,不是各段的开工前置);各系统文档的「待办」节只留一行指路存根,不再自建条目。条目格式(标题=登记元数据含可选优先级,正文=实况/缺口/改动面/状态四属性)与状态机以 [doc-conventions §12.1](design/engineering/doc-conventions.md) 为权威。 +#### 正常屏唯一色数收敛(2026-11-01 登记,来源=会话提及) + +**实况**:实测凭据=render_gate 七屏 shot_checker 读数(2026-11-01 会话实测,1280 档整屏唯一色数):营地 60/设置 125/生涯 736/关卡 843/状态 865/菜单 968/战斗 1579–1884;历史 QA(2026-09-30)最低 495。正常屏色数 60–1579、数量级过大=颜色过杂,用户裁记待办治理;本批只调闸机阈值(正常地板 60 的 2/3=40),不动色板。关联文档:[美术圣经](design/art/art-bible.md)(§4.1 色板分层=色板纪律 owner)。 + +**缺口**:还差一次美术设计讨论——正常屏色数的目标上限、收敛手段(色板压缩/量化纪律)、与 §4.1 两层色板条款(token 板 ≤48/环境子板每屏 ≤32)的关系。 + +**改动面**:文档+美术素材 + +**状态**:待文档设计 + #### hobgoblin 内容三件套补齐(2026-11-01 登记,来源=审计发现) **实况**:敌人表 hobgoblin 行(寻址键 (1, battle, 3))数值完整在役、战斗正常运行,但内容三件套未交付——立绘、敌种语义模板、敌人系统.md 敌种表行均缺,呈现面因语义模板未成文无定义可依。登记凭据=[敌人系统](design/gdd/systems/战斗循环/敌人系统.md) v1.1「hobgoblin 缺口登记」节(2026-10-13 迭代 24 反哺④)。 @@ -14,11 +24,11 @@ #### 状态合并改累加制——同名状态重复授予改加时长(2026-10-31 登记,来源=会话提及) -**实况**:2026-10-31 用户立案并四点裁决闭合:六行 refresh 全改累加/时长不封顶/只加时长、层数与强度不变/累加量=本次授予的生效时长(技能施放行带覆盖时长时按覆盖值)。设计定稿=[增益状态](design/gdd/systems/战斗循环/增益状态.md) v1.3(2026-10-31,合并策略「刷新」改「累加」)+[地图战斗资源](design/gdd/systems/战斗循环/地图战斗资源.md) 削弱行引用句随改。查证记录:全仓设计文档、reports 与 git 全历史均无既往累加制决策,本次为新裁决、非补同步。本裁决消解「空刷新的可见性」条目(累加制下重复授予恒有变化,无空操作授予面)。 +**实况**:2026-10-31 用户立案并四点裁决闭合:六行 refresh 全改累加/时长不封顶/只加时长、层数与强度不变/累加量=本次授予的生效时长(技能施放行带覆盖时长时按覆盖值)。设计定稿=[增益状态](design/gdd/systems/战斗循环/增益状态.md) v1.3(2026-10-31,合并策略「刷新」改「累加」)+[地图战斗资源](design/gdd/systems/战斗循环/地图战斗资源.md) 削弱行引用句随改。查证记录:全仓设计文档、reports 与 git 全历史均无既往累加制决策,本次为新裁决、非补同步。本裁决消解「空刷新的可见性」条目(累加制下重复授予恒有变化,无空操作授予面)。需求卡片:reports/需求卡片-状态合并累加制批-2026-11-01.md(2026-11-01 写卡会话落位,零待裁点,开工门=U0)。 **改动面**:文档+游戏代码 -**状态**:文档设计已闭合 +**状态**:文档设计已闭合+已写卡 #### 迭代 43 批后待裁两点——名字行字号档位/换色常量退役(2026-10-30 登记,来源=批次移交) @@ -142,16 +152,11 @@ #### 营地五界面窗口化批——营地功能页点开后的呈现形态(2026-10-22 登记,来源=会话提及) -**实况**:营地场景图(卡④)把旧四柜台换成「一张可点击的场景图」,从场景图点进去的**五个功能界面**——锻造工坊/秘宝匣/天赋树(树淬炼)/奖励格图鉴/生涯记录——其**呈现形态尚未定稿**:是各开独立全屏页(生涯先例),还是作为**窗口**打开(场景根留底)。**作者 2026-10-22 明示意图=窗口打开,不是全屏页**。该形态原属卡④ §9 代拍板白名单第 2 条(非用户裁、且「缩放虚化」第三形态禁批内自选),故单独立批,不在美术设计段定值。 - -**依赖(单向)**:**强依赖卡④**(场景图素材定稿 + 五界面入口改挂)完成;卡④不依赖本条 ⇒ 排序在卡④之后。**与「营地美术素材怎么生成」无关联**(不影响出图/分层/提示词)。 - -**缺口**:① 窗口形态与叠层规则定稿(独立全屏页=场景根隐藏/单一内页切换=场景根留底);② **窗口化=场景根留底 ⇒ 会引出「背景要不要压暗/虚化」**,而该点撞上 art-bible §2(2026-10-22 缩窄后**仍禁情绪表达**,背景压暗属氛围表达仍在禁区)与卡④「缩放虚化禁批内自选」——**须在该批开工前一并裁掉**;③ 五界面各自的返回/关闭钮(卡④ v1.1 已承诺各带一个)。 -- 相关文档:卡④ §9 代拍板域 → 独立成批(呈现层+文档线);窗口形态与叠层规则写入 `LAYER_CONTRACT` 与 [camp](design/gdd/ux/camp.md)「叠层与开合」节 +**实况**:营地场景图(卡④)把旧四柜台换成「一张可点击的场景图」,从场景图点进去的**五个功能界面**——锻造工坊/秘宝匣/天赋树(树淬炼)/奖励格图鉴/生涯记录——其呈现形态原属卡④ §9 代拍板白名单第 2 条,故单独立批。**2026-11-01 用户裁三点闭合**:①承载形态=功能窗口·场景根留底+半透明压暗遮罩(交互聚焦用,复用既有模态遮罩件,现值锚 0.6)+五窗互斥单开(模态栈深恒 1)+各窗自带关闭钮(卡④ v1.1 承诺面);②ESC 优先序=有功能窗口开着先关最上层窗、无窗才进卡⑤ ESC 浮窗四态;③前置冲突消解=art-bible §2「情绪明暗禁令」整块删除(用户裁:明亮基调为正向方向,压暗属普通设计决策逐案走样张目检——该禁令查无正向拦截实例,同批修 art-bible 七处引用站)。**与「营地美术素材怎么生成」无关联**(不影响出图/分层/提示词);零新美术素材。定稿凭据:[camp](design/gdd/ux/camp.md) v2.3「叠层与开合」节+[art-bible](design/art/art-bible.md) v3.32(禁令删除批)。实现属后续卡,强依赖卡④完工(排序在卡④之后)。 **改动面**:文档 -**状态**:待文档设计 +**状态**:文档设计已闭合 #### UI 贴图重构批——元进度件仍是程序化占位(2026-10-13 登记,来源=审计发现) @@ -298,16 +303,15 @@ **状态**:已写卡+已编迭代 46 -#### 立绘清晰度回退评估——是否改用高清图(2026-10-13 登记,来源=playnote) +#### 立绘清晰度回退评估——原稿分辨率+三档显示(2026-10-13 登记,来源=playnote) -**实况**:来源=playnote 用户试玩记录「现在的立绘太丑了,像素化的粒度太低了,导致根本看不清立绘;看是否可以改回用较为高清的图片?还有一个问题是大小的问题……现在地精的图片看起来比熊地精还要大,这并不合理」。2026-10-13 用户裁定:与「第二 / 三关棋盘观感」同属**美术线更新**。**两个子问题现状不同**:子问题一=怪物大小比例不合理——**已兑现**(体量语义改生物体型〔character-design §5.2,弃强度线性映射〕+八敌逐键定档〔art-bible §8.2〕),剩余面=用户是否复核验收;子问题二=像素粒度过低/是否改回高清图——**方向已裁(2026-10-14 用户裁)**:「还是像素风格立绘,但是不需要像现在太过于像素」,定性为**精细手绘像素**(不是插画、不是 HD-2D、不回退高清图;裁决录=[美术审计-cursor会话存档](reports/美术审计-cursor会话存档-2026-10-14.md) §2.2;权威面 art-bible/character-design 口径节反哺另批),粒度问题已改派生管线(八敌源档 36–94 全过可读门槛:24 糊/32 可读/48 清楚)。[08-Alpha版本标准](design/gdd/08-Alpha版本标准.md) 未决项已随裁删除(2026-10-16 状态刷新批)。Alpha 出口裁决:Alpha 范围=主角+三个 Boss 按新口径重产,其余敌种当前可读则保留到 Beta。 +**实况**:来源=playnote 用户试玩记录「现在的立绘太丑了,像素化的粒度太低了,导致根本看不清立绘;看是否可以改回用较为高清的图片?还有一个问题是大小的问题……现在地精的图片看起来比熊地精还要大,这并不合理」。2026-10-13 用户裁定:与「第二 / 三关棋盘观感」同属**美术线更新**。**两个子问题均已定**:子问题一=怪物大小比例——体量语义改生物体型(character-design §5.2,弃强度线性映射),2026-11-01 进一步归并为三档绝对显示高;子问题二=像素粒度/是否回退高清——2026-10-14 裁不回退高清(裁决录=[美术审计-cursor会话存档](reports/美术审计-cursor会话存档-2026-10-14.md) §2.2),2026-11-01 会话查明根因=入包前 `dom_block_resize` 把原稿 189px 细节砍到 74–94(现行入包稿与原稿降采样**逐像素相同**),当日用户裁终态方案:**保留原稿分辨率、入包禁再降采样、显示按三档绝对高缩放**(小型 96=地精/巨蜘蛛/灰矮人;中型 144=主角/钩爪恐魔/熊地精;大型 188=食人魔酋长/蛛化卓尔/灰矮人石君王;宽随源比例、NEAREST)。同日裁:2026-10-14「须手绘重产」方向作废,现有形象即终稿、禁改形象。已接受项:五件源高低于档高属放大显示(主角 92/钩爪 94/熊地精 123/地精 90/巨蜘蛛 81);食人魔酋长显示宽 157 超桩盒 150。2026-10-28 为重产新增的色板额度议题(含 `#A79CB8` 去留)按用户令保留在板、另批讨论,本批不动色板。 +- 相关文档:[美术圣经](design/art/art-bible.md) §8.2 站桩立绘显示档条(v3.32,显示档定值单点)+ [角色设计](design/art/character-design.md) §5.2/§5.5 + [生图提示词卡](design/art/art-prompts.md) §5.4 按档派生工单(v2.13)+ [08-Alpha版本标准](design/gdd/08-Alpha版本标准.md) v1.22 覆盖行 +- 需求卡片:[需求卡片-立绘显示档批-2026-11-01](reports/需求卡片-立绘显示档批-2026-11-01.md) -**缺口**:还差立绘按「精细手绘像素」新口径重产的设计——整屏方向稿与地面/立绘密度同批锁(与战斗一屏样张批联动)后才可出重产工单。 -- 相关文档:[角色设计](design/art/character-design.md)(立绘规格与体量语义)+ [美术圣经](design/art/art-bible.md)(像素管线与档位) +**改动面**:美术素材+游戏代码 -**改动面**:美术素材 - -**状态**:待美术设计 +**状态**:美术设计已闭合+已写卡 #### 站桩帧动画——Alpha 定版闸前完成(2026-10-06 登记,来源=审计发现)