Files
novafarma/scripts/generate_nature_anim.py

143 lines
5.3 KiB
Python

import os
import xml.etree.ElementTree as ET
from PIL import Image
import numpy as np
def generate_nature_animation():
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
out_dir = os.path.join(base_dir, 'assets', 'maps', 'tilesets')
# 1. GRASS
grass_src = os.path.join(base_dir, 'assets', 'grounds', 'grass.png')
# 2. WATER
water_src = os.path.join(base_dir, 'assets', 'grounds', 'water.png')
# 3. CANNABIS
# Try finding loop to locate specific file
import glob
cannabis_matches = glob.glob(os.path.join(base_dir, '**', '*cannabis*stage4*.png'), recursive=True)
cannabis_src = None
if cannabis_matches:
cannabis_src = cannabis_matches[0] # Pick first valid
else:
# Fallback
cannabis_src = os.path.join(base_dir, 'assets', 'intro_assets', 'cannabis_stage4.png') # If exists?
targets = []
if os.path.exists(grass_src):
targets.append(('Grass_Animated', grass_src))
if os.path.exists(water_src):
targets.append(('Water_Animated', water_src))
if cannabis_src and os.path.exists(cannabis_src):
targets.append(('Cannabis_Animated', cannabis_src))
else:
print("⚠️ Could not find Cannabis Stage 4 image.")
if not os.path.exists(out_dir):
os.makedirs(out_dir)
# Function to create wind sway (Skew) - FOR GRASS ONLY
def create_sway_frame(image, factor=0.0):
"""Subtle skew transform for grass wind effect."""
width, height = image.size
return image.transform((width, height), Image.AFFINE, (1, factor, 0, 0, 1, 0), resample=Image.BILINEAR)
# Function to create water glimmer (Subtle brightness/color shift)
def create_water_glimmer_frame(image, brightness_factor=1.0):
"""
Creates a subtle glimmer effect for water.
brightness_factor: 1.0 = normal, 1.05 = slightly brighter (glimmer peak)
"""
from PIL import ImageEnhance
# Brightness shift for shimmer
enhancer = ImageEnhance.Brightness(image)
return enhancer.enhance(brightness_factor)
for name, src in targets:
print(f"Processing {name} from {src}...")
img = Image.open(src).convert('RGBA')
width, height = img.size
# Different animation based on type
if 'Grass' in name or 'Cannabis' in name:
# GRASS: Wind sway (gentle skew)
print(f" → Grass/Plant: Using wind sway animation")
f1 = img
f2 = create_sway_frame(img, -0.08) # Gentle right sway
f3 = img
f4 = create_sway_frame(img, 0.08) # Gentle left sway
elif 'Water' in name:
# WATER: Glimmer effect (brightness shift, NO movement)
print(f" → Water: Using glimmer animation (no skew)")
f1 = img
f2 = create_water_glimmer_frame(img, 1.03) # Subtle brighten
f3 = img
f4 = create_water_glimmer_frame(img, 0.97) # Subtle darken
else:
# Fallback
f1 = f2 = f3 = f4 = img
frames = [f1, f2, f3, f4]
# Combine
total_height = height * 4
combined = Image.new('RGBA', (width, total_height))
for i, f in enumerate(frames):
combined.paste(f, (0, i * height))
out_img_path = os.path.join(out_dir, f"{name}.png")
combined.save(out_img_path)
print(f"Saved PNG: {out_img_path}")
# Generate TSX
tile_w, tile_h = 32, 32 # Assuming standard tiles
# If image is larger (like Cannabis sprite), we treat it as big tiles?
# Tiled animations work on per-tile basis.
# If Cannabis is 64x128, it's composed of 8 tiles (2x4).
# We need to animate EACH tile.
cols = width // tile_w
rows = height // tile_h
total_tiles_per_frame = cols * rows
total_tiles_all = total_tiles_per_frame * 4
root = ET.Element("tileset")
root.set("version", "1.10")
root.set("tiledversion", "1.11.0")
root.set("name", name)
root.set("tilewidth", str(tile_w))
root.set("tileheight", str(tile_h))
root.set("tilecount", str(total_tiles_all))
root.set("columns", str(cols))
image_node = ET.SubElement(root, "image")
image_node.set("source", f"{name}.png")
image_node.set("width", str(width))
image_node.set("height", str(total_height))
# Anim definitions
for i in range(total_tiles_per_frame):
tile_node = ET.SubElement(root, "tile")
tile_node.set("id", str(i))
anim_node = ET.SubElement(tile_node, "animation")
for k in range(4):
frame_node = ET.SubElement(anim_node, "frame")
frame_node.set("tileid", str(i + k * total_tiles_per_frame))
frame_node.set("duration", "200") # Slower wind
tree = ET.ElementTree(root)
ET.indent(tree, space=" ", level=0)
out_tsx_path = os.path.join(out_dir, f"{name}.tsx")
tree.write(out_tsx_path, encoding='UTF-8', xml_declaration=True)
print(f"Saved TSX: {out_tsx_path}")
if __name__ == "__main__":
generate_nature_animation()