#!/usr/bin/env python3 """Cut a grid-based sprite sheet (rows x cols of equal-size frames in one PNG) into the assets/sprites//frame_NN.png convention this project's sprite loader expects. Usage: python scripts/slice_spritesheet.py idle_sheet.png assets/sprites/idle --cols 6 --rows 1 """ from __future__ import annotations import argparse from pathlib import Path from PIL import Image def slice_sheet(sheet_path: Path, out_dir: Path, cols: int, rows: int) -> int: sheet = Image.open(sheet_path).convert("RGBA") frame_w = sheet.width // cols frame_h = sheet.height // rows if frame_w == 0 or frame_h == 0: raise ValueError(f"sheet is {sheet.width}x{sheet.height}, too small for {cols}x{rows} frames") out_dir.mkdir(parents=True, exist_ok=True) count = 0 for row in range(rows): for col in range(cols): box = (col * frame_w, row * frame_h, (col + 1) * frame_w, (row + 1) * frame_h) frame = sheet.crop(box) frame.save(out_dir / f"frame_{count:02d}.png") count += 1 return count def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("sheet", type=Path, help="path to the grid sprite sheet PNG") parser.add_argument("out_dir", type=Path, help="e.g. assets/sprites/idle") parser.add_argument("--cols", type=int, required=True) parser.add_argument("--rows", type=int, default=1) args = parser.parse_args() count = slice_sheet(args.sheet, args.out_dir, args.cols, args.rows) print(f"Wrote {count} frames to {args.out_dir}") return 0 if __name__ == "__main__": raise SystemExit(main())