Skip to content
Search

Dungeon Generation

lastmod 2026-01-19created 2018-07-1715 edits

About techniques for automatically generating dungeons

Categories

Libraries

Korean: 테라리아 style

See Terraria#pygame-ce clone coding for details.

Survey of 2D top-down dungeon generation algorithms

WARNING

Generated by Deep research

In game development, dungeon generation algorithms are a kind of procedural content generation (PCG) that automatically generates a new top-down dungeon map every time.

Random Room Placement

Overview: The simplest dungeon generation technique, which randomly places several rectangular rooms across the whole map and connects them. First, a set number of rectangular rooms are placed at random positions on the map without overlapping. When placing each room, it is discarded if it overlaps another room already placed, and kept if it does not​. Then corridors are made to connect all the rooms. Corridors are usually created by digging straight or L-shaped paths between the center points of the rooms. This yields a single dungeon in which the rooms are linked to each other by passages.

Pros: Very simple and intuitive to implement. You can easily change the density of the dungeon by adjusting the size and number of rooms. Depending on how the corridors are connected, you can get maps of various shapes.

Cons: Because rooms are placed randomly, it is hard to get a desired structure (e.g. rooms connected in a specific pattern). Corridors between rooms tend to end up as simple straight passages, so the terrain can be simple. Also, without enough attempts, room placement may fail and the dungeon may come out small.

Suitability for top-down games: ✅ Suitable. It is the basic method used by most roguelike games, and provides a clear room-and-passage structure in 2D top-down, which suits exploration gameplay.

The random room placement algorithm has been used in actual games such as Rogue and Angband, and generates dungeons with the simple procedure of "place several rooms at random positions and connect them with random corridors"​. Below is a brief Python implementation of this algorithm. It works by placing rooms without overlap and connecting each to the previous rooms in turn with L-shaped passages.

import random

def generate_random_rooms(map_width, map_height, max_rooms=15, room_min_size=5, room_max_size=10):
    dungeon = [[1 for _ in range(map_width)] for _ in range(map_height)]  # 1=벽, 0=바닥
    rooms = []
    for _ in range(max_rooms):
        # 무작위 크기의 방 생성
        w = random.randint(room_min_size, room_max_size)
        h = random.randint(room_min_size, room_max_size)
        x = random.randint(1, map_width - w - 2)
        y = random.randint(1, map_height - h - 2)
        # 다른 방과 겹치는지 검사
        if any(x < rx+rw and x+w > rx and y < ry+rh and y+h > ry 
               for (rx, ry, rw, rh) in rooms):
            continue  # 겹치면 이 방은 버림
        # 방을 맵에 새기기 (배열에 0으로 채우기)
        for iy in range(y, y+h):
            for ix in range(x, x+w):
                dungeon[iy][ix] = 0
        rooms.append((x, y, w, h))
    # 모든 방들을 복도로 연결 (여기선 순차적으로 이전 방과 연결)
    for i in range(1, len(rooms)):
        x1, y1 = rooms[i-1][0] + rooms[i-1][2]//2, rooms[i-1][1] + rooms[i-1][3]//2  # 이전 방 중심
        x2, y2 = rooms[i][0] + rooms[i][2]//2, rooms[i][1] + rooms[i][3]//2          # 현재 방 중심
        # 무작위로 가로->세로 또는 세로->가로 경로로 연결
        if random.random() < 0.5:
            # 가로 먼저
            for x in range(min(x1, x2), max(x1, x2)+1):
                dungeon[y1][x] = 0
            for y in range(min(y1, y2), max(y1, y2)+1):
                dungeon[y][x2] = 0
        else:
            # 세로 먼저
            for y in range(min(y1, y2), max(y1, y2)+1):
                dungeon[y][x1] = 0
            for x in range(min(x1, x2), max(x1, x2)+1):
                dungeon[y2][x] = 0
    return dungeon

Binary Space Partitioning (BSP)

Overview: The BSP algorithm places rooms by recursively partitioning the entire dungeon space in the form of a binary tree​. First the whole map is split in two, and each part is again split in two in a random direction, repeated recursively. Splitting continues while a region is sufficiently larger than the minimum size, dividing a large map into small zones in a tree structure. Then one room is placed in each final zone (a room is created at a random position/size within the zone boundaries). Finally, rooms in adjacent zones are connected with corridors following the partition tree​. For example, a corridor is made between the rooms of two child nodes with the same parent in the BSP tree, and this is repeated going up the tree so that the whole dungeon is connected into one. A dungeon generated this way has a grid-like partitioned structure.

Pros: With BSP, rooms never overlap in the first place, and space is used efficiently​. The tree structure also makes it relatively easy to guarantee a path connecting all rooms. The resulting dungeon has rooms spread out in a balanced way, making control of map composition (room size, density, etc.) easy​.

Cons: Depending on the splitting method, the dungeon shape can feel somewhat regular. Many corridors come out stair-shaped (L-shaped), which can give a linear, geometric feel. Implementation also requires understanding recursive partitioning and tree connection, so it is slightly harder.

Suitability for top-down games: ✅ Suitable. Rooms are spread irregularly yet all connected, so it is useful for reliably generating the structure of large maps. It is proven enough to be offered as a default algorithm in many roguelike game engines and toolkits.

BSP-based dungeon generation places rooms by bisecting the space, producing dungeons with rooms suitably spaced apart and connected by passages​. The code below is a brief implementation of the BSP algorithm. It recursively partitions the map, puts a room in each final zone, and connects the rooms of adjacent zones with corridors following the partition tree structure.

def generate_bsp_dungeon(map_width, map_height, min_size=5, max_size=12, max_depth=4):
    dungeon = [[1 for _ in range(map_width)] for _ in range(map_height)]
    # BSP 분할을 위한 스택 (x, y, w, h, depth)
    stack = [(1, 1, map_width-2, map_height-2, 0)]  # 테두리 1칸은 벽으로 남김
    regions = []  # 최종 분할된 구역들
    while stack:
        x, y, w, h, depth = stack.pop()
        if depth < max_depth and w > 2*min_size and h > 2*min_size and random.random() < 0.75:
            # 무작위 방향으로 분할 (가로/세로)
            if w > h:
                split = random.randint(min_size, w - min_size)  # 세로 분할 위치
                stack.append((x, y, split, h, depth+1))
                stack.append((x + split + 1, y, w - split - 1, h, depth+1))
            else:
                split = random.randint(min_size, h - min_size)  # 가로 분할 위치
                stack.append((x, y, w, split, depth+1))
                stack.append((x, y + split + 1, w, h - split - 1, depth+1))
        else:
            # 더 이상 분할하지 않고 구역을 확정
            regions.append((x, y, w, h))
    # 각 구역에 하나씩 방 배치
    room_centers = []
    for (x, y, w, h) in regions:
        rw = random.randint(min_size, min(w, max_size))
        rh = random.randint(min_size, min(h, max_size))
        rx = random.randint(x, x + w - rw)  # 구역 내 랜덤 위치
        ry = random.randint(y, y + h - rh)
        for iy in range(ry, ry+rh):
            for ix in range(rx, rx+rw):
                dungeon[iy][ix] = 0
        cx, cy = rx + rw//2, ry + rh//2  # 방 중심 좌표
        room_centers.append((cx, cy))
    # 방들을 연결 - 여기서는 MST(최소 신장 트리)로 연결 보장
    connected = [room_centers[0]]
    not_connected = room_centers[1:]
    while not_connected:
        # 가장 가까운 연결되지 않은 방 선택
        c = connected[-1]
        # 가까운 방 찾기
        nearest = min(not_connected, key=lambda t: (c[0]-t[0])**2 + (c[1]-t[1])**2)
        x1, y1 = c; x2, y2 = nearest
        # L자형 복도 생성
        if random.random() < 0.5:
            for x in range(min(x1, x2), max(x1, x2)+1):
                dungeon[y1][x] = 0
            for y in range(min(y1, y2), max(y1, y2)+1):
                dungeon[y][x2] = 0
        else:
            for y in range(min(y1, y2), max(y1, y2)+1):
                dungeon[y][x1] = 0
            for x in range(min(x1, x2), max(x1, x2)+1):
                dungeon[y2][x] = 0
        connected.append(nearest)
        not_connected.remove(nearest)
    return dungeon

Cellular Automata

Overview: Dungeon generation with cellular automata treats the map as a grid of cells, regards each cell as being in a wall or floor state, and builds terrain by repeatedly applying rules. First, the map's cells are randomly filled with walls (1) or floors (0). Then, for a set number of times, the number of walls among each cell's neighbors (the surrounding 8 cells) is counted and walls/floors are updated according to the rules. A typical rule is called the 4-5 rule: if there are 5 or more walls around, the cell becomes a wall​. After several generations (iterations), the initial random noise gradually converges into cave-like connected rooms and passages. Maps generated this way suit natural cave terrain or irregular dungeons.

Pros: You get naturally shaped dungeons. Because it automatically creates organic shapes such as hand-drawn-looking caves and winding passages, it avoids the uniformity of rectangular dungeons​. It is also fairly easy to implement, and you can experiment with various shapes by tuning parameters (initial wall probability, neighbor thresholds, etc.).

Cons: Without proper tuning, disconnected isolated spaces can appear​. For example, if several caves split off, the player cannot reach some areas. To fix this, post-processing is needed, such as using Flood Fill to keep only the largest connected region and fill the rest with walls​. It is also hard to precisely control the desired shape, so large maps need enough iterations and tuning.

Suitability for top-down games: ✅ Mostly suitable. Useful for making dungeons with a natural cave or outdoor terrain feel. However, for games like roguelikes where all areas must be connected, it is a good idea to add a connectivity correction step after generation.

Cellular automata-based algorithms start from a random initial map and repeatedly apply simple rules, producing a map that keeps changing to resemble its surroundings​. The implementation below places walls with an initial 45% probability, then applies the following rule for 4 iterations: if 5 or more of the surrounding 8 cells are walls, the current cell becomes a wall, otherwise a floor. Finally, as post-processing, it finds all small disconnected empty spaces and fills them so that only one large cave remains.

def generate_cellular_cave(map_width, map_height, fill_prob=0.45, iterations=4):
    # 초기 맵 랜덤 배치
    cave = [[1 if random.random() < fill_prob else 0 for _ in range(map_width)] 
            for _ in range(map_height)]
    # 지도 가장자리 영역을 모두 벽으로 고정 (외벽)
    for x in range(map_width):
        cave[0][x] = cave[map_height-1][x] = 1
    for y in range(map_height):
        cave[y][0] = cave[y][map_width-1] = 1
    # 정해진 횟수만큼 규칙 반복 적용
    for _ in range(iterations):
        new_cave = [row[:] for row in cave]  # 복사
        for y in range(1, map_height-1):
            for x in range(1, map_width-1):
                wall_count = 0
                # 주변 8방향 벽 개수 세기
                for ny in range(y-1, y+2):
                    for nx in range(x-1, x+2):
                        if nx == x and ny == y:
                            continue
                        if cave[ny][nx] == 1:
                            wall_count += 1
                # 규칙 적용
                if cave[y][x] == 1:
                    new_cave[y][x] = 1 if wall_count >= 4 else 0
                else:
                    new_cave[y][x] = 1 if wall_count >= 5 else 0
        cave = new_cave
    # 연결성 확보: 가장 큰 연결 영역 이외의 바닥은 모두 벽으로 메우기
    visited = [[False]*map_width for _ in range(map_height)]
    largest_region = []
    directions = [(1,0),(-1,0),(0,1),(0,-1)]
    for sy in range(1, map_height-1):
        for sx in range(1, map_width-1):
            if cave[sy][sx] == 0 and not visited[sy][sx]:
                region = []
                stack = [(sx, sy)]
                visited[sy][sx] = True
                while stack:
                    cx, cy = stack.pop()
                    region.append((cx, cy))
                    for dx, dy in directions:
                        nx, ny = cx+dx, cy+dy
                        if 0 <= nx < map_width and 0 <= ny < map_height:
                            if cave[ny][nx] == 0 and not visited[ny][nx]:
                                visited[ny][nx] = True
                                stack.append((nx, ny))
                if len(region) > len(largest_region):
                    largest_region = region
    # largest_region이 아닌 모든 바닥은 벽으로 변경
    floor_set = set(largest_region)
    for y in range(map_height):
        for x in range(map_width):
            if cave[y][x] == 0 and (x, y) not in floor_set:
                cave[y][x] = 1
    return cave

Drunkard’s Walk (random carving)

Overview: The Drunkard's Walk algorithm carves passages by walking randomly across the map, like a drunk person staggering around​. Initially the whole map is wall; starting from one point (e.g. the center), that position is dug out as floor and then it moves one cell in a random direction. If the cell it moved to was a wall, it becomes floor. Then it repeats moving in a random direction. Running this process enough times creates a dungeon shaped like cave passages that widen here and there along the path​. It looks like the trail of a miner digging a maze who wandered around randomly, giving a map that mixes narrow corridors with suddenly widened spaces. Usually a target floor ratio for the whole map (e.g. 40%) is set and it repeats until that many floor cells exist.

Pros: Simple to implement, yet the result differs greatly every time. You get maps mixing passages of irregular width with open spaces, producing unexpected, distinctive layouts​. Another advantage is that the random walk path is inherently continuous, so it generates a single connected dungeon without a separate connectivity check.

Cons: Because it walks completely randomly, it is hard to control specific structures, and the map shape depends too much on luck. If not enough space is dug, it can end up with very narrow passages or a bland shape. Also, if the path clusters at the map edges, only some areas may be dug while large areas stay empty (to mitigate this, the walker is sometimes relocated to the map center or another position).

Suitability for top-down games: ✅ Suitable. Especially useful when you want cave-style dungeons or maze-like passages. A dungeon with narrow paths and wide rooms connected irregularly increases the exploration element, but if you dislike overly unpredictable shapes, it is sometimes mixed with other algorithms.

A dungeon generated by Drunkard's Walk consists of a single continuous path, so it is always connected​. The implementation below starts at the map center and walks randomly in four directions, repeating until about 40% of all cells are dug out as floor. When the path clusters at the edges, it occasionally moves to a random existing floor point to balance things out.

def generate_drunkards_walk(map_width, map_height, floor_ratio=0.4):
    dungeon = [[1 for _ in range(map_width)] for _ in range(map_height)]
    total_cells = map_width * map_height
    target_floor_count = int(total_cells * floor_ratio)
    # 시작 위치 (중앙)
    x, y = map_width // 2, map_height // 2
    dungeon[y][x] = 0
    floor_count = 1
    directions = [(0,1),(0,-1),(1,0),(-1,0)]  # 하, 상, 우, 좌
    while floor_count < target_floor_count:
        dx, dy = random.choice(directions)
        nx, ny = x + dx, y + dy
        # 경계 밖으로 나가면 무시 (다른 방향으로 계속 시도)
        if not (0 < nx < map_width-1 and 0 < ny < map_height-1):
            # 가끔 워커를 맵 내 랜덤 바닥 위치로 순간이동시켜 분산
            if random.random() < 0.3:
                rx, ry = random.randrange(1, map_width-1), random.randrange(1, map_height-1)
                if dungeon[ry][rx] == 0:
                    x, y = rx, ry
            continue
        # 이동
        x, y = nx, ny
        if dungeon[y][x] == 1:  # 벽이면 판다
            dungeon[y][x] = 0
            floor_count += 1
    return dungeon

Maze-based generation (Maze-based, depth-first search, etc.)

Overview: A technique that applies maze generation algorithms to dungeons; the most representative is generating a perfect maze using recursive backtracking (depth-first search). In this algorithm, the whole map is first walled off, then starting from one cell it proceeds by breaking through adjacent walls DFS (Depth-First Search) style. Specifically, from the current position it randomly picks an unvisited neighbor cell, knocks down the wall and moves there, and when there is nowhere else to go it backtracks and explores another direction​. This produces a single loop-free network of passages, and such a maze has the property that every cell is connected to every other by a single path​. Maze-based dungeons usually produce maze-structured dungeons made of 1-cell-wide corridors connected in a grid.

Pros: Guaranteed connectivity – a map generated by a maze algorithm becomes a fully connected graph with exactly one path between any two points​. So the player can explore every area, and paths are easy to figure out. Implementation only needs DFS, so it is relatively simple and also fast​. Suitable when you want complex, puzzle-like terrain built mostly of narrow passages.

Cons: Because there are no loops, paths can be '''overly linear and monotonous, or have many dead ends. A finished maze is structurally complex but can feel spatially cramped, and lacks combat spaces or special rooms. To compensate, rooms are sometimes added to parts of the maze or some walls are knocked down to create loops.

Suitability for top-down games: ⚠️ Partially suitable. Maze-shaped dungeons offer puzzle elements and the fun of pathfinding, but creating combat or event spaces requires extra work. So it is often applied to parts of a dungeon (e.g. complex passage sections) rather than the whole dungeon, or mixed with other algorithms.

Maze generation with recursive backtracking is one of the easiest maze algorithms to understand, carving paths while visiting most cells once​. The implementation below creates 1-cell-wide corridors by carving passages at odd coordinates of the grid. (It starts at (1,1) and knocks down walls while jumping two cells at a time.) The resulting maze has no loops and all passages are connected.

def generate_maze(map_width, map_height):
    # 맵 크기를 홀수로 조정 (외곽을 벽으로 유지)
    if map_width % 2 == 0: map_width -= 1
    if map_height % 2 == 0: map_height -= 1
    maze = [[1 for _ in range(map_width)] for _ in range(map_height)]
    # DFS 스택 초기화
    stack = [(1, 1)]
    maze[1][1] = 0  # 시작점
    while stack:
        x, y = stack[-1]
        # 방문하지 않은 이웃 셀 (2칸 띄운 위치 기준)
        neighbors = []
        for dx, dy in [(2,0),(-2,0),(0,2),(0,-2)]:
            nx, ny = x + dx, y + dy
            if 1 <= nx < map_width-1 and 1 <= ny < map_height-1 and maze[ny][nx] == 1:
                neighbors.append((nx, ny))
        if neighbors:
            nx, ny = random.choice(neighbors)
            # 현재 위치와 선택 이웃 사이의 벽 허물기
            wall_x = x + (nx - x)//2
            wall_y = y + (ny - y)//2
            maze[wall_y][wall_x] = 0
            maze[ny][nx] = 0
            stack.append((nx, ny))  # 이동
        else:
            stack.pop()  # 백트래킹
    return maze

Rogue-like Generation

Overview: Roguelike-style dungeon generation follows the procedure of the classic game Rogue, placing multiple rooms and corridors in a more regular structure. For example, the original Rogue divided the map into a 3x3 grid and gave each zone a probability of having a room, placing up to 9 rooms. It then always connected adjacent rooms with corridors so that the whole map formed a single connected network. Modern roguelike generation is similar: it is based on the random room placement algorithm, but restricts room positions to a grid and always connects adjacent rooms with passages​. Each game also applies special rules (e.g. removing some rooms, or adding intersections midway to create loops) to make it more fun.

Pros: Easy to balance gameplay. Rooms are spread across regular zones and always connected, so there are no blocked areas that cannot be explored. You can also deliberately bend or cross corridors to create strategic terrain, and it is easy to adjust the ratio of rooms to passages. It basically has all the advantages of random room placement, with somewhat more structural consistency.

Cons: With less freedom, maps of similar shape can come out every time. Placing rooms on a grid can reveal patterns, and if too regular, the dungeon risks looking artificial. Also, without adding complex variation rules, it can end up as a simple sequence of rooms and corridors.

Suitability for top-down games: ✅ Suitable. The roguelike genre itself developed this method, so it fits top-down games such as turn-based roguelikes and dungeon crawlers well. Connectivity between rooms is high and it is easy to design without problems for game progression, so it is stable in terms of gameplay.

Roguelike dungeon generation can be seen as a kind of hybrid. The basis is similar to random room placement, but there are extra rules, such as restricting room positions to a grid and using a minimum spanning tree (MST) to connect all rooms efficiently. The code below is an example implementation that divides the map into 3x3 regions, places a room in each region, and connects the rooms with corridors based on an MST. Similar to the original Rogue, this guarantees that all rooms form a single graph even if they are not adjacent.

def generate_roguelike_dungeon(map_width, map_height, grid_rows=3, grid_cols=3):
    dungeon = [[1 for _ in range(map_width)] for _ in range(map_height)]
    region_w = (map_width - 2) // grid_cols
    region_h = (map_height - 2) // grid_rows
    room_centers = []
    # 각 그리드 셀마다 방을 놓을지 결정하고 생성
    for r in range(grid_rows):
        for c in range(grid_cols):
            rx1 = 1 + c * region_w
            ry1 = 1 + r * region_h
            rx2 = 1 + (c+1) * region_w if c < grid_cols-1 else map_width - 1
            ry2 = 1 + (r+1) * region_h if r < grid_rows-1 else map_height - 1
            # 80% 확률로 해당 구역에 방 생성
            if random.random() < 0.8:
                rw = random.randint(4, min(8, rx2 - rx1 - 1))
                rh = random.randint(4, min(8, ry2 - ry1 - 1))
                rx = random.randint(rx1, rx2 - rw - 1)
                ry = random.randint(ry1, ry2 - rh - 1)
                for y in range(ry, ry+rh):
                    for x in range(rx, rx+rw):
                        dungeon[y][x] = 0
                cx, cy = rx + rw//2, ry + rh//2
                room_centers.append((cx, cy))
            else:
                room_centers.append(None)
    # None 제거 (존재하는 방들의 중심 리스트)
    centers = [c for c in room_centers if c is not None]
    # 최소 신장 트리를 사용하여 모든 방 연결
    if centers:
        connected = [centers[0]]
        not_connected = centers[1:]
        while not_connected:
            c = connected[-1]
            nearest = min(not_connected, key=lambda t: (c[0]-t[0])**2 + (c[1]-t[1])**2)
            x1, y1 = c; x2, y2 = nearest
            if random.random() < 0.5:
                for x in range(min(x1, x2), max(x1, x2)+1):
                    dungeon[y1][x] = 0
                for y in range(min(y1, y2), max(y1, y2)+1):
                    dungeon[y][x2] = 0
            else:
                for y in range(min(y1, y2), max(y1, y2)+1):
                    dungeon[y][x1] = 0
                for x in range(min(x1, x2), max(x1, x2)+1):
                    dungeon[y2][x] = 0
            connected.append(nearest)
            not_connected.remove(nearest)
    return dungeon

Algorithm demo using Pygame

I implemented a demo that lets you visually check all the algorithms described above with pygame-ce. When run, a main menu appears in a single window, and the dungeon map generated with the algorithm the user selects is drawn as a 2D grid. You can also go back to the menu and try another algorithm. Each algorithm generates the map using the functions written above, with walls shown in a dark color and floors (passages and rooms) in a light color.

When you run the code below, you can quit the program with the ESC key or by closing the window, and select each algorithm by pressing number keys 1–6.

import pygame
import random

# 앞서 정의한 던전 생성 함수들이 이미 있다고 가정합니다.
# generate_random_rooms, generate_bsp_dungeon, generate_cellular_cave,
# generate_drunkards_walk, generate_maze, generate_roguelike_dungeon 함수를 사용.

# 색상 정의
COLOR_FLOOR = (200, 200, 200)  # 바닥 색 (밝은 회색)
COLOR_WALL = (50, 50, 50)      # 벽 색 (어두운 회색)
COLOR_TEXT = (240, 240, 240)   # 메뉴 텍스트 색 (거의 흰색)
COLOR_BG = (30, 30, 30)       # 배경 색 (짙은 회색)

# 화면 크기 및 셀 크기
MAP_WIDTH, MAP_HEIGHT = 51, 51    # 맵 타일 개수 (51x51 격자)
CELL_SIZE = 10                   # 한 타일을 그릴 때의 픽셀 크기
SCREEN_WIDTH = MAP_WIDTH * CELL_SIZE
SCREEN_HEIGHT = MAP_HEIGHT * CELL_SIZE

# 파이게임 초기화
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Dungeon Generation Demo")
font = pygame.font.SysFont(None, 24)

# 메뉴 표시 텍스트 렌더링 함수
def draw_menu():
    screen.fill(COLOR_BG)
    menu_lines = [
        "Select Dungeon Generation Algorithm:",
        "1 - Random Room Placement",
        "2 - Binary Space Partitioning (BSP)",
        "3 - Cellular Automata Cave",
        "4 - Drunkard's Walk Cave",
        "5 - Maze (Recursive Backtracking)",
        "6 - Rogue-like Generation",
        "ESC - Quit"
    ]
    # 화면 중앙에 메뉴 텍스트 표시
    start_y = SCREEN_HEIGHT // 2 - len(menu_lines)*15
    for i, line in enumerate(menu_lines):
        text_surf = font.render(line, True, COLOR_TEXT)
        text_rect = text_surf.get_rect(center=(SCREEN_WIDTH//2, start_y + i*30))
        screen.blit(text_surf, text_rect)
    pygame.display.flip()

# 던전 맵(grid)을 화면에 그리는 함수
def draw_dungeon(grid):
    for y in range(len(grid)):
        for x in range(len(grid[0])):
            color = COLOR_FLOOR if grid[y][x] == 0 else COLOR_WALL
            pygame.draw.rect(screen, color, (x*CELL_SIZE, y*CELL_SIZE, CELL_SIZE, CELL_SIZE))
    pygame.display.flip()

# 메인 루프
running = True
showing_menu = True
while running:
    if showing_menu:
        draw_menu()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if showing_menu:
                # 메뉴에서 키 입력 처리
                if event.key == pygame.K_ESCAPE:
                    running = False
                elif event.key == pygame.K_1:
                    dungeon_map = generate_random_rooms(MAP_WIDTH, MAP_HEIGHT)
                    showing_menu = False
                elif event.key == pygame.K_2:
                    dungeon_map = generate_bsp_dungeon(MAP_WIDTH, MAP_HEIGHT)
                    showing_menu = False
                elif event.key == pygame.K_3:
                    dungeon_map = generate_cellular_cave(MAP_WIDTH, MAP_HEIGHT)
                    showing_menu = False
                elif event.key == pygame.K_4:
                    dungeon_map = generate_drunkards_walk(MAP_WIDTH, MAP_HEIGHT)
                    showing_menu = False
                elif event.key == pygame.K_5:
                    dungeon_map = generate_maze(MAP_WIDTH, MAP_HEIGHT)
                    showing_menu = False
                elif event.key == pygame.K_6:
                    dungeon_map = generate_roguelike_dungeon(MAP_WIDTH, MAP_HEIGHT)
                    showing_menu = False
                if not showing_menu:
                    # 선택된 알고리즘의 던전 맵을 생성했으므로 그리기
                    draw_dungeon(dungeon_map)
            else:
                # 던전 표시 화면에서 키 누르면 메뉴로 돌아가기
                showing_menu = True

pygame.quit()

When you run this demo program, you can see dungeons of various styles generated according to each algorithm. For example, random room placement shows several rectangular rooms and the corridors connecting them, while cellular automata will show irregularly shaped cave terrain. This lets you compare the characteristics of the algorithms described above with your own eyes.

See also

Favorite site

Creating a random 2d game world map

Samples

Tutorials

References


  1. Creating_a_random_2d_game_world_map_-_Part_1.pdf ↩

  2. Creating_a_random_2d_game_world_map_-_Part_2_Adding_rivers_and_lakes.pdf ↩

  3. Creating_a_random_2d_game_world_map_-_Part_3_Cities_caves_and_snow.pdf ↩

author Zer0 sitemap