77 lines
2.6 KiB
Python
77 lines
2.6 KiB
Python
#!/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())
|