✅ CREATED: - MINIMAL_TEMPLATE.tmx (clean slate, 5 layers, NO tilesets) - 6 crop spritesheets (256x128, 32x32 tiles) • carrots_spritesheet.png • corn_spritesheet.png (8 missing) • lettuces_spritesheet.png • potatos_spritesheet.png (2 missing) • pumpkins_spritesheet.png (8 missing) • tomatoes_spritesheet.png (1 missing) 📝 LAYERS: 1. 01_Ground (terrain) 2. 02_Crops (plants) 3. 03_Objects (decorations) 4. 04_Buildings (structures) 5. 05_Collision (hidden, 50% opacity) 📊 TOTAL ASSETS ORGANIZED: - 173 individual crop PNG files - 6 combined spritesheets - Minimal Tiled template ready ⏰ NEXT: Generate 113 Kickstarter assets at 02:19 CET (~45 min)
107 lines
3.2 KiB
Python
107 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Create Tiled-compatible spritesheets from Faza 1 crop sprites
|
||
Combines all season/stage sprites into single PNG files for easy Tiled import
|
||
"""
|
||
|
||
from PIL import Image
|
||
import os
|
||
from pathlib import Path
|
||
|
||
# Base path
|
||
CROPS_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/crops/faza1")
|
||
OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/maps 🟣/crop_spritesheets")
|
||
|
||
# Ensure output directory exists
|
||
OUTPUT_DIR.mkdir(exist_ok=True)
|
||
|
||
# Crop types
|
||
CROPS = ['corn', 'tomatoes', 'carrots', 'potatos', 'lettuces', 'pumpkins']
|
||
SEASONS = ['spring', 'summer', 'fall', 'winter']
|
||
STAGES = list(range(1, 9)) # 1-8
|
||
|
||
TILE_SIZE = 32
|
||
|
||
def create_spritesheet(crop_name):
|
||
"""
|
||
Create 8x4 spritesheet (8 stages × 4 seasons)
|
||
Layout:
|
||
Row 1: Spring stages 1-8
|
||
Row 2: Summer stages 1-8
|
||
Row 3: Fall stages 1-8
|
||
Row 4: Winter stages 1-8
|
||
"""
|
||
# Create blank 256x128 image (8 tiles × 32px wide, 4 tiles × 32px tall)
|
||
spritesheet = Image.new('RGBA', (256, 128), (0, 0, 0, 0))
|
||
|
||
crop_path = CROPS_DIR / crop_name
|
||
if not crop_path.exists():
|
||
print(f"❌ Crop folder not found: {crop_path}")
|
||
return None
|
||
|
||
missing_count = 0
|
||
|
||
for season_idx, season in enumerate(SEASONS):
|
||
season_path = crop_path / season
|
||
|
||
if not season_path.exists():
|
||
print(f" ⚠️ Season folder not found: {season_path}")
|
||
continue
|
||
|
||
for stage_idx, stage in enumerate(STAGES):
|
||
sprite_path = season_path / f"stage{stage}.png"
|
||
|
||
if sprite_path.exists():
|
||
try:
|
||
sprite = Image.open(sprite_path).convert('RGBA')
|
||
|
||
# Resize if needed
|
||
if sprite.size != (TILE_SIZE, TILE_SIZE):
|
||
sprite = sprite.resize((TILE_SIZE, TILE_SIZE), Image.NEAREST)
|
||
|
||
# Calculate position
|
||
x = stage_idx * TILE_SIZE
|
||
y = season_idx * TILE_SIZE
|
||
|
||
# Paste into spritesheet
|
||
spritesheet.paste(sprite, (x, y))
|
||
|
||
except Exception as e:
|
||
print(f" ❌ Error loading {sprite_path}: {e}")
|
||
missing_count += 1
|
||
else:
|
||
print(f" ⚠️ Missing: {sprite_path}")
|
||
missing_count += 1
|
||
|
||
# Save spritesheet
|
||
output_path = OUTPUT_DIR / f"{crop_name}_spritesheet.png"
|
||
spritesheet.save(output_path)
|
||
|
||
print(f"✅ Created: {output_path} ({missing_count} missing sprites)")
|
||
|
||
return output_path
|
||
|
||
def main():
|
||
print("=" * 60)
|
||
print("🎨 CREATING CROP SPRITESHEETS FOR TILED")
|
||
print("=" * 60)
|
||
|
||
for crop in CROPS:
|
||
print(f"\n📦 Processing: {crop}")
|
||
create_spritesheet(crop)
|
||
|
||
print("\n" + "=" * 60)
|
||
print(f"✅ COMPLETE! Spritesheets saved to:")
|
||
print(f" {OUTPUT_DIR}")
|
||
print("=" * 60)
|
||
|
||
print("\n📝 TO USE IN TILED:")
|
||
print("1. Map → Add New Tileset")
|
||
print("2. Browse to created spritesheet")
|
||
print("3. Tile Width/Height: 32px")
|
||
print("4. Columns: 8")
|
||
print("5. Click OK!")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|