补提交(布局几何单点化批·代码面+工具面+architecture行·跨会话遗留): battle_layout.tres 新表单行五字段(stage_h/info_panel_w/ap_bar_h/log_band_h_dig/log_band_h_settle)经 schema battle_layout_table.gd+域容器 config_domain_presentation.gd 收进 ConfigDb.presentation(ConfigDB 三容器→四容器,manifest 增 battle_layout 键,B区高度裁决 2026-10-30 用户裁=取代码标准 stage_h);views 五件构造签名增 layout 参(BattleStageView/HeroInfoPanelView/BoardZoneView/ApBarView/BattleLogView 常量高度改表值驱动)+ui_assembler 装配传 layout+probes 两件改址+main.gd 结算带注释去数值;tools/layout_config.py 新件+render_sample_sheet 两版读布局表现算(样张工具面);文档面: architecture.md ConfigDB 行换代(四容器成员 7/7/5/1、类变量 10)+HUD框架.md 三区表/装板不等式/调参表去数值化改指布局表+数据配置.md+interaction-patterns.md 明细带句去数值(battle.md 区表与待办清单登记面已随 1cdef6ba 在库);消费漏网 L1 就地补改九处(构造签名换型与 iter45 断点件收编的测试改址漏网,判据零变化): theme_projection_test:386/player_copy_sweep_test:44,98/adventure_feats_test:772/standee_fx_sweep_test:75/feat_vouchers_test:292 六处补 layout 实参,adventure_feats_test:791/level_shop_economy_test:1480/feat_vouchers_test:81 三处断点成员直读改经 a._bp_store(iter45卡②六成员搬移漏网,02 闸合回后首全量暴露);load_tables 超函数长键清偿(容器装配块抽 _assign_loaded 私有协函数——表行按域收进四容器+resolver 注入单一职责,与 _cross_validate 委托先例同型,S13 新增红修至基线口径内);窄验: 四件修复套件单跑全绿+gdstyle 基线外新违规 0

This commit is contained in:
DKChan committed 2026-10-31 05:05:08 +08:00
1 parent 39907d82f6
commit 4b174877be
29 files changed
+231 -118

No files matched your search

+46 -34
View File
@@ -40,7 +40,7 @@ v3.0 口径(方向稿=目检先行闸,冻结归机检):
迭代 43 扩展(2026-10-29 战斗一屏样张批):整屏样张两版出口(1280×800 基座 + 1920×1080 全局等比
1.35×+左右黑边,§8.2 1920 档策略)+ art-bible §1.4 整屏四项断言(S1–S4)+ 战斗表现五项断言(P1–P5)
+ S3b 图类型色板变体第二套 + S5 三组关键帧条 + S6 描边同屏对照与遮挡对照组 + V1 两版尺寸断言
+ V10 改前/改后基线并排对拍;B 区高按代码现状 252 出样(art-bible §8.2 文 270 差异只登记不修)。
+ V10 改前/改后基线并排对拍;分区几何读 game/data/tables/battle_layout.tres(与游戏侧同源)。
"""
from PIL import Image, ImageDraw, ImageFilter, ImageChops, ImageFont
import os
@@ -50,6 +50,8 @@ import re
import hashlib
from collections import deque
from layout_config import load as load_layout
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MAIN_ROOT = "D:/code/g-plan2"
@@ -845,14 +847,22 @@ def draw_standee(canvas, ox, oy, kind, name, enemy_id, order=1, armor="light",
canvas.alpha_composite(gray, (ox, oy))
B_H = 252 # B 区高=代码现状(battle_stage_view custom_minimum_size 252;§8.2 文 270 差异只登记不修)
CANVAS_W = 1280 # 基座档(art-bible §8.1)
CANVAS_H = 800
_LAYOUT = load_layout()
B_H = _LAYOUT["stage_h"] # B 区高(布局表单点——与游戏侧同源)
C_W = _LAYOUT["info_panel_w"] # C 区宽
D_X = C_W + 4 # D 区左边 = C 区宽 + 列间距
D_W = CANVAS_W - D_X # D 区宽
BAND_DIG = _LAYOUT["log_band_h_dig"] # 明细带收起高
BAND_SETTLE = _LAYOUT["log_band_h_settle"]
AP_H = _LAYOUT["ap_bar_h"] # D 区 AP 条高
def draw_base(canvas_w=CANVAS_W, canvas_h=800, b_h=B_H):
"""样张底板(T1):B/C/D 三区骨架——分区数值按 battle.md 指路、B 区按代码 252;格边长=CELL_D 45
def draw_base(canvas_w=CANVAS_W, canvas_h=CANVAS_H, b_h=B_H):
"""样张底板(T1):B/C/D 三区骨架——分区几何全部读布局表 battle_layout.tres;格边长=CELL_D 45
(D 区 10×10 板实比,§8.1)。返回 (img, zones)——zones 供 S/P 断言取样:
b=(0,0,w,b_h) 含明细带;band=明细带 24px;c=(0,b_h+4,240,h);d=(244,b_h+4,w,h)。"""
b=(0,0,w,b_h) 含明细带;band=明细带收起高;c=(0,b_h+4,C_W,h);d=(D_X,b_h+4,w,h)。"""
img = Image.new("RGBA", (canvas_w, canvas_h), (24, 20, 17, 255))
d = ImageDraw.Draw(img)
c_y = b_h + 4
@@ -865,25 +875,26 @@ def draw_base(canvas_w=CANVAS_W, canvas_h=800, b_h=B_H):
a = int(26 * (1 - i / 60.0))
db.rectangle([bx0 - 46 + i // 3, 0, bx0 + 46 - i // 3, 40 + i * 3], fill=(255, 236, 200, a))
img.alpha_composite(beam, (0, 0))
# 明细带(挖掘期收起 24px)
d.rectangle([0, b_h - 24, canvas_w, b_h], fill=(46, 39, 32))
# 明细带(挖掘期收起——高读布局表)
d.rectangle([0, b_h - BAND_DIG, canvas_w, b_h], fill=(46, 39, 32))
# C 区
d.rectangle([0, c_y, 240, canvas_h], fill=UIKIT["PANEL_HERO"], outline=UIKIT["PANEL_BORDER"])
d.rectangle([0, c_y, C_W, canvas_h], fill=UIKIT["PANEL_HERO"], outline=UIKIT["PANEL_BORDER"])
# D 区
d.rectangle([244, c_y, canvas_w, canvas_h], fill=(34, 29, 24), outline=UIKIT["PANEL_BORDER"])
# D 区顶行工具件(停手/图例/刷新+AP 点阵+RAP)
d.rectangle([252, c_y + 6, 304, c_y + 28], fill=(90, 80, 66), outline=(120, 106, 88))
d.text((278, c_y + 17), "停手", font=F_LBL2, fill=(232, 222, 200), anchor="mm")
d.rectangle([310, c_y + 6, 354, c_y + 28], fill=(90, 80, 66), outline=(120, 106, 88))
d.text((332, c_y + 17), "?图例", font=F_LBL2, fill=(232, 222, 200), anchor="mm")
d.rectangle([360, c_y + 6, 428, c_y + 28], fill=(90, 80, 66), outline=(120, 106, 88))
d.text((394, c_y + 17), "刷新 8|剩2", font=F_LBL2, fill=(232, 222, 200), anchor="mm")
d.rectangle([D_X, c_y, canvas_w, canvas_h], fill=(34, 29, 24), outline=UIKIT["PANEL_BORDER"])
# D 区顶行工具件(停手/图例/刷新+AP 点阵+RAP——坐标随 C 区宽平移)
dx = D_X + 8
d.rectangle([dx, c_y + 6, dx + 52, c_y + 28], fill=(90, 80, 66), outline=(120, 106, 88))
d.text((dx + 26, c_y + 17), "停手", font=F_LBL2, fill=(232, 222, 200), anchor="mm")
d.rectangle([dx + 58, c_y + 6, dx + 102, c_y + 28], fill=(90, 80, 66), outline=(120, 106, 88))
d.text((dx + 80, c_y + 17), "?图例", font=F_LBL2, fill=(232, 222, 200), anchor="mm")
d.rectangle([dx + 108, c_y + 6, dx + 176, c_y + 28], fill=(90, 80, 66), outline=(120, 106, 88))
d.text((dx + 142, c_y + 17), "刷新 8|剩2", font=F_LBL2, fill=(232, 222, 200), anchor="mm")
for i in range(6):
col = (232, 200, 120) if i < 4 else (120, 106, 88)
d.ellipse([440 + i * 18, c_y + 10, 452 + i * 18, c_y + 22], fill=col)
d.text((552, c_y + 17), "RAP 6/6", font=F_LBL2, fill=(200, 180, 140), anchor="lm")
zones = {"b": (0, 0, canvas_w, b_h), "band": (0, b_h - 24, canvas_w, b_h),
"c": (0, c_y, 240, canvas_h), "d": (244, c_y, canvas_w, canvas_h)}
d.ellipse([dx + 188 + i * 18, c_y + 10, dx + 200 + i * 18, c_y + 22], fill=col)
d.text((dx + 300, c_y + 17), "RAP 6/6", font=F_LBL2, fill=(200, 180, 140), anchor="lm")
zones = {"b": (0, 0, canvas_w, b_h), "band": (0, b_h - BAND_DIG, canvas_w, b_h),
"c": (0, c_y, C_W, canvas_h), "d": (D_X, c_y, canvas_w, canvas_h)}
return img, zones
@@ -901,24 +912,25 @@ def render_battle_screen(board_img=None):
statuses=("alert",))
draw_standee(scr, 1128, 34, "enemy", "食人魔酋长", "ogre_chief", order=3, armor="light", hp=1.0, intent="buff")
# 明细带摘要行 + 结算语境 hero 剪影 mini(P2 三语境之一;右端贴装不越缘)
d.text((10, 240), "── 第 3 轮 ── 地精 受到 4 点伤害(增伤 ×1)· 熊地精 蓄力(重击预告)…", font=F_LBL2,
d.text((10, b_h - BAND_DIG // 2), "── 第 3 轮 ── 地精 受到 4 点伤害(增伤 ×1)· 熊地精 蓄力(重击预告)…", font=F_LBL2,
fill=(240, 226, 200), anchor="lm")
mini = HERO.resize((24, int(24 * HERO.size[1] / HERO.size[0])), Image.NEAREST)
scr.alpha_composite(mini, (1236, b_h - 24))
# ── C 区内容(次级文对齐 §7.2 ≥4.5:1——STONE_DEEP/GOLD_INK 在册墨) ──
d.rectangle([8, 264, 232, 340], outline=(120, 106, 88), width=1) # 攻击数据框(直角细线)
d.text((16, 276), "攻击 6", font=ImageFont.truetype(ZH_FONT, 15), fill=(30, 26, 22))
d.text((16, 298), "(+50% 增伤 ×1)", font=F_LBL2, fill=(116, 80, 11))
d.text((16, 318), "护甲 AC 12", font=ImageFont.truetype(ZH_FONT, 15), fill=(30, 26, 22))
d.text((8, 352), "魔法道具槽(预留)", font=F_LBL2, fill=(85, 77, 65))
scr.alpha_composite(mini, (CANVAS_W - 44, b_h - BAND_DIG))
# ── C 区内容(次级文对齐 §7.2 ≥4.5:1——STONE_DEEP/GOLD_INK 在册墨;y 随 B 区高平移) ──
cy = b_h + 4
d.rectangle([8, cy + 8, C_W - 8, cy + 84], outline=(120, 106, 88), width=1) # 攻击数据框(直角细线)
d.text((16, cy + 20), "攻击 6", font=ImageFont.truetype(ZH_FONT, 15), fill=(30, 26, 22))
d.text((16, cy + 42), "(+50% 增伤 ×1)", font=F_LBL2, fill=(116, 80, 11))
d.text((16, cy + 62), "护甲 AC 12", font=ImageFont.truetype(ZH_FONT, 15), fill=(30, 26, 22))
d.text((8, cy + 96), "魔法道具槽(预留)", font=F_LBL2, fill=(85, 77, 65))
for i in range(4):
d.rectangle([8 + i * 40, 368, 8 + i * 40 + 34, 402], outline=(120, 106, 88), width=1)
d.text((8, 416), "本关强化列表(预留)", font=F_LBL2, fill=(85, 77, 65))
d.rectangle([8 + i * 40, cy + 112, 8 + i * 40 + 34, cy + 146], outline=(120, 106, 88), width=1)
d.text((8, cy + 160), "本关强化列表(预留)", font=F_LBL2, fill=(85, 77, 65))
# ── D 区主样张板(10×10@45px=450×450+悬崖 8)嵌进工具行之下居中 ──
board_origin = None
if board_img is not None:
bx = 244 + (1036 - board_img.size[0]) // 2
by = b_h + 4 + 34 + (800 - b_h - 4 - 34 - board_img.size[1]) // 2
bx = D_X + (D_W - board_img.size[0]) // 2
by = cy + AP_H + (CANVAS_H - cy - AP_H - board_img.size[1]) // 2
scr.paste(board_img.convert("RGB"), (bx, by), board_img)
board_origin = (bx, by)
return scr, zones, board_origin
@@ -1644,7 +1656,7 @@ def main():
d.text((20, 14), "战斗一屏样张方向稿 v3-draft(2026-09-29,art-bible v3.0;迭代 43 扩展:整屏两版+S1–S4/P1–P5 断言)——机检 %s(方向稿参考,冻结归目检后机检批)" %
("全绿" if ok else "有 FAIL"), col=(232, 222, 200), font=F_TITLE)
canvas.paste(scr, (20, 52))
d.text((20, 866), "三区 mockup(1280×800 实比,B 区按代码 252):B 区站桩(主角立绘 96 朝右/敌字形占位/顺位 FS_HINT/意图素牌/血条=危险红/名行=素底牌+护甲 PNG)",
d.text((20, 866), "三区 mockup(1280×800 实比,分区几何读布局表):B 区站桩(主角立绘 96 朝右/敌字形占位/顺位 FS_HINT/意图素牌/血条=危险红/名行=素底牌+护甲 PNG)",
col=(225, 215, 195), font=F_LBL)
d.text((20, 886), "C 区攻击数据框+预留槽 · D 区主样张板(方案甲拼装/接触带微光/悬停金框/封印印记/危险格巢穴占位)",
col=(225, 215, 195), font=F_LBL)
@@ -1732,7 +1744,7 @@ def main():
with open(OUT_REPORT, "w", encoding="utf-8") as f:
f.write("# 样张 v3 机检报告(2026-09-30 批 A 断言定值 + 迭代 43 整屏扩展 S1–S4/P1–P5/V1/V10/A7/A5b)\n\n")
f.write("生成:`python tools/render_sample_sheet_v3.py`;v3.5 冻结口径:格底分档/亮墨直画三档/色牌后备/物件级装饰/B 区舞台;A3b 图底分离 Δ≥30;A4 尺寸基线(立绘 46×48/小人源 32×32 硬等)。"
"迭代 43 扩展:B 区按代码 252 出样;整屏四项与战斗表现五项断言落 CHECKS;两版样张出口与基线并排对拍。方向稿目检先行,机检冻结归目检通过后。\n\n")
"迭代 43 扩展:B 区高读布局表出样;整屏四项与战斗表现五项断言落 CHECKS;两版样张出口与基线并排对拍。方向稿目检先行,机检冻结归目检通过后。\n\n")
f.write("## 断言明细\n\n")
f.write("| 断言 | 判据 | 结果 | 明细 |\n|---|---|---|---|\n")
for cid, name, okk, detail in CHECKS: