Godot Version
4.4
Question
` New to game development, and wanted to create a roguelike medevil dungeon crawler, the issue I am having now is the generation of dungeons.
From doing multipple hours of research and looking at godot redit posts, i have written this code that is semi-funtional, he only issue is that the dungeon only generates 1 room and i want a maximum of 25 to 30 rooms per dungeon. The scenes for each room are set up to have collisions and sprites that cover doorways into other rooms and are disabled when another room is spawned in that position. but it still wont work. Never expected game development to be this annoying but help would be rally appreciated.
CODE:
extends Node
const ROOM_SCENES = {
"square": preload("res://Scenes/Rooms/Beginging/room_square_begining.tscn"),
"horizontal_corridor": preload("res://Scenes/Rooms/Beginging/horizontal_corridor.tscn"),
"vertical_corridor": preload("res://Scenes/Rooms/Beginging/vertical_corridor.tscn")
}
var used_positions = []
var placed_rooms = []
func get_entry_points(room):
if not room.has_node("EntryPoints"):
push_warning("Room missing EntryPoints: " + str(room.name))
return []
return room.get_node("EntryPoints").get_children()
func position_overlaps(pos: Vector2) -> bool:
for used_pos in used_positions:
if used_pos.distance_to(pos) < 128: # Adjust to your room size + margin
return true
return false
func _ready():
var lobby_scene = preload("res://Scenes/Rooms/Beginging/begining_lobby.tscn")
var lobby = lobby_scene.instantiate()
var map_root = get_parent().get_node("MapRoot")
map_root.add_child(lobby)
var spawn = lobby.get_node("SpawnPoint")
get_parent().get_node("Player").global_position = spawn.global_position
var exit_door = lobby.get_node("ExitDoor")
exit_door.connect("dungeon_requested", Callable(self, "generate_dungeon"))
used_positions.append(lobby.global_position)
placed_rooms.append(lobby)
func disable_wall_at_door(room, door_marker: Marker2D):
var side = door_marker.name
var parts_to_disable = {
"Top": ["TopLeft", "TopRight"],
"Bottom": ["BottomLeft", "BottomRight"],
"Left": ["LeftTop", "LeftBottom"],
"Right": ["RightTop", "RightBottom"]
}
if not room.has_node("WallCollider"):
return
var wall_collider = room.get_node("WallCollider")
for part_name in parts_to_disable.get(side, []):
if wall_collider.has_node(part_name):
var part = wall_collider.get_node(part_name)
part.set_deferred("disabled", true)
func pick_room_type(exclude_type: String) -> String:
var types = ROOM_SCENES.keys()
var filtered = []
for t in types:
if t != exclude_type:
filtered.append(t)
return filtered.pick_random()
func generate_dungeon():
var map_root = get_parent().get_node("MapRoot")
var start_room = placed_rooms[0] # lobby
var open_doors = get_entry_points(start_room).duplicate()
var max_rooms = 10
var last_room_type = "lobby"
for i in range(max_rooms):
if open_doors.is_empty():
break
var existing_door = open_doors.pop_front()
var room_type = pick_room_type(last_room_type)
last_room_type = room_type
var new_room = ROOM_SCENES[room_type].instantiate()
var new_entry_points = get_entry_points(new_room)
if new_entry_points.is_empty():
push_warning("New room has no entry points: " + room_type)
continue
var new_door = new_entry_points.pick_random()
# Position new_room so new_door aligns with existing_door
var offset = existing_door.global_position - new_door.global_position
new_room.global_position = offset
# Check overlap - skip if overlapping
if position_overlaps(new_room.global_position):
continue
map_root.add_child(new_room)
used_positions.append(new_room.global_position)
placed_rooms.append(new_room)
# Remove the door we connected from new room's open doors
new_entry_points.erase(new_door)
# Add remaining doors to open_doors for further expansion
open_doors += new_entry_points
# Disable walls at connecting doors on both rooms
disable_wall_at_door(start_room, existing_door)
disable_wall_at_door(new_room, new_door)
# Update start_room to the new_room for next iteration
start_room = new_room