284 lines
12 KiB
Python
284 lines
12 KiB
Python
from __future__ import annotations
|
|
|
|
import math
|
|
from pathlib import Path
|
|
from typing import Callable
|
|
|
|
from PIL import Image, ImageDraw, ImageFilter
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
OUT = ROOT / "src" / "assets" / "images" / "ui" / "battle-ui-icons.png"
|
|
FRAME = 48
|
|
SCALE = 4
|
|
|
|
|
|
def main() -> None:
|
|
OUT.parent.mkdir(parents=True, exist_ok=True)
|
|
icons: list[tuple[str, Callable[[ImageDraw.ImageDraw], None]]] = [
|
|
("hp", draw_hp),
|
|
("might", draw_might),
|
|
("intelligence", draw_intelligence),
|
|
("leadership", draw_leadership),
|
|
("attack", draw_attack),
|
|
("defense", draw_defense),
|
|
("move", draw_move),
|
|
("mastery", draw_mastery),
|
|
("sword", draw_sword),
|
|
("spear", draw_spear),
|
|
("axe", draw_axe),
|
|
("bow", draw_bow),
|
|
("strategy", draw_strategy),
|
|
("horse", draw_horse),
|
|
("armor", draw_armor),
|
|
("accessory", draw_accessory),
|
|
("hit", draw_hit),
|
|
("critical", draw_critical),
|
|
("terrain", draw_terrain),
|
|
("counter", draw_counter),
|
|
("advantage", draw_advantage),
|
|
("success", draw_success),
|
|
]
|
|
cols = 5
|
|
rows = math.ceil(len(icons) / cols)
|
|
atlas = Image.new("RGBA", (cols * FRAME, rows * FRAME), (0, 0, 0, 0))
|
|
for index, (_name, draw_icon) in enumerate(icons):
|
|
tile = make_icon(draw_icon)
|
|
atlas.alpha_composite(tile, ((index % cols) * FRAME, (index // cols) * FRAME))
|
|
atlas.save(OUT, optimize=True)
|
|
print(f"Wrote {OUT}")
|
|
|
|
|
|
def make_icon(draw_icon: Callable[[ImageDraw.ImageDraw], None]) -> Image.Image:
|
|
image = Image.new("RGBA", (FRAME * SCALE, FRAME * SCALE), (0, 0, 0, 0))
|
|
draw = ImageDraw.Draw(image, "RGBA")
|
|
draw_icon(draw)
|
|
image = image.filter(ImageFilter.UnsharpMask(radius=1.2, percent=90, threshold=3))
|
|
return image.resize((FRAME, FRAME), Image.Resampling.LANCZOS)
|
|
|
|
|
|
def c(value: tuple[int, int, int, int] | tuple[int, int, int]) -> tuple[int, int, int, int]:
|
|
if len(value) == 3:
|
|
return (value[0], value[1], value[2], 255)
|
|
return value
|
|
|
|
|
|
def line(draw: ImageDraw.ImageDraw, points: list[tuple[int, int]], fill: tuple[int, int, int, int], width: int) -> None:
|
|
scaled = [(x * SCALE, y * SCALE) for x, y in points]
|
|
draw.line(scaled, fill=fill, width=width * SCALE, joint="curve")
|
|
|
|
|
|
def poly(draw: ImageDraw.ImageDraw, points: list[tuple[int, int]], fill, outline=None) -> None:
|
|
scaled = [(x * SCALE, y * SCALE) for x, y in points]
|
|
draw.polygon(scaled, fill=c(fill), outline=c(outline) if outline else None)
|
|
|
|
|
|
def ellipse(draw: ImageDraw.ImageDraw, box: tuple[int, int, int, int], fill, outline=None, width=1) -> None:
|
|
scaled = tuple(v * SCALE for v in box)
|
|
draw.ellipse(scaled, fill=c(fill), outline=c(outline) if outline else None, width=width * SCALE)
|
|
|
|
|
|
def rect(draw: ImageDraw.ImageDraw, box: tuple[int, int, int, int], fill, outline=None, width=1) -> None:
|
|
scaled = tuple(v * SCALE for v in box)
|
|
draw.rounded_rectangle(scaled, radius=4 * SCALE, fill=c(fill), outline=c(outline) if outline else None, width=width * SCALE)
|
|
|
|
|
|
def icon_shadow(draw: ImageDraw.ImageDraw) -> None:
|
|
ellipse(draw, (7, 35, 41, 42), (0, 0, 0, 80))
|
|
|
|
|
|
def draw_hp(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(24, 39), (10, 25), (10, 15), (16, 10), (24, 15), (32, 10), (38, 15), (38, 25)], (210, 64, 65), (72, 21, 28))
|
|
poly(draw, [(24, 35), (13, 24), (13, 16), (17, 13), (24, 18), (31, 13), (35, 16), (35, 24)], (255, 130, 111))
|
|
line(draw, [(18, 21), (30, 21)], (255, 235, 188, 240), 2)
|
|
line(draw, [(24, 15), (24, 28)], (255, 235, 188, 240), 2)
|
|
|
|
|
|
def draw_might(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
line(draw, [(13, 35), (31, 17)], (112, 78, 48), 4)
|
|
poly(draw, [(33, 10), (39, 15), (27, 25), (23, 21)], (228, 230, 219), (72, 78, 80))
|
|
line(draw, [(35, 36), (17, 18)], (112, 78, 48), 4)
|
|
poly(draw, [(15, 11), (10, 18), (22, 23), (25, 18)], (217, 221, 211), (65, 70, 73))
|
|
ellipse(draw, (19, 19, 29, 29), (190, 60, 52), (74, 31, 29))
|
|
line(draw, [(18, 30), (24, 36), (30, 30)], (239, 188, 83), 2)
|
|
|
|
|
|
def draw_intelligence(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(13, 13), (25, 9), (38, 13), (38, 34), (25, 38), (13, 34)], (74, 103, 116), (30, 41, 50))
|
|
poly(draw, [(16, 16), (25, 13), (35, 16), (35, 31), (25, 34), (16, 31)], (212, 204, 158))
|
|
line(draw, [(20, 18), (31, 16)], (89, 75, 52, 210), 1)
|
|
line(draw, [(20, 23), (31, 21)], (89, 75, 52, 210), 1)
|
|
line(draw, [(20, 28), (31, 26)], (89, 75, 52, 210), 1)
|
|
ellipse(draw, (9, 26, 17, 36), (145, 95, 64), (67, 37, 31))
|
|
line(draw, [(14, 30), (10, 37)], (231, 206, 150, 230), 2)
|
|
|
|
|
|
def draw_leadership(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
line(draw, [(15, 39), (15, 9)], (118, 92, 58), 3)
|
|
poly(draw, [(17, 11), (38, 15), (31, 23), (38, 31), (17, 27)], (185, 55, 50), (77, 27, 30))
|
|
poly(draw, [(17, 13), (34, 16), (29, 22), (34, 28), (17, 25)], (229, 157, 73))
|
|
ellipse(draw, (11, 35, 20, 43), (208, 176, 88), (73, 55, 31))
|
|
|
|
|
|
def draw_attack(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
line(draw, [(13, 34), (33, 14)], (108, 80, 49), 4)
|
|
poly(draw, [(35, 9), (39, 13), (25, 28), (21, 24)], (225, 226, 217), (70, 76, 78))
|
|
poly(draw, [(25, 25), (33, 32), (30, 36), (21, 28)], (216, 151, 73), (79, 46, 28))
|
|
line(draw, [(14, 34), (21, 41)], (244, 199, 104), 3)
|
|
|
|
|
|
def draw_defense(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(24, 7), (38, 13), (35, 31), (24, 41), (13, 31), (10, 13)], (77, 109, 132), (29, 38, 50))
|
|
poly(draw, [(24, 11), (34, 15), (32, 29), (24, 36), (16, 29), (14, 15)], (113, 154, 183))
|
|
line(draw, [(24, 12), (24, 36)], (225, 206, 138, 230), 2)
|
|
line(draw, [(15, 22), (33, 22)], (225, 206, 138, 220), 2)
|
|
|
|
|
|
def draw_move(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(15, 29), (24, 31), (36, 35), (35, 40), (22, 40), (12, 35)], (72, 98, 96), (25, 38, 38))
|
|
poly(draw, [(19, 10), (28, 10), (27, 28), (18, 29)], (148, 108, 72), (65, 43, 30))
|
|
poly(draw, [(20, 27), (31, 30), (36, 34), (23, 34), (15, 31)], (213, 167, 94))
|
|
line(draw, [(32, 14), (39, 10)], (220, 204, 144, 170), 2)
|
|
line(draw, [(34, 22), (42, 21)], (220, 204, 144, 150), 2)
|
|
|
|
|
|
def draw_mastery(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
points = []
|
|
for i in range(10):
|
|
radius = 15 if i % 2 == 0 else 6
|
|
angle = -math.pi / 2 + i * math.pi / 5
|
|
points.append((24 + math.cos(angle) * radius, 22 + math.sin(angle) * radius))
|
|
poly(draw, [(round(x), round(y)) for x, y in points], (237, 185, 72), (88, 58, 24))
|
|
rect(draw, (12, 33, 36, 39), (61, 73, 69), (30, 38, 37))
|
|
rect(draw, (14, 35, 27, 37), (129, 206, 120), None)
|
|
|
|
|
|
def draw_sword(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(32, 6), (38, 11), (21, 31), (17, 27)], (226, 229, 220), (73, 78, 80))
|
|
poly(draw, [(17, 28), (23, 34), (20, 38), (13, 31)], (201, 135, 67), (72, 44, 31))
|
|
line(draw, [(12, 37), (17, 32)], (235, 205, 112), 3)
|
|
line(draw, [(18, 25), (25, 32)], (75, 43, 33), 2)
|
|
|
|
|
|
def draw_spear(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
line(draw, [(14, 39), (31, 12)], (117, 82, 45), 3)
|
|
poly(draw, [(33, 6), (39, 18), (29, 17)], (226, 229, 220), (71, 77, 78))
|
|
poly(draw, [(29, 18), (35, 20), (30, 24)], (187, 61, 51), (75, 31, 30))
|
|
|
|
|
|
def draw_axe(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
line(draw, [(17, 39), (30, 10)], (112, 78, 48), 4)
|
|
poly(draw, [(27, 8), (42, 13), (39, 25), (28, 21), (24, 15)], (217, 221, 211), (65, 70, 73))
|
|
poly(draw, [(24, 15), (17, 19), (24, 23), (29, 20)], (183, 130, 64), (75, 45, 29))
|
|
|
|
|
|
def draw_bow(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
line(draw, [(29, 8), (34, 14), (35, 25), (30, 37)], (184, 121, 62), 4)
|
|
line(draw, [(29, 8), (18, 22), (30, 37)], (217, 199, 139, 220), 1)
|
|
line(draw, [(15, 24), (35, 24)], (220, 225, 214), 2)
|
|
poly(draw, [(36, 24), (30, 20), (30, 28)], (219, 83, 66), (75, 29, 26))
|
|
|
|
|
|
def draw_strategy(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(11, 30), (18, 13), (30, 10), (38, 22), (34, 36), (22, 39)], (223, 221, 202), (78, 77, 65))
|
|
line(draw, [(18, 16), (34, 23)], (107, 121, 129, 180), 1)
|
|
line(draw, [(16, 22), (33, 28)], (107, 121, 129, 180), 1)
|
|
line(draw, [(14, 29), (30, 34)], (107, 121, 129, 180), 1)
|
|
line(draw, [(25, 17), (17, 40)], (124, 84, 49), 2)
|
|
|
|
|
|
def draw_horse(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(11, 25), (18, 15), (31, 15), (39, 23), (35, 31), (22, 31)], (150, 114, 80), (60, 43, 33))
|
|
poly(draw, [(30, 15), (40, 9), (42, 17), (36, 21)], (150, 114, 80), (60, 43, 33))
|
|
ellipse(draw, (38, 12, 41, 15), (20, 18, 14))
|
|
line(draw, [(17, 30), (14, 40)], (90, 62, 42), 3)
|
|
line(draw, [(29, 30), (33, 40)], (90, 62, 42), 3)
|
|
line(draw, [(13, 20), (8, 16)], (92, 57, 35), 3)
|
|
|
|
|
|
def draw_armor(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(17, 9), (31, 9), (38, 18), (34, 39), (14, 39), (10, 18)], (79, 98, 116), (28, 38, 48))
|
|
poly(draw, [(20, 12), (28, 12), (34, 20), (31, 35), (17, 35), (14, 20)], (121, 143, 158))
|
|
line(draw, [(24, 13), (24, 36)], (216, 178, 94, 190), 2)
|
|
line(draw, [(16, 23), (32, 23)], (43, 55, 66, 200), 1)
|
|
line(draw, [(15, 29), (33, 29)], (43, 55, 66, 200), 1)
|
|
|
|
|
|
def draw_accessory(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
ellipse(draw, (13, 12, 35, 34), (42, 82, 90), (218, 187, 96), 2)
|
|
ellipse(draw, (19, 18, 29, 28), (84, 174, 166), (236, 223, 155), 1)
|
|
line(draw, [(24, 34), (24, 40)], (218, 187, 96), 2)
|
|
ellipse(draw, (21, 38, 27, 44), (204, 65, 59), (80, 29, 29))
|
|
|
|
|
|
def draw_hit(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
ellipse(draw, (9, 9, 39, 39), (32, 50, 58), (94, 149, 164), 2)
|
|
ellipse(draw, (16, 16, 32, 32), (83, 134, 140), (211, 218, 172), 2)
|
|
ellipse(draw, (21, 21, 27, 27), (241, 208, 96), (73, 56, 28), 1)
|
|
line(draw, [(31, 17), (40, 8)], (225, 229, 219), 2)
|
|
|
|
|
|
def draw_critical(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
points = []
|
|
for i in range(14):
|
|
radius = 18 if i % 2 == 0 else 7
|
|
angle = -math.pi / 2 + i * math.pi / 7
|
|
points.append((24 + math.cos(angle) * radius, 24 + math.sin(angle) * radius))
|
|
poly(draw, [(round(x), round(y)) for x, y in points], (230, 78, 61), (83, 32, 27))
|
|
line(draw, [(17, 16), (31, 32)], (255, 229, 139), 3)
|
|
line(draw, [(31, 16), (17, 32)], (255, 229, 139), 3)
|
|
|
|
|
|
def draw_terrain(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
poly(draw, [(7, 35), (17, 20), (24, 32), (32, 14), (42, 35)], (81, 117, 69), (33, 54, 34))
|
|
poly(draw, [(7, 35), (18, 28), (30, 33), (42, 35), (42, 40), (7, 40)], (122, 102, 63), (56, 45, 31))
|
|
line(draw, [(17, 23), (19, 27)], (215, 206, 158), 1)
|
|
line(draw, [(32, 17), (34, 22)], (215, 206, 158), 1)
|
|
|
|
|
|
def draw_counter(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
line(draw, [(13, 30), (30, 13)], (220, 224, 214), 3)
|
|
line(draw, [(35, 18), (18, 35)], (220, 224, 214), 3)
|
|
poly(draw, [(31, 9), (39, 12), (33, 18)], (216, 151, 73), (75, 41, 28))
|
|
poly(draw, [(17, 39), (9, 36), (15, 30)], (216, 151, 73), (75, 41, 28))
|
|
|
|
|
|
def draw_advantage(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
ellipse(draw, (9, 9, 39, 39), (32, 50, 58), (94, 149, 164), 2)
|
|
poly(draw, [(15, 17), (28, 17), (28, 12), (38, 22), (28, 32), (28, 27), (15, 27)], (229, 157, 73), (76, 48, 30))
|
|
poly(draw, [(33, 31), (20, 31), (20, 36), (10, 26), (20, 16), (20, 21), (33, 21)], (113, 154, 183), (29, 38, 50))
|
|
ellipse(draw, (20, 20, 28, 28), (237, 185, 72), (79, 52, 24))
|
|
|
|
|
|
def draw_success(draw: ImageDraw.ImageDraw) -> None:
|
|
icon_shadow(draw)
|
|
rect(draw, (11, 11, 37, 35), (76, 103, 91), (29, 43, 39), 2)
|
|
poly(draw, [(14, 14), (34, 14), (31, 23), (34, 32), (14, 32), (17, 23)], (184, 145, 83), (77, 55, 31))
|
|
line(draw, [(17, 24), (22, 29), (32, 17)], (225, 245, 202), 3)
|
|
ellipse(draw, (18, 36, 30, 43), (180, 63, 58), (73, 27, 27))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|