89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
"""盲航 cover.png 生成:1080x1920,深空底 + 星点 + 游戏名 + 玩法提示。"""
|
|
import math
|
|
import random
|
|
|
|
from PIL import Image, ImageDraw, ImageFilter, ImageFont
|
|
|
|
W, H = 1080, 1920
|
|
FONT = "/home/xsl/SoundGame/app/src/reflex/gen/NotoSansSC-Bold.ttf"
|
|
OUT = "/home/xsl/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)
|