"""盲航 cover.png 生成:1080x1920,深空底 + 星点 + 游戏名 + 玩法提示。""" import math import random from PIL import Image, ImageDraw, ImageFilter, ImageFont W, H = 1080, 1920 FONT = "/home/ubuntu/SoundGame/app/src/reflex/gen/NotoSansSC-Bold.ttf" OUT = "/home/ubuntu/SoundGame/web/space/cover.png" random.seed(42) img = Image.new("RGB", (W, H)) px = img.load() # 深空竖向渐变:上 #05060e -> 下 #101a33 top, bottom = (5, 6, 14), (16, 26, 51) for y in range(H): t = y / (H - 1) for x in range(W): px[x, y] = tuple(int(a + (b - a) * t) for a, b in zip(top, bottom)) d = ImageDraw.Draw(img) # 星点 for _ in range(420): x, y = random.randint(0, W - 1), random.randint(0, H - 1) r = random.random() c = random.randint(120, 255) if r < 0.85: d.point((x, y), fill=(c, c, min(255, c + 20))) else: rr = random.randint(1, 2) d.ellipse([x - rr, y - rr, x + rr, y + rr], fill=(c, c, 255)) # 几颗亮星带光晕 glow = Image.new("RGB", (W, H), (0, 0, 0)) gd = ImageDraw.Draw(glow) for _ in range(14): x, y = random.randint(0, W - 1), random.randint(0, H - 1) gd.ellipse([x - 4, y - 4, x + 4, y + 4], fill=(180, 200, 255)) glow = glow.filter(ImageFilter.GaussianBlur(6)) img = Image.blend(img, Image.new("RGB", (W, H)), 0) # no-op 保引用 from PIL import ImageChops img = ImageChops.add(img, glow) d = ImageDraw.Draw(img) # 下方舷窗弧光(飞船视角的地平线辉光) arc = Image.new("RGB", (W, H), (0, 0, 0)) ad = ImageDraw.Draw(arc) ad.ellipse([-W * 0.55, H * 0.78, W * 1.55, H * 1.75], outline=(70, 130, 220), width=10) arc = arc.filter(ImageFilter.GaussianBlur(18)) img = ImageChops.add(img, arc) d = ImageDraw.Draw(img) def text_center(y, s, size, fill, spacing=0): f = ImageFont.truetype(FONT, size) bbox = d.textbbox((0, 0), s, font=f) w = bbox[2] - bbox[0] x = (W - w) / 2 - bbox[0] if spacing: # 逐字画以加字距 cx = x for ch in s: d.text((cx, y), ch, font=f, fill=fill) cb = d.textbbox((0, 0), ch, font=f) cx += (cb[2] - cb[0]) + spacing else: d.text((x, y), s, font=f, fill=fill) # 标题(大字,加字距) title = "盲 航" f = ImageFont.truetype(FONT, 300) bbox = d.textbbox((0, 0), title, font=f) d.text(((W - (bbox[2] - bbox[0])) / 2 - bbox[0], 640), title, font=f, fill=(232, 240, 255)) # 标题辉光 tglow = Image.new("RGB", (W, H), (0, 0, 0)) td = ImageDraw.Draw(tglow) td.text(((W - (bbox[2] - bbox[0])) / 2 - bbox[0], 640), title, font=f, fill=(60, 90, 160)) tglow = tglow.filter(ImageFilter.GaussianBlur(24)) img = ImageChops.add(img, tglow) d = ImageDraw.Draw(img) d.text(((W - (bbox[2] - bbox[0])) / 2 - bbox[0], 640), title, font=f, fill=(232, 240, 255)) text_center(1060, "SPACE · BLIND FLIGHT", 40, (110, 140, 200)) text_center(1230, "闭眼驾驶,听声闪避", 64, (200, 214, 240)) text_center(1340, "警报来自哪个方向,就朝反方向滑动", 40, (130, 145, 175)) text_center(1420, "单击加速 · 双击护盾 · 撞击三次坠毁", 40, (130, 145, 175)) img.save(OUT) print("saved", OUT, img.size)