"""节拍行者封面生成: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)