From 4f6ac1753182e0536746032a97fc0231cdf9982e Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 29 Sep 2026 22:30:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(sample-v35-new):=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=B8=89=E6=9D=A1=E6=8C=87=E4=BB=A4=E9=80=90=E6=9D=A1=E8=90=BD?= =?UTF-8?q?=E5=9C=B0(=E5=9F=BA=E7=BA=BF=3Dv3.4=20=E6=96=87=E4=BB=B6,?= =?UTF-8?q?=E6=97=A7v3.5/v3.6=E8=A7=86=E5=90=8C=E4=B8=8D=E5=AD=98=E5=9C=A8?= =?UTF-8?q?)=E2=80=94=E2=80=94=E2=91=A0(b)(c)=E5=A2=99=E9=A1=B6=E5=90=8C?= =?UTF-8?q?=E8=89=B2:E=E5=A2=99=E9=9D=A2=E9=A1=B6=E9=9D=A2=E6=9D=90?= =?UTF-8?q?=E8=B4=A8=E5=8E=9F=E4=BA=AE=E5=BA=A6=E7=9B=B4=E8=B4=B4=20?= =?UTF-8?q?=E2=91=A1(b)-(c)=E8=BF=9E=E6=8E=A5=E5=A4=84=E6=97=A0=E8=BE=B9?= =?UTF-8?q?=E6=A1=86:=E6=A0=BC=E7=BA=BF=E8=B7=B3=E8=BF=87E/=E5=A2=99?= =?UTF-8?q?=E4=BA=A4=E7=95=8C=E6=AE=B5=20=E2=91=A2E=E5=A2=99=E9=9D=A2?= =?UTF-8?q?=E9=AB=98=E5=BA=A630%;=E6=9C=BA=E6=A3=8017/17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/render_sample_sheet_v3.py | 75 ++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/tools/render_sample_sheet_v3.py b/tools/render_sample_sheet_v3.py index fb8a44c5..78b79f8d 100644 --- a/tools/render_sample_sheet_v3.py +++ b/tools/render_sample_sheet_v3.py @@ -271,10 +271,16 @@ def apply_d_projection(board, gmap, cell): 北邻墙地面格 = 三段渐隐投影(顶带 0.22 格边,α0.28 起)。立体断言 F6/A6 的渲染承载。""" overlay = Image.new("RGBA", board.size, (0, 0, 0, 0)) d = ImageDraw.Draw(overlay) - # v3.5:南临墙格的立面暗带+口沿高光已废止(用户终裁:墙顶零阴影全板同色同素材) + 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]): @@ -554,7 +560,7 @@ def draw_hero_on_board(board, ox, oy, cell, hx, hy, records, digit=None): records.append(("hero", hx, hy, fx, fy, digit)) -FACADE_FRAC = 0.55 # E 格立面占比(v3.2 档位候选:0.55/0.80/1.00 三档对比,用户挑档) +FACADE_FRAC = 0.30 # E 格墙面高度(新 v3.5:用户指令 30%) def draw_facade(board, x0, y0, cell): """v3.3 E 格墙面(用户方案:地面格南邻墙 → 南部承接墙面展示)。 @@ -564,7 +570,7 @@ def draw_facade(board, x0, y0, cell): fy0 = y0 + int(cell * (1.0 - FACADE_FRAC)) wall_top = WALLS["center"].resize((cell, cell), Image.NEAREST) face = wall_top.crop((0, 0, cell, cell - fy0 + y0)) - face = face.point([min(255, int(i * 0.85)) for i in range(256)] * 3) + # 新 v3.5 ①:(b) 与 (c) 墙顶同色——顶面材质原亮度直贴,零暗档 board.paste(face, (x0, fy0)) d.rectangle([x0, fy0, x0 + cell, fy0 + 1], fill=(52, 42, 32)) # 墙脚阴线(地面/墙面交界) # v3.4:墙面底缘不画任何线——墙面直接接到南侧墙顶(用户裁:白边导致两截) @@ -576,14 +582,15 @@ def is_facade_cell(gmap, x, y): def lift_south_lip(tile): - """v3.3:南向墙格(南邻地)底部暗条以顶面材质**原亮度**直填—— - 全板墙顶同色同素材,零阴影零暗档(用户终裁:「这里没有什么阴影影响,它们是同样颜色的」)。终稿归瓦片重产(§8.5)。""" + """v3.3:南向墙格(南邻地)底部暗条改为顶面同款材质轻微暗档(×0.80)—— + 同一堵墙的顶面材质全板一致,南向厚度面只差明度,不再两截皮。终稿归瓦片重产(§8.5)。""" im = tile.convert("RGB") w, h = im.size y0 = int(h * 0.60) top_ref = im.crop((0, 0, w, y0)) # 顶面区材质 band_h = h - y0 - ref = top_ref.resize((w, band_h)) # v3.5:顶面纹理原亮度直填(无暗档无阴影——全板墙顶同色同素材) + ref = top_ref.resize((w, band_h)) # 顶面纹理拉伸到暗条区(同材质) + ref = ref.point([min(255, int(i * 0.80)) for i in range(256)] * 3) out = im.copy() out.paste(ref, (0, y0)) if tile.mode == "RGBA": @@ -702,12 +709,21 @@ def render_main_board(): band = draw_contact_glow(cg, 0, 0, cell, HERO_AT[0], HERO_AT[1], gmap) board.alpha_composite(cg) - # 网格线(屏轴对齐,低对比) + # 网格线(屏轴对齐,低对比);新 v3.5 ③:(b)-(c) 连接处(上格=地面且南邻墙/下格=墙)无边框 d = ImageDraw.Draw(board) for i in range(gmap.w + 1): 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) + for i in range(1, gmap.h + 1): + x = 0 + bottom_edge = (i == gmap.h) + while x < gmap.w: + skip = (not bottom_edge) and (gmap.grid[i][x] == "W" and gmap.grid[i - 1][x] != "W") + x2 = x + while x2 < gmap.w and ((not bottom_edge) and (gmap.grid[i][x2] == "W" and gmap.grid[i - 1][x2] != "W")) == skip: + x2 += 1 + if not skip: + d.line([(x * cell, i * cell), (x2 * cell, i * cell)], fill=(0, 0, 0, 45), width=1) + x = x2 # 整板悬崖(v2 立体强化——board_world 同款结构件,F7 同源) board = draw_slab_cliff(board, cols=gmap.w) return board, placement, records, band, gmap @@ -960,36 +976,25 @@ def run_checks(board, placement, records, band, gmap, canvas_img=None): check("A3b", "图底分离读数(候选 Δ≥30——v2 阈值 55 与格底分档带数学冲突,校准归冻结批)", (wall_top - floor_px) >= 30, "墙顶 %.0f vs 地面 %.0f,Δ=%.0f(v2 阈值 55 系地板 L0.036 时代校定)" % (wall_top, floor_px, wall_top - floor_px)) - # F6 v3.5 改口径:墙顶全板同色(南向临地墙格顶面 vs 全板墙顶均值,逐通道差 ≤6—— - # 原"顶面/立面双明度带 Δ≥18"随南临暗带废止;立体感由 E 格墙面承载) + # 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() - def _cell_top_mean(x, y): - vals = [] - for yy in range(4, int(CELL_D * 0.4), 2): - for xx in range(4, CELL_D - 4, 2): - vals.append(rgbp[x * CELL_D + xx, y * CELL_D + yy]) - n = len(vals) - return (sum(v[0] for v in vals) / n, sum(v[1] for v in vals) / n, sum(v[2] for v in vals) / n) - _excl_all = {FLAG_AT, HOVER_AT} | {(gx, gy) for (gx, gy, _k) in GLOW_CELLS} - all_tops = [_cell_top_mean(x, y) for y in range(gmap.h) for x in range(gmap.w) - if is_wall(gmap, x, y) and (y == 0 or gmap.grid[y-1][x] == "W") and (x, y) not in _excl_all] - ref = tuple(sum(v[i] for v in all_tops) / len(all_tops) for i in range(3)) - # 排除带附加层的格(旗/悬停/微光——信息层合法染色,不属墙顶色差) - _excl = {FLAG_AT, HOVER_AT} | {(gx, gy) for (gx, gy, _k) in GLOW_CELLS} - devs = [] + deltas = [] for (x, y) in south_cells: - if (x, y) in _excl: - continue - m = _cell_top_mean(x, y) - dev = max(abs(m[i] - ref[i]) for i in range(3)) - devs.append(dev) - dmax = max(devs) if devs else 0.0 - check("F6", "墙顶全板同色(南向墙格顶面 vs 全板均值逐通道差 ≤6;旗格排除)", - dmax <= 6.0, - "南向墙格 %d 个(排除 %d 个附加层格);最大色差 %.1f(参考均值 %s)" - % (len(devs), len(_excl & set(south_cells)), dmax, tuple(round(v) for v in ref))) + 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))