Files
SoundGame/tools/gen_bridge_cover.py
T
xsl 4b39ae2e49 feat(new8/batch3-4): cipher/teahouse/keeper/bridge 全套交付——new8 八款全部可交付收官
四泳道并行全流水线(资产→开发→测试→玩家迭代闭环),双双 R1-R2 连续达标裁定可交付:
- cipher《暗码》223 断言:摩尔斯解码嵌叙事/四结局矩阵/暴露度逐NIGHT验算/三层兜底;R2 三修(链首标记音/预警震/结局计数句+4句补录)4/4 全满分档
- teahouse《深夜茶馆》205 断言:泡茶时机窗/经济逐晚对账/多晚弧线;连续 2 轮 4/4 愿意玩 P0=0
- keeper《守塔人》257 断言:时空签名教学-兑现/插叙触发回返/trust×truth 档位/4结局;R2 F1/F2 坐实(震型豁免/首播跳句锁)4/4
- bridge《星环舰长》336 断言:巡检节奏逐毫秒/危机×系统态矩阵/仲裁7场景/忠诚差分/评级验算;R1 当场修F1-F4、R2 F5 菜单顺延保护 4/4 上行

公共:index.html 四卡片+profiles.js 四桶+check_all_assets 登记(预接线)、00-program 八款进度账收账、
gen_voice_dual 四游戏段、README/HANDOVER 阵容更新(11 款)、voice_text.json 四游戏键、mureka 台账(累计$1.26/$2.00)

验证:四游戏 playtest 223/205/257/336 全绿 + guide 122/122 + 全项目 15 游戏资产终检绿
遗留:keeper 三代人声滤波人耳试听(最高优先,ASR 对滤波句失明)、bridge 音频 32MB 超软指引 2MB(压缩候选)
2026-09-14 05:48:13 +08:00

56 lines
2.0 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""《星环舰长》封面生成:1080x1920 竖图(星环 + 四象限方位刻度的深空舰桥意象)。
用法:.venv-tts/bin/python tools/gen_bridge_cover.py → web/bridge/cover.png
"""
import math
import os
import numpy as np
from PIL import Image, ImageDraw
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
W, H = 1080, 1920
rng = np.random.default_rng(22)
# 深空径向底
yy, xx = np.mgrid[0:H, 0:W].astype(np.float32)
cx, cy = W / 2, H * 0.42
d = np.sqrt((xx - cx) ** 2 + (yy - cy) ** 2) / (W * 1.1)
base = np.stack([
8 + 14 * np.exp(-d * 2.2), # R
10 + 18 * np.exp(-d * 2.0), # G
22 + 38 * np.exp(-d * 1.8), # B
], axis=2)
img = Image.fromarray(np.clip(base, 0, 255).astype(np.uint8), "RGB")
dr = ImageDraw.Draw(img)
# 星点
for _ in range(420):
x, y = rng.integers(0, W), rng.integers(0, H)
b = int(rng.integers(60, 220))
r = 1 if rng.random() < 0.9 else 2
dr.ellipse([x - r, y - r, x + r, y + r], fill=(b, b, min(255, b + 20)))
# 星环(倾斜椭圆弧,亮青)
def ring(radius, width, alpha, tilt=0.32, span=(0, 360), color=(120, 210, 255)):
bbox = [cx - radius, cy - radius * (1 - tilt), cx + radius, cy + radius * (1 + tilt)]
dr.arc(bbox, span[0], span[1], fill=color, width=width)
for rad, wd, col in ((430, 5, (90, 180, 230)), (455, 3, (140, 220, 255)), (480, 2, (80, 150, 210))):
ring(rad, wd, 255, color=col)
# 四象限刻度(左舷/右舷/舰首/舰尾 方位标记点)
for ang, lab in ((180, None), (0, None), (270, None), (90, None)):
a = math.radians(ang)
px = cx + 500 * math.cos(a)
py = cy + 500 * (1 - 0.32) * math.sin(a)
dr.ellipse([px - 6, py - 6, px + 6, py + 6], fill=(255, 210, 120))
# 舰桥光晕(中心暖核)
for rad, col in ((60, (255, 220, 160)), (36, (255, 235, 190)), (18, (255, 245, 220))):
dr.ellipse([cx - rad, cy - rad, cx + rad, cy + rad], fill=col)
img.save(os.path.join(ROOT, "web", "bridge", "cover.png"))
print("cover ->", os.path.join(ROOT, "web", "bridge", "cover.png"))