#!/usr/bin/env python3 # -*- coding: utf-8 -*- """站桩槽位素材机检(M-3 迭代 6 T1——48px 档契约断言;重闸素材面闸)。 四断言(契约=计划书 C4/圣经 §8.2): 尺寸 高恒 48(槽位源档 ×2 整数放大=盒高 96);宽 1..75(盒宽 150 半值)。 锚点 底行有不透明像素(底中锚——纵向比例自底边口径,脚贴画布底缘)。 色数 ≤32(fixer 批 32 色冻结;NEAREST 采样不产生新色)。 无插值 alpha 二值(仅 0/255——双线性/混合会在边缘产生中间 α)。 用法: python tools/standee_asset_check.py [角色素材目录] 默认 game/assets/art/character/;必需集=八敌+主角 portrait/attack/hit。 """ import os import sys from collections import Counter from PIL import Image REQUIRED = ["character_enemy_%s.png" % k for k in ("bugbear", "drider", "duergar", "duergar_king", "giant_spider", "goblin", "hook_horror", "ogre_chief")] + \ ["character_hero_portrait.png", "character_hero_attack.png", "character_hero_hit.png"] SLOT_H = 48 W_MAX = 75 COLOR_MAX = 32 def check(path): problems = [] im = Image.open(path).convert("RGBA") w, h = im.size if h != SLOT_H: problems.append("高应 48,实得 %d" % h) if not (1 <= w <= W_MAX): problems.append("宽应 1..%d,实得 %d" % (W_MAX, w)) px = im.load() colors = set() alphas = set() bottom_opaque = 0 for y in range(h): for x in range(w): c = px[x, y] alphas.add(c[3]) if c[3] > 0: colors.add(c[:3]) if y == h - 1: bottom_opaque += 1 if bottom_opaque < 1: problems.append("底行无不透明像素(底中锚失守——脚未贴画布底缘)") if len(colors) > COLOR_MAX: problems.append("色数 %d > %d" % (len(colors), COLOR_MAX)) if not alphas <= {0, 255}: problems.append("alpha 非二值(插值痕迹:%s)" % sorted(alphas - {0, 255})[:5]) return problems, (w, h, len(colors)) def main(): root = sys.argv[1] if len(sys.argv) > 1 else os.path.join("game", "assets", "art", "character") missing = [f for f in REQUIRED if not os.path.isfile(os.path.join(root, f))] n_fail = 0 for f in REQUIRED: p = os.path.join(root, f) if not os.path.isfile(p): print("MISS %-36s 缺位" % f) n_fail += 1 continue problems, info = check(p) if problems: n_fail += 1 for pr in problems: print("FAIL %-36s %s" % (f, pr)) else: print("PASS %-36s %dx%d 色数%d" % (f, info[0], info[1], info[2])) print("机检完成:%d 件必需,%d 件未过" % (len(REQUIRED), n_fail)) sys.exit(1 if n_fail else 0) if __name__ == "__main__": main()