90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
||
"""Star Raid Android 图标生成:使用游戏初始飞机 falcon(ship0) 像素数据"""
|
||
import os
|
||
import random
|
||
from PIL import Image, ImageDraw
|
||
|
||
BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
RES = os.path.join(BASE, "app", "src", "main", "res")
|
||
|
||
# —— 初始飞机 falcon (ship0) 像素数据(来自 star-raid/js/sprites.js)——
|
||
PAL = {"K": "#14142b", "W": "#f2f0e6", "C": "#43e8ff", "R": "#e0393e", "D": "#8f1d2c", "O": "#ff9a3d"}
|
||
SHIP = [
|
||
"......K......", ".....KWK.....", ".....KWK.....", ".....KCK.....",
|
||
"....KWWWK....", "....KRCRK....", "...KWRRRWK...", "..KWKRDRKWK..",
|
||
"..KWRRRRRWK..", ".KWKRRRRRKWK.", ".KRRKWWWKRRK.", "KKRDKWKWKDRKK",
|
||
"KD..KWKWK..DK", "K...KOKOK...K", "....KOKOK....",
|
||
]
|
||
BG_COLOR = (10, 10, 24) # 深空蓝黑
|
||
|
||
def hex2rgb(h):
|
||
h = h.lstrip("#")
|
||
return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
|
||
|
||
def render_ship(scale, mono=False):
|
||
w, h = len(SHIP[0]), len(SHIP)
|
||
img = Image.new("RGBA", (w * scale, h * scale), (0, 0, 0, 0))
|
||
d = ImageDraw.Draw(img)
|
||
for y, row in enumerate(SHIP):
|
||
for x, ch in enumerate(row):
|
||
if ch != ".":
|
||
c = (255, 255, 255) if mono else hex2rgb(PAL[ch])
|
||
d.rectangle([x * scale, y * scale, (x + 1) * scale - 1, (y + 1) * scale - 1], fill=c + (255,))
|
||
return img
|
||
|
||
def stars_bg(size, seed=7, n=120):
|
||
rnd = random.Random(seed)
|
||
img = Image.new("RGB", (size, size), BG_COLOR)
|
||
d = ImageDraw.Draw(img)
|
||
for _ in range(n):
|
||
x, y = rnd.randint(0, size - 1), rnd.randint(0, size - 1)
|
||
r = rnd.choice([1, 1, 1, 2])
|
||
col = rnd.choice([(242, 240, 230), (67, 232, 255), (255, 255, 255), (150, 170, 220)])
|
||
d.rectangle([x, y, x + r, y + r], fill=col)
|
||
for _ in range(6):
|
||
x, y = rnd.randint(20, size - 20), rnd.randint(20, size - 20)
|
||
d.rectangle([x - 1, y, x + 1, y], fill=(242, 240, 230))
|
||
d.rectangle([x, y - 1, x, y + 1], fill=(242, 240, 230))
|
||
return img
|
||
|
||
def paste_center(canvas, layer, scale):
|
||
fg = render_ship(scale)
|
||
x = (canvas.width - fg.width) // 2
|
||
y = (canvas.height - fg.height) // 2
|
||
canvas.alpha_composite(fg, (x, y))
|
||
|
||
def save_png(img, path):
|
||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||
img.save(path, "PNG")
|
||
print("saved", path, img.size)
|
||
|
||
# 1) adaptive icon foreground:512 透明底 + 飞机 16x(176x240,居中,安全区内)
|
||
fg = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
|
||
paste_center(fg, render_ship, 16)
|
||
save_png(fg, os.path.join(RES, "drawable", "ic_launcher_fg.png"))
|
||
|
||
# 2) mono(Android 13 主题图标):白色飞机
|
||
mono = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
|
||
mono_ship = render_ship(16, mono=True)
|
||
mono.alpha_composite(mono_ship, ((512 - mono_ship.width) // 2, (512 - mono_ship.height) // 2))
|
||
save_png(mono, os.path.join(RES, "drawable", "ic_launcher_mono.png"))
|
||
|
||
# 3) 完整图标(背景 + 飞机):用于 legacy mipmap
|
||
full = stars_bg(512).convert("RGBA")
|
||
paste_center(full, render_ship, 16)
|
||
save_png(full, os.path.join(RES, "drawable", "ic_launcher_full.png"))
|
||
|
||
# 4) legacy mipmap 各尺寸
|
||
mipmap_sizes = {"mdpi": 48, "hdpi": 72, "xhdpi": 96, "xxhdpi": 144, "xxxhdpi": 192}
|
||
for dpi, size in mipmap_sizes.items():
|
||
icon = full.resize((size, size), Image.NEAREST)
|
||
for name in ("ic_launcher", "ic_launcher_round"):
|
||
save_png(icon, os.path.join(RES, "mipmap-" + dpi, name + ".png"))
|
||
|
||
# 5) splash logo:透明底飞机大图(windowBackground layer-list 用)
|
||
splash = Image.new("RGBA", (512, 512), (0, 0, 0, 0))
|
||
paste_center(splash, render_ship, 24)
|
||
save_png(splash, os.path.join(RES, "drawable", "splash_logo.png"))
|
||
|
||
print("DONE")
|