import streamlit as st import os from PIL import Image, ImageDraw import random # Function to arrange images dynamically def arrange_images(image_files, output_path="dungeon_layout.png"): if not image_files: return None # Initialize layout positions = [] # Keeps track of image positions (x1, y1, x2, y2) canvas_size = (3000, 3000) # Large canvas for positioning canvas = Image.new("RGBA", canvas_size, "white") draw = ImageDraw.Draw(canvas) def get_center(pos): """Calculate center of a bounding box (x1, y1, x2, y2).""" return ((pos[0] + pos[2]) // 2, (pos[1] + pos[3]) // 2) def does_overlap(new_box, existing_boxes): """Check if a new bounding box overlaps any existing boxes.""" for box in existing_boxes: if ( new_box[0] < box[2] and new_box[2] > box[0] and new_box[1] < box[3] and new_box[3] > box[1] ): return True return False # Place the first image at the center of the canvas first_img_path = os.path.join(map_dir, image_files[0]) with Image.open(first_img_path) as img: width, height = img.size x1 = (canvas_size[0] - width) // 2 y1 = (canvas_size[1] - height) // 2 x2, y2 = x1 + width, y1 + height positions.append((x1, y1, x2, y2)) canvas.paste(img, (x1, y1)) # Place remaining images for img_file in image_files[1:]: placed = False img_path = os.path.join(map_dir, img_file) with Image.open(img_path) as img: width, height = img.size while not placed: # Choose a random existing image to connect to target_box = random.choice(positions) target_center = get_center(target_box) # Randomly choose a side of the target image side = random.choice(["top", "bottom", "left", "right"]) # Calculate the new image's position based on the chosen side if side == "top": x1 = target_center[0] - width // 2 y1 = target_box[1] - height elif side == "bottom": x1 = target_center[0] - width // 2 y1 = target_box[3] elif side == "left": x1 = target_box[0] - width y1 = target_center[1] - height // 2 elif side == "right": x1 = target_box[2] y1 = target_center[1] - height // 2 x2, y2 = x1 + width, y1 + height # Check for overlap if not does_overlap((x1, y1, x2, y2), positions): # Place the image positions.append((x1, y1, x2, y2)) canvas.paste(img, (x1, y1)) placed = True # Draw a connecting line new_center = get_center((x1, y1, x2, y2)) draw.line([target_center, new_center], fill="black", width=5) canvas.save(output_path) return output_path # Streamlit App st.title("Dynamic Dungeon Map Generator") st.write("Automatically generates dungeon maps by arranging PNG images dynamically.") # Directory for images map_dir = "." # Top-level directory # Scan the directory for .png files image_files = [f for f in os.listdir(map_dir) if f.endswith(".png")] if image_files: # Add "Create Map" button if st.button("🗺️ Create Map"): layout_image = arrange_images(image_files) if layout_image: st.image(layout_image, caption="Generated Dungeon Map Layout") else: st.write("Failed to generate a map. Please check the images in the directory.") else: st.write("No PNG files found in the top-level directory.") # Sidebar for file upload st.sidebar.title("Options") uploaded_file = st.sidebar.file_uploader("Upload a PNG file", type="png") if uploaded_file: # Save uploaded file to the directory with open(os.path.join(map_dir, uploaded_file.name), "wb") as f: f.write(uploaded_file.getbuffer()) st.sidebar.success("File uploaded successfully! Refresh the app to include it in the dungeon map.")