"""围猎 cover.png 生成:1080x1920,夜幕山林底 + 篝火辉光 + 八方位刻度 + 游戏名 + 玩法提示。""" import math import random from PIL import Image, ImageDraw, ImageFilter, ImageFont, ImageChops W, H = 1080, 1920 FONT = "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc" OUT = "/home/xsl/AutoVideo/SoundGame/web/hunt/cover.png" random.seed(23) img = Image.new("RGB", (W, H)) px = img.load() # 夜幕竖向渐变:上 #060913 -> 下 #1a1206(底部篝火映暖) top, bottom = (6, 9, 19), (26, 18, 6) 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(260): x, y = random.randint(0, W - 1), random.randint(0, int(H * 0.55)) c = random.randint(100, 220) d.point((x, y), fill=(c, c, min(255, c + 15))) # 月亮(右上,冷光) moon = Image.new("RGB", (W, H), (0, 0, 0)) md = ImageDraw.Draw(moon) md.ellipse([W * 0.66, H * 0.07, W * 0.86, H * 0.07 + W * 0.20], fill=(200, 214, 235)) moon = moon.filter(ImageFilter.GaussianBlur(2)) img = ImageChops.add(img, ImageChops.multiply(moon, Image.new("RGB", (W, H), (1, 1, 1)).point(lambda v: v))) # 直接画月盘 + 光晕 d = ImageDraw.Draw(img) d.ellipse([W * 0.68, H * 0.075, W * 0.84, H * 0.075 + W * 0.16], fill=(214, 224, 240)) mglow = Image.new("RGB", (W, H), (0, 0, 0)) mg = ImageDraw.Draw(mglow) mg.ellipse([W * 0.63, H * 0.05, W * 0.89, H * 0.05 + W * 0.26], fill=(40, 48, 66)) mglow = mglow.filter(ImageFilter.GaussianBlur(40)) img = ImageChops.add(img, mglow) d = ImageDraw.Draw(img) d.ellipse([W * 0.68, H * 0.075, W * 0.84, H * 0.075 + W * 0.16], fill=(214, 224, 240)) # 远山与林木剪影(两层) d.polygon([(0, H * 0.52), (W * 0.22, H * 0.40), (W * 0.45, H * 0.50), (W * 0.70, H * 0.38), (W, H * 0.50), (W, H), (0, H)], fill=(8, 10, 16)) for i in range(26): x = random.randint(0, W) base = H * 0.52 + random.randint(-8, 8) h = random.randint(60, 150) w = random.randint(18, 40) d.polygon([(x, base - h), (x - w, base), (x + w, base)], fill=(5, 7, 11)) # 八方位刻度环(猎场罗盘,围绕篝火):刻线 + 四正向加亮 cx, cy, r = W / 2, H * 0.76, W * 0.30 for k in range(8): az = math.radians(k * 45 - 90) # N 在上 x0, y0 = cx + (r - 26) * math.cos(az), cy + (r - 26) * math.sin(az) x1, y1 = cx + r * math.cos(az), cy + r * math.sin(az) main = k % 2 == 0 d.line([x0, y0, x1, y1], fill=(232, 168, 92) if main else (120, 96, 70), width=10 if main else 6) # 外环暗弧 d.ellipse([cx - r - 14, cy - r - 14, cx + r + 14, cy + r + 14], outline=(66, 52, 38), width=4) # 篝火:地面暖光晕 + 火堆 glow = Image.new("RGB", (W, H), (0, 0, 0)) gd = ImageDraw.Draw(glow) gd.ellipse([cx - 300, cy - 130, cx + 300, cy + 190], fill=(96, 46, 10)) gd.ellipse([cx - 170, cy - 70, cx + 170, cy + 110], fill=(150, 70, 14)) glow = glow.filter(ImageFilter.GaussianBlur(60)) img = ImageChops.add(img, glow) d = ImageDraw.Draw(img) # 柴堆 d.line([cx - 90, cy + 66, cx + 90, cy + 30], fill=(26, 16, 8), width=18) d.line([cx - 90, cy + 30, cx + 90, cy + 66], fill=(30, 18, 9), width=18) # 火焰(三层锥形) flame = Image.new("RGB", (W, H), (0, 0, 0)) fd = ImageDraw.Draw(flame) fd.polygon([(cx, cy - 150), (cx - 84, cy + 44), (cx + 84, cy + 44)], fill=(178, 62, 8)) fd.polygon([(cx, cy - 108), (cx - 56, cy + 40), (cx + 56, cy + 40)], fill=(232, 120, 16)) fd.polygon([(cx, cy - 62), (cx - 30, cy + 36), (cx + 30, cy + 36)], fill=(255, 196, 66)) flame = flame.filter(ImageFilter.GaussianBlur(6)) img = ImageChops.add(img, flame) d = ImageDraw.Draw(img) def text_center(y, s, size, fill): f = ImageFont.truetype(FONT, size) bbox = d.textbbox((0, 0), s, font=f) w = bbox[2] - bbox[0] d.text(((W - w) / 2 - bbox[0], y), s, font=f, fill=fill) # 标题(大字 + 辉光) title = "围 猎" f = ImageFont.truetype(FONT, 280) bbox = d.textbbox((0, 0), title, font=f) tx, ty = (W - (bbox[2] - bbox[0])) / 2 - bbox[0], 330 tglow = Image.new("RGB", (W, H), (0, 0, 0)) td = ImageDraw.Draw(tglow) td.text((tx, ty), title, font=f, fill=(140, 64, 12)) tglow = tglow.filter(ImageFilter.GaussianBlur(26)) img = ImageChops.add(img, tglow) d = ImageDraw.Draw(img) d.text((tx, ty), title, font=f, fill=(248, 226, 188)) text_center(700, "NIGHT HUNT", 44, (150, 118, 82)) text_center(880, "听声辨向,背背守夜", 64, (238, 214, 176)) text_center(980, "野兽从八个方向围上来,朝声音的方向滑", 40, (160, 136, 104)) text_center(1058, "单击呼喊支援 · 双击旋风斩 · 撑过五波天亮就赢", 40, (160, 136, 104)) text_center(1780, "2-4 人联机 · 建议戴耳机", 40, (120, 104, 82)) img.save(OUT) print("saved", OUT, img.size)