143 lines
5.3 KiB
Python
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()
|