- 新增 web/ 纯音频 HTML5 平台:共享引擎(手势/WebAudio 三层/设置/震动)、 Node 零依赖服务器(静态 + 注册登录 + 进度存档 API) - 游戏:剑与声(RPG 新作)、声命线、暗室(重设计)、音序回响(重设计)、 节拍行者(跟随领奏重构)、盲航(同向闪避重构);声东击西删除 - 全局功能:男声/女声双套 TTS 资产、三档语速、BGM 音量三档、 震动反馈语言(10 种震型)、服务器进度同步 - 资产:899 ogg + 899 m4a(Qwen3-TTS 双性别语音、Stable Audio 3 音效、 Mureka BGM 4+3 首),终检零缺失 - 文档:docs/design/ 13 篇设计审查文档、docs/audio/ 资产管线、 web/server/README.md API 文档
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""节拍行者封面生成:1080x1920 深色底 + 游戏名 + 玩法提示。"""
|
|
import math
|
|
import os
|
|
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
W, H = 1080, 1920
|
|
ROOT = "/home/ubuntu/SoundGame/web/rhythm"
|
|
FONT = os.path.join(ROOT, "gen", "NotoSansSC-Bold.ttf")
|
|
|
|
img = Image.new("RGB", (W, H), (10, 12, 24))
|
|
d = ImageDraw.Draw(img)
|
|
|
|
# 底部到中部渐亮
|
|
for y in range(H):
|
|
t = y / H
|
|
r = int(10 + 20 * t)
|
|
g = int(12 + 14 * t)
|
|
b = int(24 + 46 * t)
|
|
d.line([(0, y), (W, y)], fill=(r, g, b))
|
|
|
|
# 律动音柱装饰(模拟频谱柱,青/品红双色)
|
|
bars = 24
|
|
bw = W // bars
|
|
for i in range(bars):
|
|
h = int(120 + 260 * abs(math.sin(i * 1.7) * 0.6 + math.sin(i * 0.9) * 0.4))
|
|
color = (0, 229, 255) if i % 2 == 0 else (255, 64, 129)
|
|
x0 = i * bw + 8
|
|
d.rounded_rectangle([x0, H - 320 - h, x0 + bw - 16, H - 320], 10, fill=color)
|
|
# 顶部镜像倒影(暗一些)
|
|
dim = tuple(c // 3 for c in color)
|
|
d.rounded_rectangle([x0, 260, x0 + bw - 16, 260 + h // 2], 10, fill=dim)
|
|
|
|
# 节拍圆点(四四拍)
|
|
for i in range(4):
|
|
cx = W // 2 - 180 + i * 120
|
|
cy = H - 180
|
|
fill = (255, 215, 64) if i == 0 else (60, 66, 90)
|
|
d.ellipse([cx - 28, cy - 28, cx + 28, cy + 28], fill=fill)
|
|
|
|
f_title = ImageFont.truetype(FONT, 220)
|
|
f_sub = ImageFont.truetype(FONT, 56)
|
|
f_small = ImageFont.truetype(FONT, 40)
|
|
|
|
title = "节拍行者"
|
|
bbox = d.textbbox((0, 0), title, font=f_title)
|
|
tw = bbox[2] - bbox[0]
|
|
ty = H // 2 - 260
|
|
# 描边阴影 + 主字
|
|
d.text((W // 2 - tw // 2 + 6, ty + 8), title, font=f_title, fill=(0, 0, 0))
|
|
d.text((W // 2 - tw // 2, ty), title, font=f_title, fill=(240, 245, 255))
|
|
|
|
sub = "听音踩点 · 跟上节拍"
|
|
bbox = d.textbbox((0, 0), sub, font=f_sub)
|
|
d.text((W // 2 - (bbox[2] - bbox[0]) // 2, ty + 300), sub, font=f_sub, fill=(0, 229, 255))
|
|
|
|
hint = "滑上下左右 · 单击 · 双击"
|
|
bbox = d.textbbox((0, 0), hint, font=f_small)
|
|
d.text((W // 2 - (bbox[2] - bbox[0]) // 2, ty + 410), hint, font=f_small, fill=(150, 160, 190))
|
|
|
|
out = os.path.join(ROOT, "cover.png")
|
|
img.save(out)
|
|
print("saved", out, img.size)
|