feat(entities): andamiatge del sistema d'entitats (classes, factory, bus, YAML, placeholders, smoke tests)
This commit is contained in:
1 parent
984cc820c0
commit
96b71b0f65
48 files changed
+1957
No files matched your search
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Genera GIFs placeholder paletitzats per al sistema d'entitats.
|
||||
|
||||
Motor: el GIF loader del joc (source/core/rendering/gif.cpp) treballa amb
|
||||
GIFs paletitzats (mode P). Aquest script usa Pillow per crear un fitxer
|
||||
per entitat amb un únic frame de color sòlid distintiu, perquè cada
|
||||
entitat es distingeixi en pantalla en ausència d'art definitiu.
|
||||
|
||||
Sortida: data/entities/<name>/<name>.gif amb les mides especificades.
|
||||
|
||||
Execució:
|
||||
python3 tools/entities/generate_placeholders.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
# (width, height, (r,g,b)) per a cada entitat. L'ordre no importa.
|
||||
ENTITIES = {
|
||||
"torch": (16, 16, (255, 165, 0)), # taronja
|
||||
"door": (16, 16, (101, 67, 33)), # marró fosc
|
||||
"mummy": (12, 24, (235, 215, 180)), # beige
|
||||
"sarcophagus": (48, 16, (212, 175, 55)), # daurat (3×1 tiles)
|
||||
"rolling_rock": (16, 16, (128, 128, 128)), # gris
|
||||
"wall_trap": (16, 16, (139, 0, 0)), # vermell fosc
|
||||
"floor_trap": (16, 16, (220, 20, 60)), # vermell clar (crimson)
|
||||
}
|
||||
|
||||
|
||||
def build_gif(width: int, height: int, rgb: tuple[int, int, int]) -> Image.Image:
|
||||
"""Crea un GIF paletitzat d'un sol frame amb color sòlid.
|
||||
|
||||
Entrada 0 de la paleta = transparent (convenció del motor). El color
|
||||
del sprite viu a l'entrada 1; la resta de la paleta s'omple amb
|
||||
negre. Com que només usem un índex visible, l'LZW comprimeix el
|
||||
frame a una rajola de bytes idèntics.
|
||||
"""
|
||||
img = Image.new("P", (width, height), color=1)
|
||||
|
||||
palette = bytearray(256 * 3)
|
||||
# Índex 0: transparent (valor RGB irrellevant; marcat amb transparency).
|
||||
palette[0:3] = bytes((0, 0, 0))
|
||||
palette[3:6] = bytes(rgb)
|
||||
img.putpalette(bytes(palette))
|
||||
return img
|
||||
|
||||
|
||||
def main() -> int:
|
||||
repo_root = Path(__file__).resolve().parents[2]
|
||||
base = repo_root / "data" / "entities"
|
||||
|
||||
for name, (width, height, rgb) in ENTITIES.items():
|
||||
out_dir = base / name
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
out_file = out_dir / f"{name}.gif"
|
||||
|
||||
img = build_gif(width, height, rgb)
|
||||
# transparency=0 mantén la convenció del motor; optimize=False
|
||||
# força un GIF amb GCT estàndard (el loader no accepta variants
|
||||
# minimalistes sense GCT).
|
||||
img.save(out_file, format="GIF", transparency=0, optimize=False)
|
||||
|
||||
size = os.path.getsize(out_file)
|
||||
print(f" {out_file.relative_to(repo_root)} {width}x{height} {size} bytes")
|
||||
|
||||
print(f"OK: {len(ENTITIES)} placeholders escrits a data/entities/")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user