Features: - Resized 4513 PNG assets to 40% for optimal Tiled performance - Created comprehensive tileset library (grass, dirt, trees, flowers, ruins, walls) - Generated 3 test maps: travnik_32x32, zapuscena_vas_48x48, travnik_s_objekti - Added 9 different ruined building tilesets for TownRestorationSystem integration Tools Added: - resize_assets_for_tiled.py: Batch resize all assets to 40% - generate_tiled_map.py: Auto-generate maps with placed objects - fix_tiled_map.py: Create proper tile-based maps Structure: - Slike_za_Tiled/: 4513 resized assets ready for Tiled - assets/tilesets/: 16 tileset definitions (.tsx files) - assets/maps/: 3 ready-to-use Tiled maps (.tmx files) Documentation: - docs/TILED_SETUP_GUIDE.md: Complete setup and usage guide Ready for map design in Tiled Map Editor!
198 lines
6.1 KiB
Python
198 lines
6.1 KiB
Python
"""
|
|
Generate Tiled map with Collection of Images tileset
|
|
Automatically places dirt, trees, and Kai character
|
|
"""
|
|
import os
|
|
import random
|
|
import xml.etree.ElementTree as ET
|
|
from xml.dom import minidom
|
|
|
|
# Configurations
|
|
SLIKE_DIR = r"c:\novafarma\Slike_za_Tiled"
|
|
OUTPUT_MAP = r"c:\novafarma\assets\maps\auto_generated_map.tmx"
|
|
MAP_WIDTH = 32
|
|
MAP_HEIGHT = 32
|
|
TILE_WIDTH = 48
|
|
TILE_HEIGHT = 48
|
|
|
|
def find_assets():
|
|
"""Find required assets in Slike_za_Tiled folder"""
|
|
assets = {
|
|
'dirt': [],
|
|
'trees': [],
|
|
'kai': None
|
|
}
|
|
|
|
if not os.path.exists(SLIKE_DIR):
|
|
print(f"❌ Error: {SLIKE_DIR} does not exist!")
|
|
print(" Run resize_assets_for_tiled.py first!")
|
|
return None
|
|
|
|
for filename in os.listdir(SLIKE_DIR):
|
|
if not filename.endswith('.png'):
|
|
continue
|
|
|
|
lower_name = filename.lower()
|
|
filepath = os.path.join(SLIKE_DIR, filename)
|
|
|
|
# Find dirt/soil tiles
|
|
if 'dirt' in lower_name or 'soil' in lower_name or 'ground' in lower_name:
|
|
assets['dirt'].append(filepath)
|
|
|
|
# Find trees
|
|
if 'tree' in lower_name:
|
|
assets['trees'].append(filepath)
|
|
|
|
# Find Kai character
|
|
if 'kai' in lower_name or 'character' in lower_name or 'player' in lower_name:
|
|
if assets['kai'] is None: # Take first match
|
|
assets['kai'] = filepath
|
|
|
|
print(f"🔍 Found assets:")
|
|
print(f" - Dirt/Soil tiles: {len(assets['dirt'])}")
|
|
print(f" - Trees: {len(assets['trees'])}")
|
|
print(f" - Kai character: {'✓' if assets['kai'] else '✗'}")
|
|
|
|
return assets
|
|
|
|
def create_tiled_map():
|
|
"""Create Tiled map with auto-placed objects"""
|
|
|
|
# Find assets
|
|
assets = find_assets()
|
|
if not assets:
|
|
return
|
|
|
|
# Create map root
|
|
map_elem = ET.Element('map', {
|
|
'version': '1.10',
|
|
'tiledversion': '1.11.1',
|
|
'orientation': 'orthogonal',
|
|
'renderorder': 'right-down',
|
|
'width': str(MAP_WIDTH),
|
|
'height': str(MAP_HEIGHT),
|
|
'tilewidth': str(TILE_WIDTH),
|
|
'tileheight': str(TILE_HEIGHT),
|
|
'infinite': '0',
|
|
'nextlayerid': '3',
|
|
'nextobjectid': '20'
|
|
})
|
|
|
|
# Create object layer
|
|
objectgroup = ET.SubElement(map_elem, 'objectgroup', {
|
|
'id': '2',
|
|
'name': 'Objects'
|
|
})
|
|
|
|
obj_id = 1
|
|
|
|
# Place 8 dirt tiles in center (2x4 grid)
|
|
print("\n🌍 Placing 8 dirt tiles in center...")
|
|
center_x = MAP_WIDTH // 2 - 1
|
|
center_y = MAP_HEIGHT // 2 - 2
|
|
|
|
for i in range(8):
|
|
if assets['dirt']:
|
|
dirt_asset = random.choice(assets['dirt'])
|
|
x = (center_x + (i % 2)) * TILE_WIDTH
|
|
y = (center_y + (i // 2)) * TILE_HEIGHT
|
|
|
|
obj = ET.SubElement(objectgroup, 'object', {
|
|
'id': str(obj_id),
|
|
'name': f'dirt_{i+1}',
|
|
'x': str(x),
|
|
'y': str(y),
|
|
'width': str(TILE_WIDTH),
|
|
'height': str(TILE_HEIGHT)
|
|
})
|
|
ET.SubElement(obj, 'image', {
|
|
'source': os.path.relpath(dirt_asset, os.path.dirname(OUTPUT_MAP))
|
|
})
|
|
obj_id += 1
|
|
|
|
# Place 10 trees randomly around the dirt area
|
|
print("🌲 Placing 10 trees randomly...")
|
|
tree_positions = []
|
|
attempts = 0
|
|
max_attempts = 100
|
|
|
|
while len(tree_positions) < 10 and attempts < max_attempts:
|
|
attempts += 1
|
|
tree_x = random.randint(2, MAP_WIDTH - 3) * TILE_WIDTH
|
|
tree_y = random.randint(2, MAP_HEIGHT - 3) * TILE_HEIGHT
|
|
|
|
# Avoid center dirt area
|
|
if (center_x * TILE_WIDTH <= tree_x <= (center_x + 2) * TILE_WIDTH and
|
|
center_y * TILE_HEIGHT <= tree_y <= (center_y + 4) * TILE_HEIGHT):
|
|
continue
|
|
|
|
# Avoid placing trees too close together
|
|
too_close = False
|
|
for px, py in tree_positions:
|
|
if abs(tree_x - px) < TILE_WIDTH * 3 and abs(tree_y - py) < TILE_HEIGHT * 3:
|
|
too_close = True
|
|
break
|
|
|
|
if too_close:
|
|
continue
|
|
|
|
if assets['trees']:
|
|
tree_asset = random.choice(assets['trees'])
|
|
tree_positions.append((tree_x, tree_y))
|
|
|
|
obj = ET.SubElement(objectgroup, 'object', {
|
|
'id': str(obj_id),
|
|
'name': f'tree_{len(tree_positions)}',
|
|
'x': str(tree_x),
|
|
'y': str(tree_y),
|
|
'width': str(TILE_WIDTH * 2),
|
|
'height': str(TILE_HEIGHT * 2)
|
|
})
|
|
ET.SubElement(obj, 'image', {
|
|
'source': os.path.relpath(tree_asset, os.path.dirname(OUTPUT_MAP))
|
|
})
|
|
obj_id += 1
|
|
|
|
# Place Kai character near center
|
|
if assets['kai']:
|
|
print("🧑 Placing Kai character...")
|
|
kai_x = (center_x + 2) * TILE_WIDTH + 60
|
|
kai_y = center_y * TILE_HEIGHT + 80
|
|
|
|
obj = ET.SubElement(objectgroup, 'object', {
|
|
'id': str(obj_id),
|
|
'name': 'kai_player',
|
|
'x': str(kai_x),
|
|
'y': str(kai_y),
|
|
'width': str(TILE_WIDTH),
|
|
'height': str(TILE_HEIGHT)
|
|
})
|
|
ET.SubElement(obj, 'image', {
|
|
'source': os.path.relpath(assets['kai'], os.path.dirname(OUTPUT_MAP))
|
|
})
|
|
|
|
# Write XML to file
|
|
os.makedirs(os.path.dirname(OUTPUT_MAP), exist_ok=True)
|
|
|
|
# Pretty print XML
|
|
xml_str = ET.tostring(map_elem, encoding='unicode')
|
|
dom = minidom.parseString(xml_str)
|
|
pretty_xml = dom.toprettyxml(indent=' ', encoding='UTF-8')
|
|
|
|
with open(OUTPUT_MAP, 'wb') as f:
|
|
f.write(pretty_xml)
|
|
|
|
print(f"\n{'='*60}")
|
|
print(f"✨ TILED MAP CREATED!")
|
|
print(f"{'='*60}")
|
|
print(f"📁 Location: {OUTPUT_MAP}")
|
|
print(f"📏 Size: {MAP_WIDTH}x{MAP_HEIGHT} tiles")
|
|
print(f"🎮 Objects placed:")
|
|
print(f" - 8 dirt tiles (center)")
|
|
print(f" - {len(tree_positions)} trees (random)")
|
|
print(f" - 1 Kai character")
|
|
print(f"\n🚀 Open in Tiled Map Editor to continue editing!")
|
|
|
|
if __name__ == "__main__":
|
|
create_tiled_map()
|