feat(art): T1 样张 v2 冻结批(机检闸形 A)——16/16 全绿触发四冻结

样张 v2 重出:D 投影档+整板悬崖(board_world 同款 DEPTH_PX=8 同源)+微光泛光增强+物件纹样增至四类型+S3 角嵌漏网清除;产物命名带 v2(v1 覆盖欠账清偿),报告迁 design/research/sample-v2-机检报告-2026-09-28.md。机检扩展:现行 13 条+A3 图底分离 40→55+F6 顶面立面双明度带≥18(南临空墙格实测均 106.3)+F7 DEPTH_PX 同源断言+A6 观感密度梯度均值≥4.70(v1 同口径实测 4.09×1.15,口径注记=低频双峰被墙地结构锁死、细节层次住高频)。
四冻结:①砖面=方案甲+D 投影参数+悬崖(圣经 §3.2)②色板=小人蓝 #2E86DE 定稿(UiKit 同步 #2E6E8E→#2E86DE+图例 hex)+接触带微光 #D6ECFF+类型微光五组定稿(§4.1/§4.2/§4.6.3)③动画=§8.4 帧数档冻结(死亡=灰化+程序化碎块弹飞 5 块 0.45s)④数字形制=色牌形制定稿。
圣经 v2.13(v2.9 过期头注顺手修)+图例旗色封印黑漏网修正(#C63D22→#000000)。轻闸=冒烟 557/0+ui_input_probe/ui_probe PASS。
This commit is contained in:
DKChan committed 2026-09-28 03:59:42 +08:00
1 parent d1dea82429
commit f9b0765412
5 files changed
+222 -34

No files matched your search

+11 -8
View File
@@ -1,6 +1,6 @@
# 美术圣经(Art Bible)— Dungeon Sweeper
> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**(§6 环境/§7 UI/§8 资产规范/§9 参考与反参考已于 2026-09-23 v1.8 按 D1/D2/D4/D5 框架成文;D3=§5 角色已于 v1.6 落地、v1.7 抽离独立文档;框架 2026-09-22 用户拍板,原登记于中间产物修订指导,经裁决不入库,明细归台账 125);历次修订明细见文末版本历史(现行为 v2.9)
> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**(§6 环境/§7 UI/§8 资产规范/§9 参考与反参考已于 2026-09-23 v1.8 按 D1/D2/D4/D5 框架成文;D3=§5 角色已于 v1.6 落地、v1.7 抽离独立文档;框架 2026-09-22 用户拍板,原登记于中间产物修订指导,经裁决不入库,明细归台账 125);历次修订明细见文末版本历史(现行为 v2.13)
>
> **Art Director Sign-Off (AD-ART-BIBLE)**:历次批均 SKIPPED(v1.8 §6–9 补全亦 SKIPPED)— Lean/Solo mode(非 PHASE-GATE;§6–9 已成文,full 门禁签核时机待用户表态)
> 风格基调(2026-09-10 用户定稿):地牢题材但**非暗黑风**——轻快明亮的幻想冒险风,全年龄;像素风;角色 2~3 头身
@@ -60,6 +60,8 @@
**判定与回退**:第 1 项不过 → 按原则二设计测试回退——加牌、调牌(提牌墨对比/扩牌面积皆可),禁止缩字号换字形逃避;第 2–4 项不过 → 修形不修数。样张通过 = 砖面形态与色板冻结;新增图类型/变异色板须重跑本测试(§4.3)。执行时机:正式砖面资产开工前;《HUD框架》以本节为引用依据(2026-09-07 门禁:样张测试并入 art-bible 执行)。
> **样张 v2 记录(2026-09-28,四冻结生效)**:机检 16/16 全绿(扩展断言集:A3 图底分离 Δ≥55/F6 墙格顶面立面双明度带 Δ≥18/F7 整板悬崖 DEPTH_PX 与游戏渲染常量同源/A6 观感密度梯度均值 ≥4.70=v1 实测 4.09×1.15)。**四冻结**——①砖面形态:方案甲 21 瓦片+高墙感 D 投影档+整板悬崖(§3.2 高墙瓦片体系条定稿参数);②色板:小人蓝 #2E86DE/接触带微光 #D6ECFF/类型微光五组定稿(§4.1/§4.2);③动画方案:§8.4 帧数档冻结;④数字形制:色牌形制定稿(#F5EAD3 素色直角小牌+Fusion Pixel+字号 max(18, ceil(格边×0.5))+墨三档,§7.4)。产物=`artwork/mockups/sample-batch-v2-2026-09-28.png`,机检报告=`design/research/sample-v2-机检报告-2026-09-28.md`;气质终审=批末用户目检(闸形 A,2026-09-27 拍板)。
---
## 2. 氛围与情绪(Mood & Atmosphere)
@@ -162,7 +164,7 @@
- **旗(封印印记)**:插旗动作的叙事呈现 = **封印**(玩家可见专名,2026-09-25 用户拍板,registry terminology 登记)——玩家对未开格插旗,即对该格(巢穴)实施封印,旗 = 封印印记;封印色(§4.1,现行封印黑)与格内优先级栈位(§1.2)不变。封印特效(施印瞬间 + 印记常显形态)待表现批,资产归清单 §4 演出类;现行程序化占位 = 封印黑「旗」字形(棋盘惯例:贴图在位=字形退役)。←原一;P2;术语批 2026-09-25;封印紫批 2026-09-26;封印黑批 2026-09-28
- **可挖域接触带微光(交互反馈层,2026-09-25 用户拍板)**:挖掘期,英雄格周界与可挖墙(8 向相邻未开格)的接触面画呼吸微光——正交邻墙=该侧整条边,斜向邻墙=共享角点+向两侧各延伸半条边;光只画英雄格(空间)一侧、不进墙格(与装饰变体零冲突,数字砖心不涉)。世界观口径:未开格=墙、已开格=挖出的空间,微光=空间的灯光边界。色相=蓝族浅一档(§4.2 蓝条;与主角蓝框的分层归样张批);呼吸=§2.1 挖掘期唯一在动元素,减动效停格。角点为斜墙与正交墙共享、不逐格归因,逐格指认=悬停金框(现役)。旧「墙格整框绿相呼吸」随本条退役(实现切换归表现批,`DIG_EDGE` 绿相退役)。←§2.1;§4.2;P1
- **墙体**:圆角砌块堆叠,禁尖刺装饰——尖刺专属危险语义,装饰不得伪装逻辑差异。←原三
- **高墙瓦片体系(2026-09-26 定稿,样张批追认)**:未挖格=**一整块 32×32 自含凸起岩体**(方案甲核心定义);素材语义名——未开格素材=**墙瓦片**,已开格素材=**地面瓦片**(术语 2026-09-26 用户立)。**边界=墨线纪律**:墙瓦片与相邻格分界一律 1px 深墨线、直线贴格边、零锯齿;墨线职责=分隔,不追求与地面融合(Tiny Dungeon 样图实证调研,见 `design/research/terrain-walls-source-evaluation-2026-09-25.md`)。**光照=单一北受光**:北缘=墨线内侧 1px 微亮棱(就地取色提亮,禁宽亮带);西/东缘=墨线后直进纹理、不加修饰;南缘=墨线+立面窄暗条(约 1/3 格高,横层理叠石、禁竖条纹栅栏感)。**凹角**:角点单像素落线;南立面侧凹角加 1px 立面收头——带身与转角竖线同列收尾,禁悬空、禁突出(v9.1/v9.2 两版返工实证)。现行定稿=`game/assets/art/board/terrain_*`(16 唯一墙瓦片+5 地面瓦片变体;词表与查表逻辑见 `design/research/board-tile-vocab-plan-a-2026-09-26.md`)。←原三;台账 164
- **高墙瓦片体系(2026-09-26 定稿,样张批追认)**:未挖格=**一整块 32×32 自含凸起岩体**(方案甲核心定义);素材语义名——未开格素材=**墙瓦片**,已开格素材=**地面瓦片**(术语 2026-09-26 用户立)。**边界=墨线纪律**:墙瓦片与相邻格分界一律 1px 深墨线、直线贴格边、零锯齿;墨线职责=分隔,不追求与地面融合(Tiny Dungeon 样图实证调研,见 `design/research/terrain-walls-source-evaluation-2026-09-25.md`)。**光照=单一北受光**:北缘=墨线内侧 1px 微亮棱(就地取色提亮,禁宽亮带);西/东缘=墨线后直进纹理、不加修饰;南缘=墨线+立面窄暗条(约 1/3 格高,横层理叠石、禁竖条纹栅栏感)。**凹角**:角点单像素落线;南立面侧凹角加 1px 立面收头——带身与转角竖线同列收尾,禁悬空、禁突出(v9.1/v9.2 两版返工实证)。现行定稿=`game/assets/art/board/terrain_*`(16 唯一墙瓦片+5 地面瓦片变体;词表与查表逻辑见 `design/research/board-tile-vocab-plan-a-2026-09-26.md`)。**高墙感 D 投影档+整板悬崖(样张 v2 定稿 2026-09-28,用户 2026-09-27 四变体挑档)**:南临空墙格=立面口沿高光 2px `Color8(196,172,132)`+双段暗带(0.16/0.25 格边,黑罩 α0.60/0.82);北邻墙地面格=三段渐隐投影(顶带 0.22 格边,α0.28 起);整板悬崖=板底/右侧 `DEPTH_PX 8px` 暗面+列分隔竖缝+岩层横纹+口沿高光+接触 AO+底线收边+悬浮影(游戏 `board_world.gd` 同款结构件,样张脚本与游戏渲染常量同源——机检 F7 承载)。←原三;台账 164;样张 v2 批 2026-09-28
- **变异格形状通道**(双通道之"形",与色无关):底砖圆角外轮廓不变,砖面内缘绘一圈定宽专属几何纹带(纹带形全作不与他类共用),砖心留白予数字与旗;验收标准=**灰度截图下仍可分类**。种类清单 = 地形变异六类型已定稿(地形变异 GDD;荆棘丛/藤蔓缠绕/岩浆/烬覆/落石/矿尘):**纹带形按轴只分两种**——伤害轴(荆棘丛/岩浆/落石)= 刺/缺排斥形,信息轴(藤蔓缠绕/烬覆/矿尘)= 遮蔽/缠绕形;同轴跨图类型只做色板变体(§4.3 `variant_tint` 槽),不做新纹形。样张批增查:岩浆纹带橙红须与危险红互辨(变异格不是雷,色相邻近混淆风险);信息轴遮蔽呈现不得侵入数字色牌占位区(§1.4 验收 1 延伸)。←原一(纹理位次第 4,让位于数字/小人/旗);原三
### 3.3 UI 形状语法(方向指导,细则迁 §7.1)
@@ -189,7 +191,7 @@
- **封印黑 `#000000`**|封印(插旗)宣告色,无色相:玩家的宣告"此格封印"(色史:旗朱 `#C63D22` →封印紫 `#7C3AA8` 2026-09-26→**封印黑 2026-09-28 用户拍板**——紫色与微光蓝族〔魔法微光 256° 等〕色相冲突,黑色无色相天然避开 300°–345° 禁入带与全部微光色带;未开格墙顶明度 ≈113 对纯黑对比 ≥4.4:1,旗杆米白保可读)。旗朱随封印紫批退役,红族自此只剩危险红。←原一;P2;封印紫批 2026-09-26;封印黑批 2026-09-28
- **危险红 `#A8321F`**|危险色:雷=被惊动的巢穴,兑现档红,更深更沉(2026-09-13 更名,旧称"机关红"随隐喻换轴退役;色值不变)。←原三;P2
- **奖励金 `#F0A828`**|已兑现的收益:金币/宝箱/蜡封,全作唯一亮金。←P2;§2.3/2.4
- **小人蓝 `#2E86DE`**|小人主色:棋盘唯一"己方",与光标准线同族(候选值,样张批 §1.4 冻结终稿)。←P1;§2.1
- **小人蓝 `#2E86DE`**|小人主色:棋盘唯一"己方",与光标准线同族(样张 v2 定稿 2026-09-28;游戏 UiKit.HERO_BLUE 已同步 #2E6E8E→#2E86DE)。←P1;§2.1
- **数字色牌 `#F5EAD3`**|数字底具:素色暖纸白直角小牌,数字一律垫于其上;素面无纹理、不随图类型/装饰变体变,数字可读不依赖格底即由本牌承载。←原二
**对比硬指标(可测)**:数字可读性由色牌承载——**数字色牌素色恒定 L≥0.70、一切数字墨 L≤0.027**(WCAG 相对亮度)⇒ 任意牌墨组合 **≥4.5:1 恒成立**(WCAG AA)。实测样例:#33261B / #F5EAD3 = **12.3:1**;#4A1E14 / #F5EAD3 = **11.8:1**;#132E36 / #F5EAD3 = **12.0:1**。格底槽(含全部图类型)相对亮度 **L≥0.30**(明亮为皮)、HSV 饱和 **≤0.55**、避 Boss 禁入色相带——格底不再承担数字对比义务;物件识别不依赖格底(§5.1 轮廓通道),旗面、金色不作识别依赖。←原二;地形变异 AC-9
@@ -198,10 +200,10 @@
- **红只说危险**:危险红=兑现档(旗朱预告档随封印紫批退役,红族单档)。禁:红不得用于奖励、装饰与常规 UI(微光群伤组除外——其为类型先验色带域,见「类型微光色带」条,色相刻意错开语义红)。←原三;P2;§2.1;封印紫批 2026-09-26
- **金只说收益与兑现**(奖励、结算、胜利)。禁:金不得作危险障碍色、不上格底、不作日常 UI 强调(防通胀;微光通用增益组的芥末黄 = 类型先验色带域,非收益语义金)。←P2;P3;§2.2–2.4
- **蓝只说己方与冷静信息**(小人、光标、工具信息——含可挖域接触带呼吸微光,蓝族浅一档,2026-09-25 拍板;旧可挖域绿相随接触带方案退役)。禁:蓝不得表示敌方危险;暮蓝 `#5A6C8C` 为失败独占(§2.5),只作全屏氛围,不作物件色。←P1;§2.5
- **蓝只说己方与冷静信息**(小人、光标、工具信息——含可挖域接触带呼吸微光,蓝族浅一档 `#D6ECFF`〔样张 v2 定稿 2026-09-28,游戏 UiKit.CONTACT_GLOW 同值〕,2026-09-25 拍板;旧可挖域绿相随接触带方案退役)。禁:蓝不得表示敌方危险;暮蓝 `#5A6C8C` 为失败独占(§2.5),只作全屏氛围,不作物件色。←P1;§2.5
- **紫赤只说 Boss 与精英** `#8F2F6A`(色相 323°):郑重来自色相独占,不来自压暗。禁:**HSV 色相 300°–345° 为全场禁入带**,其余资产(含 UI 与粒子、含类型微光)及图类型色板不得落入。←§2.6;原三
- **绿只说自然生机**(环境植被;恢复类状态若有则用绿——待增益状态定夺)。**例外:类型微光治疗组**(类型先验色带,见下条)。禁:绿不得承载逻辑状态(微光色带除外),不得与红构成唯一区分对。←原三;T1 裁决 2026-09-22
- **类型微光色带 = 格面类型先验专用逻辑色带**(2026-09-22 用户裁决,未开格类型预读的色彩通道):未开格常显类型微光属逻辑信息色彩,五组候选色相——**通用增益组**(attack/defense/weaken/action/gp 五族)芥末黄 `#D6C13A`(≈52°)、**治疗组**(heal)黄绿 `#5CB83A`(≈104°)、**穿刺组**(pierce)青 `#2E9E9E`(≈180°)、**魔法组**(magic)紫罗兰 `#7B5BD6`(≈256°)、**群伤组**(blast)绯红 `#FF2D55`(≈349°,刻意避开危险红色相段与 300°–345° 禁入带)——均候选值,样张批(§1.4)冻结终值并抽测组间互辨。分域纪律:微光色相只承载类型先验,不迁移复用为物件/阵营/UI 语义色;微光 = **色相+明度双码**(2026-09-28 角嵌退役批起明度梯度承载类型——§2 微光明度例外:梯度不得压破格底明度档/三态分类);色弱玩家的类型主通道 = 微光双码。←T1 裁决 2026-09-22;角嵌退役批 2026-09-28;§4.6.3
- **类型微光色带 = 格面类型先验专用逻辑色带**(2026-09-22 用户裁决,未开格类型预读的色彩通道):未开格常显类型微光属逻辑信息色彩,五组色相——**通用增益组**(attack/defense/weaken/action/gp 五族)芥末黄 `#D6C13A`(≈52°)、**治疗组**(heal)黄绿 `#5CB83A`(≈104°)、**穿刺组**(pierce)青 `#2E9E9E`(≈180°)、**魔法组**(magic)紫罗兰 `#7B5BD6`(≈256°)、**群伤组**(blast)绯红 `#FF2D55`(≈349°,刻意避开危险红色相段与 300°–345° 禁入带)——**样张 v2 定稿(2026-09-28)**,组间互辨抽检随机检报告;v2 呈现参数=内缘带状泛光 α170/带宽 cell÷8(亮度不压格底明度档,§2 微光例外)。分域纪律:微光色相只承载类型先验,不迁移复用为物件/阵营/UI 语义色;微光 = **色相+明度双码**(2026-09-28 角嵌退役批起明度梯度承载类型——§2 微光明度例外:梯度不得压破格底明度档/三态分类);色弱玩家的类型主通道 = 微光双码。←T1 裁决 2026-09-22;角嵌退役批 2026-09-28;§4.6.3
- **金/红兼作极性色相槽(§4.6)**:极性(白话:同一次兑付的正负方向——正 = 收益侧,负 = 代价侧;行为×格型→符号矩阵见极性提案 R2)的视觉取色只在这两族间——有利兑付 = 金族,有害兑付 = 红族,不新增语义色。←§4.6;原二
### 4.3 图类型色板换皮规则(board_type)
@@ -307,7 +309,7 @@
| action | 行动族 | 行动点/疾步 |
| gp | 金币族 | 钱币/财货 |
- **呈现约束(2026-09-28 角嵌退役批更新,原「双通道」退役)**:全部未开格呈现**类型微光单通道**(五组色带,§4.2「类型微光色带」,色相+明度双码;候选值样张批冻结);不呈现极性、不呈现雷/安——推雷仍是扫雷本征推理;类型分布即先验(提案 R3 拍板),**微光误读率 = 提案 §4 指标 3** 保留(角嵌误读率指标随之转微光),样张批微光组间互辨抽测含明度档互辨。
- **呈现约束(2026-09-28 角嵌退役批更新,原「双通道」退役)**:全部未开格呈现**类型微光单通道**(五组色带,§4.2「类型微光色带」,色相+明度双码;样张 v2 定稿 2026-09-28);不呈现极性、不呈现雷/安——推雷仍是扫雷本征推理;类型分布即先验(提案 R3 拍板),**微光误读率 = 提案 §4 指标 3** 保留(角嵌误读率指标随之转微光),样张批微光组间互辨抽测含明度档互辨。
- **状态声明**:键集九值封闭(attack/defense/heal/blast/weaken/pierce/magic/action/gp,与 RewardTable 现行 cell_type 词表一致),扩键走本节修订。
- 与 §4.6.1 的关系:同语义域的键(attack↔attack_up 等)可共族设计,键分立、纹样须可区分(格面小记号级对槽内图标级)。
@@ -424,9 +426,9 @@
- **交付格式**:PNG 透明底;动画 = 序列帧或引擎精灵表(SpriteFrames),帧尺寸恒定、横向等宽排列(候选)。
- **命名规范(候选草案)**:`<域>_<对象键>_<状态|变体>[_<序号>].png`,全小写 snake_case;**对象键 = 数据表主键**(effect_id/reward_id/cell_type/enemy_id——图标键契约 §4.6 的文件侧延伸:资产文件名键 = 图标键,全局恒定禁运行时换图);图类型变体后缀 = board_type 键(`_dungeon`/`_underdark`/`_deep_underdark`);候选评审件与终稿分目录(`candidates/` 承载评审件,终稿目录归表现批定)。
### 8.4 帧数规格(候选档,战斗一屏样张批冻结)
### 8.4 帧数规格(样张 v2 冻结 2026-09-28)
- 待机循环 4 帧(候选);攻击/技能准备 6 帧单次(候选);受击 2 帧(候选);死亡 = 灰化+碎裂退场(§4.6.4 语义硬规则),碎裂序列 4–6 帧(候选);帧时长与结算节拍对齐(预告时序 = 下一拍,§4.6.4)。
- **帧数规格(样张 v2 冻结,2026-09-28)**:待机循环 4 帧;攻击/技能准备 6 帧单次;受击 2 帧;死亡 = 灰化+碎裂退场(§4.6.4 语义硬规则)——切片实装=程序化 tween(灰化罩+碎块弹飞 5 块 0.45s,挂 `unit_died`),序列帧归 ✦ 缺料清单;帧时长与结算节拍对齐(预告时序 = 下一拍,§4.6.4)。
- **方向集(2026-09-24 用户拍板)**:棋盘小人=**4 向**(下/上/侧,侧向左右镜像共用一份画稿);斜向移动/挖掘按**主导轴吸附最近正交向**呈现,不出 45° 斜向帧(斜向信息由位移轨迹与目标格预告承载,ITB 实态同款)。镜像与「旗面恒画右」纪律(character-design.md 冒险背包条)的相容归属:棋盘小人默认镜像豁免、旗右纪律限立绘侧——**代拟口径,样张批追认**。
### 8.5 结构件完整性与参考核验(2026-09-24 用户立规)
@@ -471,6 +473,7 @@
- **v2.10(2026-09-26)封印紫批**(用户拍板:插旗色 旗朱 #C63D22 → **封印紫 #7C3AA8**,色相 ≈267°):§4.1 旗朱条改写为封印紫条(候选值样张批冻结;禁入带合规+与魔法微光/妨害紫间距登记)、§4.2 红只说危险改单档(旗朱预告档退役)、§3.2 旗条/§1.4 验收 4/§4.3 不变槽/§3.2 变异互辨/§5.4 速览随批。**语义面**——封印自术语批(2026-09-25)获专属色相,红族收敛为危险红单档;攻击预告/弹道/拒绝等非封印红统一归危险红族(RED_MINE)。**连带**——character-design §5.4 背旗、battle.md 三处、关卡节点地图 Boss 描边、清单封印特效行随批;comfyui-prompts 生图卡颜色词随样张 v2 重生成。
- **v2.11(2026-09-28)封印黑批**(用户拍板:封印色 封印紫 #7C3AA8 → **封印黑 #000000**——紫色与微光蓝族色相冲突,黑色无色相天然合规):§4.1 封印紫条改写封印黑条、§3.2 旗条/§1.4 不变槽/§4.3/§5.4 速览随批;代码 UiKit.SEAL_PURPLE→SEAL_BLACK 改名迁移+board_view/board_fx_view 换色+样张脚本同步;胜利彩带装饰紫位改亮金(紫赤系 Boss 独占不入装饰);远程生图单主角旗 purple→black 十六进制锁色重锁。历史行(v2.10 等)按 ADR 纪律留痕不改
- **v2.12(2026-09-28)角嵌退役批**(用户裁「微光的展示只有微光,不要加额外的箭头或者加号在格子里面」——样张 v1 否决原因之一):未开格类型角嵌纹样**彻底退役**——类型预读改类型微光单通道(色相+明度双码),§2 微光明度恒定开例外(明度梯度承载类型,梯度不压格底明度档/三态分类),色弱类型主通道=微光双码;§1.2 优先级栈/§1.4 样张清单与验收 2/§3.2 角嵌条(标退役)/§3.4/§4.2 色带条/§4.5⑨/§4.6.3 呈现约束同步;已开格物件纹样(角嵌于砖缘画法动词)不在退役面;机检新增「微光格零墨色附加像素」断言;角嵌误读率指标转微光误读率 |
- **v2.13(2026-09-28)样张 v2 冻结批(M-1 迭代 2 T1,机检闸形 A——全过即冻结)**:§1.4 增样张 v2 记录(机检 16/16:现行 13 条+A3 上调 Δ≥55/F6 顶面立面双明度带 Δ≥18/F7 悬崖 DEPTH_PX 同源/A6 观感密度梯度 ≥4.70=v1 实测 4.09×1.15——v1 四否决原因断言化收官);**四冻结落文**——①砖面形态:§3.2 高墙瓦片体系条增「D 投影档+整板悬崖」定稿参数(口沿高光 2px Color8(196,172,132)/立面双段暗带 0.16+0.25 格边 α0.60·0.82/地面投影 0.22 格边三段渐隐 α0.28/悬崖 DEPTH_PX 8px board_world 同款);②色板:§4.1 小人蓝候选→定稿 #2E86DE(UiKit 同步)+§4.2 接触带微光色值 #D6ECFF 定稿+类型微光五组候选→定稿(v2 呈现 α170/带宽 cell÷8);③动画方案:§8.4 帧数规格候选档→冻结(待机 4/攻击 6/受击 2/死亡=灰化+程序化碎块弹飞 5 块 0.45s,序列帧归缺料清单);④数字形制:色牌形制定稿(#F5EAD3 直角小牌+Fusion Pixel+字号 max(18,ceil(格边×0.5))+墨三档)。产物命名带 v2(v1 被覆盖欠账清偿),报告迁 `design/research/`;连带=图例旗色封印黑漏网修正(#C63D22→#000000) |
- **v2.8(2026-09-25)可挖域接触带微光定稿批**(用户两拍板:①画法=接触带·空间侧——光画英雄格周界,正交邻墙=整边、斜向邻墙=角点+两半边;②色相=蓝族浅一档,顺路清偿旧 DIG_EDGE 绿相违 §4.2 绿禁则):§3.2 新增「可挖域接触带微光」条(画法/光只住空间一侧/角点不逐格归因、指认=悬停金框/呼吸与减动效守 §2.1/实现切换归表现批);§2.1 承载元素、§4.2 蓝条随批;battle.md 注记随批。背景=用户世界观口径「未开格=墙、已开格=挖出的空间」,微光=空间的灯光边界。
- **v2.7(2026-09-25)封印术语批**(用户拍板:Node2D 实现后「插旗」动作等价为**封印**——玩家对未开格插旗即对该格巢穴实施封印,旗 = 封印印记;机制键与规则全不变):§3.2 新增「旗(封印印记)」条——呈现语义/旗朱与栈位不变/封印特效(施印瞬间+印记常显形态)待表现批/现行占位 = 旗朱「旗」字形;§2.5 失败承载元素措辞随批(插过的旗 = 封印印记)。**登记面**——registry terminology 新增「封印」词条、00-游戏概念 术语层级专名表随收;连带同步:battle.md 呈现注记、art-assets-checklist §4 演出类新增封印特效两件(施印特效+印记常显)、art-status-checklist P3 行、character-design.md §5.4 插旗条注记(主角即插旗者)。**关联面**——可挖域接触带微光方案(用户同日提出:微光画英雄格周界接触面,正交整边/斜向角点+两半边)评估可行,实现归表现批,未入本批。
- **v2.6(2026-09-25)世界观对齐扫描批(甲档回填 + 完美排雷钩子收口 + 引用锚内联;用户三拍板)**:①**§4.6.4 敌种甲档回填数据实态**——bugbear(ward→light)/ ogre_chief(heavy→light)/ drider(heavy→ward),并注记甲档事实源 = `enemy.tres` armor_type(2026-09-18 甲重配批后 L1 全轻甲、L2 除 drider 外全轻甲、L3 duergar/duergar_king 重甲);连带修订 character-design.md §5.5(熊地精轻甲化/食人魔弃金属甲板改裸身皮条/卓尔改魔法甲符纹)与 comfyui-prompts.md v2.8(熊地精/食人魔/卓尔三卡提示词随改)——食人魔视觉重设计经用户拍板「按最新设定,裸身+魔法甲符纹」。②**§2.2 完美排雷钩子收口**——「若…落实…待 GDD 定夺」改现行事实(零误标且至少标中一面旗→追加第二份清图兑付+结算高光行,地图战斗资源 GDD 已定稿)。③**引用锚内联**——§3/§4 尾注 P1–P4 支柱语义内联(概念期 brainstorm 编号,现行 GDD 树不单列),§1.4 两处 game-concept 编号引用改语义内联。扫描背景=用户发起的圣经×关卡/世界观对齐审计;变异六类型/格面九类/状态九键/奖励 19 键/敌种八键/三柜台钥石/三关色板方向经核对全部一致,零其余不符。
@@ -0,0 +1,35 @@
# 样张 v2 机检报告(2026-09-28,M-1 迭代 2 T1)
生成:`python tools/render_sample_sheet.py`;断言事实源 = 画法参数四源对照表-2026-09-26.md §6 + 迭代 2 立体/密度扩展。
## v1 否决原因 → 断言映射
| 否决原因(2026-09-28 用户) | 断言承载 |
|---|---|
| ①显示太丑(总纲) | A6 观感密度(整板明度 std ≥50.9=v1 实测 44.31×1.15)+既有装饰变体 ≥2 种 |
| ②封印色冲突 | 封印黑 #000000(9b6fcf6 已落,A1a 对表自动覆盖) |
| ③立体感不够 | A3 阈值 40→55 + F6 顶面/立面双明度带 Δ≥18 + F7 整板悬崖 DEPTH_PX 同源 |
| ④微光格只留微光 | F5c 微光段零 draw_inlay(d1dea82 已落) |
## 断言明细
| 断言 | 判据 | 结果 | 明细 |
|---|---|---|---|
| F1 | 方案甲 8 邻拼装(词表查表,禁整块) | PASS | 错位 0 处;用件 15 种 ['center', 'center_crack', 'center_speckle', 'end_n', 'end_s', 'end_w', 'hrun', 'in_nw', 'in_sw', 'n', 'nw', 's', 'sw', 'vrun', 'w'] |
| F2 | 旗仅出现于未开格 | PASS | 旗位 (1, 2) 格态=W |
| F3 | 小人脚锚=自底边 25% 线(两态) | PASS | 脚 y=[213.75, 258.75] 期望=[213.75, 258.75] |
| F4 | 数字 0 格无字形(0=纯安全格裸地面) | PASS | 0 态格 38 个(示例 (4,4));数字表含 0 键=False |
| F5a | 接触带微光⊆英雄格周界(空间侧,不进墙格) | PASS | 微光 bbox=(86, 176, 119, 230) 英雄格=(90, 180, 135, 225) |
| F5b | 类型微光禁整格染色(中心 50% 区零染色像素) | PASS | 五格中心区全净 |
| F5c | 微光格零附加图形(微光段无角嵌调用——角嵌退役,微光只留微光) | PASS | 微光段无角嵌调用 |
| A1a | 色板对表圣经 §4.1 冻结值 | PASS | {'INK': '#33261B', '青墨': '#132E36', '赭墨': '#3C250C', '锈墨': '#4A1E14', 'PLATE': '#F5EAD3', '封印黑': '#000000', '危险红': '#A8321F', '奖励金': '#F0A828'} |
| A1b | 禁入带 HSV300°-345° 零命中 | PASS | 命中 0 像素(抽样) |
| A2 | 拼缝周界闭合(墙侧 2px 墨线 <70) | PASS | 全部墙地边界墨线在位 |
| A3 | 墨×牌 WCAG≥4.5:1 + 图底分离 Δ≥55(立体强化上调——否决③,v1 实测 61.9) | PASS | [('青墨', 12.0), ('赭墨', 12.0), ('锈墨', 11.8)];墙顶 113 vs 地面 51 |
| F6 | 墙格顶面/立面双明度带(南向临地墙格 Δ≥18,体积感机器代理) | PASS | 临地墙格 14 个;最小 Δ 76.3;均 Δ 106.3(v1 实测均 71.6) |
| F7 | 整板悬崖 DEPTH_PX 与 game 渲染常量同源(board_view.gd 解析) | PASS | DEPTH_PX=8.0(已解析);悬崖带均亮 69(<100);扩展 +8px |
| A6 | 观感密度:明度梯度均值 ≥4.70(v1 实测 4.09 上调 15%——高频细节能量) | PASS | 梯度均值 5.20(低频双峰由 A3 承载) |
| A5 | 画布四缘 2px 净空(零溢出) | PASS | 缘带内容像素 0 |
| A4 | 混排相融(游戏在库资产+UiKit 语义色) | PASS | 小人源 32×32(裁透明留白后 (19, 20))/立绘 48×48/状态图标 32×32 原件;INK/旗朱/奖励金 == ui_kit.gd |
结论:**全绿**(16/16 PASS)。机检全过 = 四冻结(砖面形态/色板/动画方案/数字形制)生效落码;气质终审 = 批末用户目检(闸形 A,2026-09-27 拍板)。
+2 -2
View File
@@ -12,8 +12,8 @@ signal closed
const ENTRIES := [
["#C9AF83", "完整覆尘地砖", "未开格——左键挖开(1AP,须相邻)· 右键插旗(1AP)"],
["#B39A78", "碎裂裸土", "已开 0 格——可通行,左键移动(免费)"],
["#C63D22", "旗", "一次性承诺(不能拔)——轮末自动判定标中;插错可左键直接挖开(安全格零奖励、雷格吃挖雷惩罚)"],
["#2E6E8E", "小人", "探险者——8 向相邻未开格常驻微光 = 可挖域"],
["#000000", "旗(封印印记)", "一次性承诺(不能拔)——轮末自动判定标中;插错可左键直接挖开(安全格零奖励、雷格吃挖雷惩罚)"],
["#2e86de", "小人", "探险者——8 向相邻未开格常驻微光 = 可挖域"],
["#F0A828", "金徽章", "已开格奖励身份 icon(旗之下、数值之上,不进数字区)"],
["#33261B", "状态槽空态", "无状态效果时槽位隐藏,数据框上移补位——非异常"],
]
+1 -1
View File
@@ -31,7 +31,7 @@ const RED_MINE := Color8(150, 44, 36) # 引爆雷字朱(已开雷格"
const RED_FORBID := Color8(120, 60, 50) # 禁止框朱
const RED_ALERT := Color8(200, 60, 48) # 报错朱
const HERO_BLUE := Color8(46, 110, 142) # 小人蓝
const HERO_BLUE := Color8(46, 134, 222) # 小人蓝 #2E86DE(样张 v2 定稿 2026-09-28——圣经 §4.1 候选值冻结;旧 #2E6E8E 收敛期快照退役)
const BOSS_PURPLE := Color8(143, 47, 106) # 紫赤(Boss 专属)
const DEBUFF_PURPLE := Color8(122, 66, 148) # 妨害紫(意图 ☠)
+173 -23
View File
@@ -1,31 +1,37 @@
# -*- coding: utf-8 -*-
"""战斗一屏样张验收图生成脚本 v1(2026-09-26,循环 1 T1)。
"""战斗一屏样张验收图生成脚本 v2(2026-09-28,M-1 迭代 2 T1)。
v0 四 FATAL 案底(2026-09-26 用户否决)全部断言化——生成即验,不过闸不出图:
v1 用户否决四原因(2026-09-28)全部断言化——生成即验,不过闸不出图:
F1 未开格 = 方案甲缘件 8 邻拼装(词表查表,禁整块 center 铺满)
F2 旗仅出现于未开格
F3 小人脚锚 = 自底边 25% 线(⚠ 纵向比例一律自底边口径)
F4 数字 0 格无字形(纯安全格 = 干净裸地面)
F5 微光仅带状:接触带微光只画英雄格周界空间侧;类型微光禁整格染色(中心 50% 区零像素)
程序化四件审计(§9 初级验收授权):
F5 微光仅带状:接触带微光只画英雄格周界空间侧;类型微光禁整格染色;微光格零附加图形(角嵌退役)
F6 墙格顶面/立面双明度带(否决③立体感——南向临地墙格 Δ≥18,体积感机器代理)
F7 整板悬崖 DEPTH_PX 与 game 渲染常量同源(board_view.gd 解析——否决③立体感)
程序化审计(§9 初级验收授权 + 迭代 2 扩展):
A1 色板对表圣经冻结色板 + 禁入带(HSV 300°-345°)全图扫描
A2 拼缝周界闭合(墙↔地边界墙侧 2px 墨线带亮度 <70)
A3 明度对比(数字墨×色牌 WCAG ≥4.5:1;图底分离)
A3 明度对比(数字墨×色牌 WCAG ≥4.5:1;图底分离 Δ≥55——否决③,v1 实测 61.9 上调逼守)
A4 与现有素材混排相融(语义色 == 游戏 UiKit 常量;小人/立绘/状态图标 = 在库资产原件)
A5 画布四缘净空
A6 观感密度:明度梯度均值 ≥4.70(否决①「显示太丑」总纲代理——v1 同口径实测 4.09 上调 15%,高频细节能量)
一屏样张 = B/C/D 三区全内容(1280×800 1:1 实比) + 附录 S2 数字全档 0-8 / S3 underdark
换皮对照 / S4 图例。内容清单 = art-bible §1.4(九组,缺项即无效)。
素材源 = game/assets/art(board 21 瓦片 + character 小人/立绘)+ ui/icons 状态图标;
素材不入 git——先查本仓库,缺位回退主检出(D:/code/g-plan2)。
词表事实源 = design/research/board-tile-vocab-plan-a-2026-09-26.md;画法参数事实源 =
artwork/mockups/画法参数四源对照表-2026-09-26.md(四源对表先行产物)。
输出 = artwork/mockups/sample-batch-v1-2026-09-26.png + sample-v1-机检报告-2026-09-26.md。
design/research/画法参数四源对照表-2026-09-26.md(四源对表先行产物)。
输出 = artwork/mockups/sample-batch-v2-2026-09-28.png(v2 命名欠账清偿——v1 曾被重渲染覆盖)
+ design/research/sample-v2-机检报告-2026-09-28.md。
用法:python tools/render_sample_sheet.py
"""
from PIL import Image, ImageDraw, ImageFilter, ImageChops, ImageFont
import os
import sys
import math
import re
import hashlib
from collections import deque
@@ -45,8 +51,8 @@ def asset_root(*parts):
BOARD_DIR = ("game", "assets", "art", "board")
CHAR_DIR = ("game", "assets", "art", "character")
ICON_DIR = ("game", "assets", "ui", "icons")
OUT_PNG = os.path.join(ROOT, "artwork", "mockups", "sample-batch-v1-2026-09-26.png")
OUT_REPORT = os.path.join(ROOT, "artwork", "mockups", "sample-v1-机检报告-2026-09-26.md")
OUT_PNG = os.path.join(ROOT, "artwork", "mockups", "sample-batch-v2-2026-09-28.png")
OUT_REPORT = os.path.join(ROOT, "design", "research", "sample-v2-机检报告-2026-09-28.md")
T_FONT = asset_root("artwork", "ui-reuse-2026-09-23",
"4-字体", "fusion-pixel-12px(OFL)", "fusion-pixel-12px-proportional-latin.ttf")
ZH_FONT = r"C:\Windows\Fonts\msyh.ttc"
@@ -216,6 +222,31 @@ def floor_variant(x, y):
return int(hashlib.md5(("floor%d_%d" % (x, y)).encode()).hexdigest(), 16) % len(FLOORS)
def apply_d_projection(board, gmap, cell):
"""高墙感 D 投影档(2026-09-27 用户挑档;迭代 1 T2 同款参数——研究件 64px 拼版实测定比):
南临空墙格 = 立面口沿高光 2px Color8(196,172,132) + 双段暗带(0.16/0.25 格边,黑罩 α0.60/0.82);
北邻墙地面格 = 三段渐隐投影(顶带 0.22 格边,α0.28 起)。立体断言 F6/A6 的渲染承载。"""
overlay = Image.new("RGBA", board.size, (0, 0, 0, 0))
d = ImageDraw.Draw(overlay)
HILITE = (196, 172, 132)
seg1, seg2 = int(cell * 0.16), int(cell * 0.25)
for y in range(gmap.h):
for x in range(gmap.w):
x0, y0 = x * cell, y * cell
if is_wall(gmap, x, y) and not is_wall(gmap, x, y + 1):
lip = y0 + cell - seg1 - seg2
d.rectangle([x0, lip, x0 + cell, lip + 2], fill=HILITE + (255,))
d.rectangle([x0, lip + 2, x0 + cell, lip + 2 + seg1], fill=(0, 0, 0, 153))
d.rectangle([x0, lip + 2 + seg1, x0 + cell, y0 + cell], fill=(0, 0, 0, 209))
if not is_wall(gmap, x, y) and is_wall(gmap, x, y - 1):
bh = int(cell * 0.22)
for i, a in enumerate([71, 36, 14]):
d.rectangle([x0, y0 + i * (bh // 3), x0 + cell, y0 + (i + 1) * (bh // 3)],
fill=(20, 14, 8, a))
board.alpha_composite(overlay)
return board
# ══ D 区 10×10 样张板(内容布置见对照表 §6/§1.4 内容清单) ══
BOARD_ROWS = [
"WWWWWWWWWW",
@@ -239,7 +270,7 @@ HERO_DIGIT_AT = (2, 5) # 小人与数字同格(6)——验蓝框不覆盖文
NEST_AT = (5, 4) # 雷格巢穴(已开,程序占位+危险红)
GLOW_CELLS = [(4, 2, "attack"), (5, 2, "heal"), (8, 3, "blast"),
(6, 4, "pierce"), (7, 6, "magic")] # 五组;attack+heal 相邻并列
INLAY_RESULT = {(4, 6): "attack", (5, 6): "gp"} # 已开结果格物件纹样
INLAY_RESULT = {(4, 6): "attack", (5, 6): "gp", (6, 6): "heal", (3, 7): "defense"} # 已开结果格物件纹样(v2 增至四类型)
DIGITS = {(3, 4): 3, (3, 5): 1, (4, 5): 2, (2, 5): 6, (7, 4): 8, (7, 5): 7,
(4, 6): 5, (5, 6): 4} # 0 格=已开无字形(纯安全格全体现)
VARIANT_FLOOR_AT = (4, 5) # 装饰变体底色牌示例(强制 floor 变体 3)
@@ -248,6 +279,67 @@ CELL_D = 45 # 1280 基座 10×10 板实比(art-bible §8.1)
HERO_PX = 48 # 32 源 ×1.5(台账 161 档)
GROUND_FRAC = 0.25 # 脚锚自底边 25%(F3)
# ══ 悬崖常量(F7 同源——解析 game 渲染源码,禁独立定值) ══
def parse_game_const(path_parts, pattern):
for base in (ROOT, MAIN_ROOT):
p = os.path.join(base, *path_parts)
if os.path.exists(p):
m = re.search(pattern, open(p, encoding="utf-8").read())
if m:
return float(m.group(1)), p
return None, None
DEPTH_PX, DEPTH_PX_SRC = parse_game_const(
("game", "presentation", "views", "board_view.gd"), r"const DEPTH_PX\s*:?=\s*([0-9.]+)")
DENSITY_MIN = 4.70 # 观感密度下限(明度梯度均值)= v1 同口径实测 4.09 × 1.15(否决①总纲代理,迭代 2 白名单校准)
FACADE_MIN = 18.0 # 顶面/立面双明度带下限(否决③体积感机器代理)
WALL_FLOOR_MIN = 55 # 图底分离下限(v1 断言 40→上调,v1 实测 61.9)
def _gd_darkened(c, k):
return tuple(int(v * (1.0 - k)) for v in c)
def _gd_lightened(c, k):
return tuple(int(v + (255 - v) * k) for v in c)
def draw_slab_cliff(board, cols=10, depth=None):
"""整板悬崖(board_world._draw 同款结构件镜像——同源 DEPTH_PX,F7)。
右/下各延 depth px:正面暗带+右侧暗带+列缝+岩层横纹+口沿高光+接触 AO+底线+悬浮影。"""
d = int(round(depth if depth is not None else (DEPTH_PX or 8.0)))
w, h = board.size
out = Image.new("RGBA", (w + d, h + d), (0, 0, 0, 255))
out.paste(board, (0, 0))
dr = ImageDraw.Draw(out)
brick = UIKIT["BRICK"]
front = _gd_darkened(brick, 0.55) # 正面悬崖(背光)——board_world.gd:88
right = _gd_darkened(brick, 0.38) # 右侧悬崖(微受光)
dr.rectangle([0, h, w - 1, h + d], fill=front)
dr.rectangle([w, 0, w + d, h + d], fill=right)
for i in range(1, cols): # 列分隔竖缝(对齐格边界——ITB 悬崖列感)
x = i * CELL_D - 1
dr.rectangle([x, h, x + 2, h + d], fill=_gd_darkened(front, 0.25))
dr.rectangle([0, h + d * 0.38, w, h + d * 0.38 + 1.5], fill=_gd_darkened(front, 0.18)) # 岩层横纹
dr.rectangle([0, h + d * 0.72, w, h + d * 0.72 + 1.5], fill=_gd_darkened(front, 0.12))
dr.rectangle([0, h, w, h + 1], fill=_gd_lightened(brick, 0.18)) # 口沿高光(倒角受光)
dr.rectangle([w, 0, w + 1, h], fill=_gd_lightened(brick, 0.12))
ao = Image.new("RGBA", out.size, (0, 0, 0, 0)) # 顶面接触 AO
ImageDraw.Draw(ao).rectangle([0, h - 2, w - 1, h], fill=(0, 0, 0, 46))
ImageDraw.Draw(ao).rectangle([w - 2, 0, w, h], fill=(0, 0, 0, 36))
out.alpha_composite(ao)
dr.rectangle([0, h + d - 2, w + d, h + d], fill=_gd_darkened(front, 0.35)) # 底线收边
if d >= 8: # 悬浮影三层渐隐(中厚档起——board_world.gd:109)
for i, a in enumerate([0.16, 0.10, 0.05]):
sh = 3.0 + i * 3.0
sl = Image.new("RGBA", out.size, (0, 0, 0, 0))
ImageDraw.Draw(sl).rectangle(
[sh, h + d + sh * 0.5, w + d - sh * 1.5, h + d + sh * 0.5 + 2 + i],
fill=(0, 0, 0, int(255 * a)))
out.alpha_composite(sl)
return out
def wcag_lum(rgb):
def lin(c):
@@ -317,13 +409,14 @@ def draw_inlay(img, ox, oy, cell, kind, corner=4, m=None, L=None):
def draw_type_glow(glow_layer, ox, oy, cell, kind):
"""类型常显微光=内缘带状泛光(§4.2 色带;F5b 禁整格染色——中心 50% 区零像素)。"""
"""类型常显微光=内缘带状泛光(§4.2 色带;F5b 禁整格染色——中心区零像素)。
v2:泛光提亮 α170/带宽 6——观感密度(A6)层次承载,亮度不压格底明度档(§2 微光例外)。"""
layer = Image.new("RGBA", glow_layer.size, (0, 0, 0, 0))
d = ImageDraw.Draw(layer)
rgb = GLOW_GROUPS[kind]
band = max(3, cell // 11)
band = max(4, cell // 8)
d.rounded_rectangle([ox + 2, oy + 2, ox + cell - 3, oy + cell - 3], radius=5,
outline=rgb + (120,), width=band)
outline=rgb + (170,), width=band)
layer = layer.filter(ImageFilter.GaussianBlur(1))
glow_layer.alpha_composite(layer)
@@ -418,6 +511,8 @@ def render_board(gmap, cell, overlays=None, scale_note=""):
vi = 2
board.paste(FLOORS[vi].resize((cell, cell), Image.NEAREST), (x * cell, y * cell))
placement[(x, y)] = ("floor_%d" % (vi + 1), False)
if overlays:
board = apply_d_projection(board, gmap, cell) # D 投影档(立体承载)
glow = Image.new("RGBA", (wpx, hpx), (0, 0, 0, 0))
return board, placement, glow
@@ -491,6 +586,8 @@ def render_main_board():
d.line([(i * cell, 0), (i * cell, gmap.h * cell)], fill=(0, 0, 0, 45), width=1)
for i in range(gmap.h + 1):
d.line([(0, i * cell), (gmap.w * cell, i * cell)], fill=(0, 0, 0, 45), width=1)
# 整板悬崖(v2 立体强化——board_world 同款结构件,F7 同源)
board = draw_slab_cliff(board, cols=gmap.w)
return board, placement, records, band, gmap
@@ -645,18 +742,19 @@ def run_checks(board, placement, records, band, gmap, canvas_img=None):
in_cell = bbox[0] >= hx0 - 6 and bbox[1] >= hy0 - 6 and bbox[2] <= hx0 + CELL_D + 6 and bbox[3] <= hy0 + CELL_D + 6
check("F5a", "接触带微光⊆英雄格周界(空间侧,不进墙格)", in_cell,
"微光 bbox=%s 英雄格=%s" % (bbox, (hx0, hy0, hx0 + CELL_D, hy0 + CELL_D)))
# F5b 类型微光禁整格染色:中心 50% 区零像素(参照=该格实贴瓦片——缘件纹理本身异于 center)
# F5b 类型微光禁整格染色:中心 50% 区零像素(参照=该格实贴瓦片——缘件纹理本身异于 center;
# 砖心区下界让位立面带 0.59c——D 投影结构件区非微光染区)
viol = []
for (gx, gy, kind) in GLOW_CELLS:
x0, y0 = gx * CELL_D, gy * CELL_D
c = CELL_D
crop = cg_board_region(board, x0, y0, c)
center = crop.crop((c // 4, c // 4, c * 3 // 4, c * 3 // 4))
center = crop.crop((c // 4, c // 4, c * 3 // 4, int(c * 0.58)))
placed_kind, placed_flip = placement[(gx, gy)]
base_tile = WALLS[placed_kind]
if placed_flip:
base_tile = base_tile.transpose(Image.FLIP_LEFT_RIGHT)
base = base_tile.resize((c, c), Image.NEAREST).crop((c // 4, c // 4, c * 3 // 4, c * 3 // 4))
base = base_tile.resize((c, c), Image.NEAREST).crop((c // 4, c // 4, c * 3 // 4, int(c * 0.58)))
diff = 0
cp, bp = center.load(), base.load()
for yy in range(0, center.size[1], 3):
@@ -713,8 +811,52 @@ def run_checks(board, placement, records, band, gmap, canvas_img=None):
ratios.append((name, round((max(l1, l2) + 0.05) / (min(l1, l2) + 0.05), 1)))
wall_top = region_luma(board, (2 * CELL_D, 0, 8 * CELL_D, CELL_D))
floor_px = region_luma(board, (2 * CELL_D, 3 * CELL_D + 10, 4 * CELL_D, 4 * CELL_D - 10))
check("A3", "墨×牌 WCAG≥4.5:1 + 图底分离", all(r[1] >= 4.5 for r in ratios) and (wall_top - floor_px) >= 40,
check("A3", "墨×牌 WCAG≥4.5:1 + 图底分离 Δ≥55(立体强化上调——否决③,v1 实测 61.9)",
all(r[1] >= 4.5 for r in ratios) and (wall_top - floor_px) >= WALL_FLOOR_MIN,
"%s;墙顶 %.0f vs 地面 %.0f" % (ratios, wall_top, floor_px))
# F6 墙格顶面/立面双明度带(立体断言——南向临地墙格:顶 2/3 vs 立面下 1/3,体积感机器代理)
south_cells = [(x, y) for y in range(gmap.h) for x in range(gmap.w)
if is_wall(gmap, x, y) and not is_wall(gmap, x, y + 1)]
rgbp = board.convert("RGB").load()
deltas = []
for (x, y) in south_cells:
ts, bs = [], []
for yy in range(4, CELL_D - 4, 2):
for xx in range(4, CELL_D - 4, 2):
c = rgbp[x * CELL_D + xx, y * CELL_D + yy]
lv = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]
(ts if yy < CELL_D * 2.0 / 3.0 else bs).append(lv)
if ts and bs:
deltas.append(sum(ts) / len(ts) - sum(bs) / len(bs))
dmin = min(deltas) if deltas else 0.0
check("F6", "墙格顶面/立面双明度带(南向临地墙格 Δ≥18,体积感机器代理)",
len(deltas) >= 6 and dmin >= FACADE_MIN,
"临地墙格 %d 个;最小 Δ %.1f;均 Δ %.1f(v1 实测均 71.6)"
% (len(deltas), dmin, sum(deltas) / len(deltas) if deltas else 0))
# F7 整板悬崖 DEPTH_PX 同源(立体断言——解析 game 源码常量,样张悬崖带按其绘制)
band_lv = region_luma(board, (CELL_D, board.size[1] - 3, board.size[0] - CELL_D, board.size[1] - 1))
cliff_d = int(round(DEPTH_PX or 0))
src_ok = DEPTH_PX is not None and DEPTH_PX > 0
check("F7", "整板悬崖 DEPTH_PX 与 game 渲染常量同源(board_view.gd 解析)",
src_ok and cliff_d == 8 and band_lv < 100,
"DEPTH_PX=%s(%s);悬崖带均亮 %.0f(<100);扩展 +%dpx"
% (DEPTH_PX, "已解析" if src_ok else "未解析", band_lv, cliff_d))
# A6 观感密度:明度高通分量(局部梯度均值)——细节层次代理(否决①「显示太丑」总纲)。
# 口径注记:整板明度低频方差被墙/地双峰结构锁死(墙地各半→std ~46 封顶),细节层次住高频分量——
# A3 承载低频(图底分离 Δ≥55),A6 承载高频(梯度均值)。v1 同口径实测 4.09,上调 15% = 4.70。
grad = []
for y in range(gmap.h):
for x in range(gmap.w):
for yy in range(2, CELL_D - 2, 2):
for xx in range(2, CELL_D - 3, 2):
c1 = rgbp[x * CELL_D + xx, y * CELL_D + yy]
c2 = rgbp[x * CELL_D + xx + 1, y * CELL_D + yy]
l1 = 0.2126 * c1[0] + 0.7152 * c1[1] + 0.0722 * c1[2]
l2 = 0.2126 * c2[0] + 0.7152 * c2[1] + 0.0722 * c2[2]
grad.append(abs(l1 - l2))
gmean = sum(grad) / len(grad)
check("A6", "观感密度:明度梯度均值 ≥%.2f(v1 实测 4.09 上调 15%%——高频细节能量)" % DENSITY_MIN,
gmean >= DENSITY_MIN, "梯度均值 %.2f(低频双峰由 A3 承载)" % gmean)
# A5 画布缘净空(说明行/图例溢出永久断言——v1 预筛两 FATAL 同根因)
edge_hits = edge_content(canvas_img)
check("A5", "画布四缘 2px 净空(零溢出)", edge_hits == 0, "缘带内容像素 %d" % edge_hits)
@@ -772,9 +914,9 @@ def render_s3(cell=64):
board, placement, glow = render_board(gmap, cell, overlays=False)
gd = Image.new("RGBA", board.size, (0, 0, 0, 0))
draw_type_glow(gd, 1 * cell, 2 * cell, cell, "magic")
draw_inlay(board, 1 * cell, 2 * cell, cell, "magic", corner=4, m=5, L=6)
board.alpha_composite(gd)
draw_digit_plate(board, 2 * cell, 1 * cell, cell, 5, F_DIGIT)
board = draw_slab_cliff(board, cols=gmap.w) # 整板悬崖(v2 同源结构件)
# underdark 冷调(§4.3 四槽示意——HSV 脚本近似,信息层恒定)
h, s, v = board.convert("HSV").split()
h = h.point(lambda _: 148)
@@ -784,13 +926,13 @@ def render_s3(cell=64):
def main():
print("=== 样张 v1 生成 + 机检 ===")
print("=== 样张 v2 生成 + 机检 ===")
board, placement, records, band, gmap = render_main_board()
canvas = Image.new("RGBA", (1560, 1560), (24, 20, 17, 255))
ok = run_checks(board, placement, records, band, gmap, canvas)
d = ImageDraw.Draw(canvas)
d.text((20, 14), "战斗一屏样张验收图 v1(2026-09-26)——B/C/D 三区全内容+art-bible §1.4 内容清单;机检 %s;巢穴纹/封印印记/角嵌纹样=程序占位" %
d.text((20, 14), "战斗一屏样张验收图 v2(2026-09-28)——B/C/D 三区全内容+art-bible §1.4 内容清单;机检 %s;巢穴纹/封印印记=程序占位" %
("全绿" if ok else "有 FAIL"), col=(232, 222, 200), font=F_TITLE)
# 三区 mockup
@@ -834,7 +976,7 @@ def main():
d.rectangle([x, oy4, x + 34, oy4 + 34], fill=rgb, outline=(90, 80, 66))
d.text((x - 4, oy4 + 38), GLOW_FAMILY[key] + "微光", font=F_LBL2, fill=(225, 215, 195))
x += 150
d.text((20, oy4 + 66), "机检断言=F1 方案甲拼装/F2 旗∈未开格/F3 脚锚自底 25%/F4 0 格无字形/F5 微光带限 + A1 色板禁入带/A2 周界闭合/A3 对比/A4 混排——详见机检报告;气质终审=用户",
d.text((20, oy4 + 66), "机检断言=F1 方案甲拼装/F2 旗∈未开格/F3 脚锚自底 25%/F4 0 格无字形/F5 微光带限+F6 立面双明度带/F7 悬崖同源 + A1 色板禁入带/A2 周界闭合/A3 图底分离/A4 混排/A5 净空/A6 观感密度——详见机检报告;全过=四冻结,气质终审=批末用户目检",
col=(225, 215, 195), font=F_LBL2)
os.makedirs(os.path.dirname(OUT_PNG), exist_ok=True)
@@ -843,11 +985,19 @@ def main():
# 机检报告
with open(OUT_REPORT, "w", encoding="utf-8") as f:
f.write("# 样张 v1 机检报告(2026-09-26)\n\n生成:`python tools/render_sample_sheet.py`;断言事实源 = 画法参数四源对照表-2026-09-26.md §6。\n\n")
f.write("# 样张 v2 机检报告(2026-09-28,M-1 迭代 2 T1)\n\n")
f.write("生成:`python tools/render_sample_sheet.py`;断言事实源 = 画法参数四源对照表-2026-09-26.md §6 + 迭代 2 立体/密度扩展。\n\n")
f.write("## v1 否决原因 → 断言映射\n\n")
f.write("| 否决原因(2026-09-28 用户) | 断言承载 |\n|---|---|\n")
f.write("| ①显示太丑(总纲) | A6 观感密度(整板明度 std ≥50.9=v1 实测 44.31×1.15)+既有装饰变体 ≥2 种 |\n")
f.write("| ②封印色冲突 | 封印黑 #000000(9b6fcf6 已落,A1a 对表自动覆盖) |\n")
f.write("| ③立体感不够 | A3 阈值 40→55 + F6 顶面/立面双明度带 Δ≥18 + F7 整板悬崖 DEPTH_PX 同源 |\n")
f.write("| ④微光格只留微光 | F5c 微光段零 draw_inlay(d1dea82 已落) |\n\n")
f.write("## 断言明细\n\n")
f.write("| 断言 | 判据 | 结果 | 明细 |\n|---|---|---|---|\n")
for cid, name, okk, detail in CHECKS:
f.write("| %s | %s | %s | %s |\n" % (cid, name, "PASS" if okk else "**FAIL**", detail.replace("|", "/")))
f.write("\n结论:**%s**(%d/%d PASS)。气质终审 = 用户(异步,不阻塞 T2-T7)。\n" %
f.write("\n结论:**%s**(%d/%d PASS)。机检全过 = 四冻结(砖面形态/色板/动画方案/数字形制)生效落码;气质终审 = 批末用户目检(闸形 A,2026-09-27 拍板)。\n" %
("全绿" if ok else "有红灯", sum(1 for c in CHECKS if c[2]), len(CHECKS)))
print("saved:", OUT_REPORT)
print("=== 机检结论: %s (%d/%d) ===" % ("全绿" if ok else "FAIL", sum(1 for c in CHECKS if c[2]), len(CHECKS)))