feat(entities): andamiatge del sistema d'entitats (classes, factory, bus, YAML, placeholders, smoke tests)

This commit is contained in:
JailDesigner committed 2026-04-21 12:35:19 +02:00
1 parent 984cc820c0
commit 96b71b0f65
48 files changed
+1957

No files matched your search

+76
View File
@@ -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())