"""build_preview.py —— 用已生成素材打一个单文件 HTML 可玩预览。 把 out// 里的角色 + UI 美术按比例内嵌成 base64,生成一个 index.html:手机竖屏布局、霓虹框包住果冻网格、可点 SPIN 跑"同款聚 5 只就消除→连锁倍数"的玩法。纯前端、双击即玩,无需任何后端。 用法: python build_preview.py [game] [输出html路径] """ import base64 import io import json import os import sys from PIL import Image HERE = os.path.dirname(os.path.abspath(__file__)) GAME = sys.argv[1] if len(sys.argv) > 1 else "jelly-candy-slot" OUT = sys.argv[2] if len(sys.argv) > 2 else os.path.join(HERE, "out", GAME, f"JellyPop预览.html") BASE = os.path.join(HERE, "out", GAME) def b64(img, maxside, fmt="PNG"): im = img.convert("RGBA") w, h = im.size s = min(1.0, maxside / max(w, h)) if s < 1.0: im = im.resize((max(1, int(w * s)), max(1, int(h * s))), Image.LANCZOS) buf = io.BytesIO() im.save(buf, fmt) return "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode() def load(p): return Image.open(p).convert("RGBA") lib = json.load(open(os.path.join(BASE, "library.json"), encoding="utf-8")) char_ids = [c["id"] for c in lib.get("characters", [])] # 内嵌资源(按用途控制尺寸,平衡清晰度与体积) A = {} for cid in char_ids: A[cid] = b64(load(os.path.join(BASE, "characters", f"{cid}.png")), 190) ui = os.path.join(BASE, "ui_art") A["bg"] = b64(load(os.path.join(ui, "bg_main.png")), 820) A["logo"] = b64(load(os.path.join(ui, "logo.png")), 560) A["frame"] = b64(load(os.path.join(ui, "reel_frame.png")), 620) A["spin"] = b64(load(os.path.join(ui, "btn_spin.png")), 220) A["round"] = b64(load(os.path.join(ui, "btn_round.png")), 150) SYMS = json.dumps(char_ids, ensure_ascii=False) ASSETS = json.dumps(A, ensure_ascii=False) HTML = r""" Jelly Pop · 果冻消消乐
余额
5000
下注
50
本局赢
0
TURBO
BET
BET
AUTO
点 ⟳ 旋转 · 同款果冻聚成一片就连锁消除,连锁越多倍数越高
""" html = HTML.replace("__ASSETS__", ASSETS).replace("__SYMBOLS__", SYMS) os.makedirs(os.path.dirname(OUT), exist_ok=True) with open(OUT, "w", encoding="utf-8") as f: f.write(html) print("wrote", OUT, f"({len(html)//1024} KB)")