diff options
Diffstat (limited to 'scripts/make-cc0-art.py')
| -rw-r--r-- | scripts/make-cc0-art.py | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/scripts/make-cc0-art.py b/scripts/make-cc0-art.py index 897ec4f..f5c97ee 100644 --- a/scripts/make-cc0-art.py +++ b/scripts/make-cc0-art.py @@ -5,7 +5,7 @@ Reads the two provenanced CC0 packs in third_party/ (Kenney Tiny Farm tiles, Puny Characters) and emits Deterministic CC0 Atlases for the prototype: src/LivingVillage.Desktop/Assets/cc0-tiles.png 128x32 (4 ground tiles, 32px each) - src/LivingVillage.Desktop/Assets/cc0-characters.png 2560x48 (5 variants x 4 directions x 4 frames, 32x48 cells) + src/LivingVillage.Desktop/Assets/cc0-characters.png 3840x48 (5 variants x 4 directions x 6 frames, 32x48 cells) Mapping strategy (16 -> 32): integer 2x nearest-neighbour upscale of every source sprite; ground tiles fill the 32x32 cell exactly; Puny sprites keep their @@ -115,14 +115,18 @@ def build_cc0_tile_atlas(): def build_cc0_character_atlas(): - """5 variants x 4 directions x 4 frames of 32x48 cells from Puny characters. + """5 variants x 4 directions x 6 frames of 32x48 cells from Puny characters. Layout: each 32x48 CELL = source 16x24 content band scaled 2x (32x48), anchored bottom (feet on the ground line). Directions: the pack provides south-facing art only; south/north use the same band (pack limitation recorded in the commit), west/east are mirrored copies so walkers always read toward the player. + + Frames 0-3 are the walk cycle (source poses 0-3). Frames 4-5 are the idle + breath cycle: the neutral pose (source pose 0) relaxed, then raised 1px for + the inhale. The pack has no dedicated idle art, so this reuses pose 0. """ - c = Canvas(2560, 48) + c = Canvas(3840, 48) variant_files = [ "Soldier-Blue.png", @@ -143,12 +147,16 @@ def build_cc0_character_atlas(): cell_w = 32 for vi, pose_cells in enumerate(variants): for di in range(4): - for frame in range(4): - sprite = pose_cells[frame].resize((32, 48), Image.NEAREST) + # Walk frames reuse poses 0-3; idle frames 4-5 reuse the neutral pose 0, + # with frame 5 raised 1px so the pair reads as a breath. + frame_poses = [pose_cells[0], pose_cells[1], pose_cells[2], pose_cells[3], pose_cells[0], pose_cells[0]] + frame_offsets = [0, 0, 0, 0, 0, -1] + for frame in range(6): + sprite = frame_poses[frame].resize((32, 48), Image.NEAREST) if di in (1, 3): sprite = sprite.transpose(Image.FLIP_LEFT_RIGHT) - ox = cell_w * ((vi * 4 + di) * 4 + frame) - c.blit(sprite, ox, 0, scale=1) + ox = cell_w * ((vi * 4 + di) * 6 + frame) + c.blit(sprite, ox, frame_offsets[frame], scale=1) return c @@ -158,7 +166,7 @@ def main(): ASSETS.mkdir(parents=True, exist_ok=True) targets = [ ("cc0-tiles.png", build_cc0_tile_atlas(), 128, 32), - ("cc0-characters.png", build_cc0_character_atlas(), 2560, 48), + ("cc0-characters.png", build_cc0_character_atlas(), 3840, 48), ] for name, canvas, w, h in targets: path = ASSETS / name |
