File size: 4,813 Bytes
e2a4174
 
207e561
e2a4174
207e561
fb8aa70
 
207e561
fb8aa70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207e561
 
 
 
 
fb8aa70
 
 
 
 
 
 
 
207e561
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb8aa70
 
 
 
 
 
207e561
 
fb8aa70
207e561
 
 
 
 
 
 
e2a4174
fb8aa70
 
 
 
 
e2a4174
fb8aa70
e2a4174
 
fb8aa70
e2a4174
 
fb8aa70
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import streamlit as st
import os
from PIL import Image
import random
from io import BytesIO

# Function to arrange images dynamically
def arrange_images(image_files, canvas_size=(3000, 3000)):
    if not image_files:
        return None

    # Initialize layout
    positions = []  # Keeps track of image positions (x1, y1, x2, y2)
    canvas = Image.new("RGBA", canvas_size, "white")

    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

    # Save canvas to memory
    buffer = BytesIO()
    canvas.save(buffer, format="PNG")
    buffer.seek(0)
    return buffer

# 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

# Canvas size and scroll offsets
canvas_size = 3000
scroll_offset = {"x": 0, "y": 0}

# WASD Controls for scrolling
st.sidebar.title("Scroll Map")
scroll_buttons = st.sidebar.columns(3)
if scroll_buttons[0].button("⬅️"):
    scroll_offset["x"] -= 100
if scroll_buttons[1].button("⬆️"):
    scroll_offset["y"] -= 100
if scroll_buttons[2].button("➡️"):
    scroll_offset["x"] += 100
if st.sidebar.button("⬇️"):
    scroll_offset["y"] += 100

# 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"):
        scroll_offset = {"x": 0, "y": 0}  # Reset scroll offset
        layout_image = arrange_images(image_files, canvas_size=(canvas_size, canvas_size))
        if layout_image:
            st.image(
                layout_image,
                caption="Generated Dungeon Map Layout",
                use_container_width=True,
                output_format="PNG",
                clamp=True
            )
        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.")