#!/usr/bin/env python3
"""Генератор спрайтов для examples/space (raw-ленты для mkatlas.py).

asteroid.raw — 16×16×4 (LOOP): серый астероид, кратеры вращаются по
фазам (шаг 22.5°).
explode.raw  — 16×16×4 (ONCE): расширяющийся взрыв (жёлтое ядро →
кольца → разлёт искр).
beacon.raw   — 16×16×4 (PINGPONG): пульсирующий маяк (крест с
растущим свечением).

Палитра — дефолтная EGA (индексы 0..15), 0xFF = прозрачно.
"""
import math

T = 0xFF                       # прозрачный
W = H = 16
CX = CY = 7.5


def blank():
    return [[T] * W for _ in range(H)]


def disc(px, cx, cy, r, c):
    for y in range(H):
        for x in range(W):
            if (x - cx) ** 2 + (y - cy) ** 2 <= r * r:
                px[y][x] = c


def ring(px, cx, cy, r, c):
    for a in range(0, 360, 4):
        x = int(round(cx + r * math.cos(math.radians(a))))
        y = int(round(cy + r * math.sin(math.radians(a))))
        if 0 <= x < W and 0 <= y < H:
            px[y][x] = c


def dot(px, x, y, c):
    if 0 <= x < W and 0 <= y < H:
        px[int(y)][int(x)] = c


def asteroid(phase):
    px = blank()
    disc(px, CX, CY, 6.8, 7)                     # LIGHTGRAY тело
    ring(px, CX, CY, 6.8, 8)                     # DARKGRAY контур
    for i in range(3):                           # кратеры на орбите
        a = math.radians(phase * 22.5 + i * 120)
        disc(px, CX + 3.6 * math.cos(a), CY + 3.6 * math.sin(a), 1.4, 8)
    dot(px, CX - 2, CY - 3, 15)                  # блик WHITE
    return px


def explode(phase):
    px = blank()
    if phase == 0:
        disc(px, CX, CY, 2.2, 14)                # YELLOW ядро
    elif phase == 1:
        disc(px, CX, CY, 3.8, 14)
        ring(px, CX, CY, 4.6, 12)                # LIGHTRED
    elif phase == 2:
        ring(px, CX, CY, 4.2, 14)
        ring(px, CX, CY, 6.0, 12)
        ring(px, CX, CY, 7.0, 4)                 # RED
    else:
        for a in range(0, 360, 30):              # разлёт искр
            r = 6.5
            dot(px, CX + r * math.cos(math.radians(a)),
                CY + r * math.sin(math.radians(a)), 4)
            dot(px, CX + 4 * math.cos(math.radians(a + 15)),
                CY + 4 * math.sin(math.radians(a + 15)), 6)  # BROWN
    return px


def beacon(phase):
    px = blank()
    r = 2 + phase * 1.6
    for d in range(int(r) + 1):                  # крест-лучи
        for xx, yy in ((CX - d, CY), (CX + d, CY), (CX, CY - d), (CX, CY + d)):
            dot(px, round(xx), round(yy), 11)    # LIGHTCYAN
    disc(px, CX, CY, 1.4, 15)                    # WHITE ядро
    if phase >= 2:
        ring(px, CX, CY, r + 1, 9)               # LIGHTBLUE ореол
    return px


def save(name, frames):
    with open(name, "wb") as f:
        for fr in frames:
            for row in fr:
                f.write(bytes(row))
    print(f"gen_sprites: {name} ({len(frames)} кадров)")


save("asteroid.raw", [asteroid(k) for k in range(4)])
save("explode.raw",  [explode(k) for k in range(4)])
save("beacon.raw",   [beacon(k) for k in range(4)])
