四泳道并行全流水线(资产→开发→测试→玩家迭代闭环),双双 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(压缩候选)
56 lines
2.0 KiB
Python
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"))
|