Files
Sprinter-SDCC/examples/space/gen_sprites.py
T
snark13 8792594c5a examples/space: демо полного спрайтового стека (атлас W0 + авто-анимации)
Всё сразу: .atl с диска (mkatlas.py из генерённых лент) → atlas_load в
EMM-страницу (W0, ISR-стаб) → движок sprite_t.page → авто-анимации:
5 астероидов (ANIM_LOOP вращение + sprite_moveto к случайным целям
разных скоростей; по прибытии — взрыв ANIM_ONCE в точке + новая цель,
по SPR_ANIM_DONE взрыв прячется), маяк ANIM_PINGPONG; дабл-буфер,
FPS-метр, ESC.  ~48 fps (vsync-кап).

Грабли по дороге (оба — прикладные, не библиотека):
- фон рисовался rand()'ом с разными последовательностями на страницах
  → мерцание звёзд; фикс — фиксированный seed на draw_space;
- НЕ была скопирована палитра страницы 0 → 1 (у каждой страницы своя,
  см. gfx.h) — страница 1 показывалась чёрной, флип мигал
  «сцена/чёрный»; fps-плашка теперь рисуется на ОБЕИХ страницах
  (fps_draw=2 кадра при смене секунды).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 16:40:48 +03:00

99 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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)])