Random dungeons with premade rooms

Godot Version

v4.6.1

Question

I’m having an issue with a script. I’m trying to make a roguelike, but with premade rooms: there is the starting room, some rooms with enemies, the final room etc. I’m testing with one room by far, but the problem is that all rooms spawns in a chaotic way. I forgot to mention that I’m watching some tutorial videos on YouTube, but maybe I’m doing something wrong. Here is the script for the room

extends Area2D

@onready var tilemap = $TileMapLayer
@onready var tilewall = $TileMapLayer2

var directions ={
“right”: Vector2i(1,0),
“bottom”: Vector2i(0,1),
“left”: Vector2i(-1,0),
“top”: Vector2i(0,-1),
}

var floorTiles ={
“default”: Vector2i(0,2),
}

var wallTiles ={
“ceiling”: Vector2i(0,0),
“wall”: Vector2i(0,1),
}

func connect_with(room):
var openDirections = directions.values()
var selectedDirection = openDirections.pick_random()
var ownConnectionPointDict = get_connection_point(-1 * selectedDirection)
var roomConnectionPointDict = room.get_connection_point(selectedDirection)
var oldPosition = global_position
global_position -= Vector2(ownConnectionPointDict[“globalPosition”] - roomConnectionPointDict[“globalPosition”])
await get_tree().create_timer(0.05)
if not get_overlapping_areas().is_empty():
return false
create_door(ownConnectionPointDict[“mapPoint”], -1 * selectedDirection)
room.create_door(roomConnectionPointDict[“mapPoint”], selectedDirection)
return true

func get_connection_point(direction) → Dictionary:
var rect = tilemap.get_used_rect()
var allCells = tilemap.get_used_cells()
if direction == directions[“right”]:
var x = rect.position.x + rect.size.x -1
allCells = allCells.filter(func(element): return element.x == x)
direction *= 2
elif direction == directions[“left”]:
var x = rect.position.x
allCells = allCells.filter(func(element): return element.x == x)
elif direction == directions[“bottom”]:
var y = rect.position.y + rect.size.y -1
elif direction == directions[“top”]:
var y = rect.position.y
allCells = allCells.filter(func(element): return element.y == y)
direction *= 5
var selectedPoint: Vector2i = allCells.pick_random()
return{
“mapPoint”: selectedPoint,
“globalPosition”: tilemap.map_to_local(selectedPoint + direction) + global_position
}

func create_door(doorPoint, direction):
if direction == directions[“right”]:
_create_right_door(doorPoint, direction)
elif direction == directions[“left”]:
_create_left_door(doorPoint, direction)
elif direction == directions[“bottom”]:
_create_bottom_door(doorPoint, direction)
elif direction == directions[“top”]:
_create_top_door(doorPoint, direction)
tilewall.set_cell(doorPoint + direction, 0, Vector2(-1,-1))
tilemap.set_cell(doorPoint + direction, 0, floorTiles[“default”])

func _create_right_door(doorPoint, direction):
if _has_wall(doorPoint + direction + directions[“top”] *2):
tilewall.set_cell(doorPoint + direction + directions[“top”], 0, wallTiles[“ceiling”])
if _has_wall(doorPoint + direction + directions[“bottom”] *2):
tilewall.set_cell(doorPoint + direction + directions[“bottom”], 0, wallTiles[“wall”])
else:
tilewall.set_cell(doorPoint + direction + directions[“bottom”], 0, wallTiles[“ceiling”])

func _create_left_door(doorPoint, direction):
if _has_wall(doorPoint + direction + directions[“top”] *2):
tilewall.set_cell(doorPoint + direction + directions[“top”], 0, wallTiles[“ceiling”])
if _has_wall(doorPoint + direction + directions[“bottom”] 2):
tilewall.set_cell(doorPoint + direction + directions[“bottom”], 0, wallTiles[“wall”])
else:
tilewall.set_cell(doorPoint + direction + directions[“bottom”], 0, wallTiles[“ceiling”])
func _create_bottom_door(doorPoint, direction):
if _has_wall(doorPoint + direction + directions[“left”] 2):
tilewall.set_cell(doorPoint + direction + directions[“left”], 0, wallTiles[“ceiling”])
else:
tilewall.set_cell(doorPoint + direction + directions[“left”], 0, wallTiles[“ceiling”])
if _has_wall(doorPoint + direction + directions[“right”] 2):
tilewall.set_cell(doorPoint + direction + directions[“right”], 0, wallTiles[“ceiling”])
else:
tilewall.set_cell(doorPoint + direction + directions[“right”], 0, wallTiles[“ceiling”])
func _create_top_door(doorPoint, direction):
tilewall.set_cell(doorPoint + direction
2, 0, Vector2(-1,-1))
tilewall.set_cell(doorPoint + direction3, 0, Vector2(-1,-1))
tilewall.set_cell(doorPoint + direction4, 0, Vector2(-1,-1))
tilemap.set_cell(doorPoint + direction * 2, 0, floorTiles[“default”])
tilemap.set_cell(doorPoint + direction * 3, 0, floorTiles[“default”])
tilemap.set_cell(doorPoint + direction * 4, 0, floorTiles[“default”])
if _has_wall(doorPoint + direction * 4 + directions[“left”] *2):
tilewall.set_cell(doorPoint + direction * 4 + directions[“left”], 0, wallTiles[“ceiling”])
else:
tilewall.set_cell(doorPoint + direction * 4 + directions[“left”], 0, wallTiles[“wall”])
if _has_wall(doorPoint + direction * 4 + directions[“right”] *2):
tilewall.set_cell(doorPoint + direction * 4 + directions[“right”], 0, wallTiles[“ceiling”])
else:
tilewall.set_cell(doorPoint + direction * 4 + directions[“right”], 0, wallTiles[“wall”])

func _has_wall(lookPosition):
return tilewall.get_cell_source_id(lookPosition) > -1

This is the script for the dungeon generation

extends Node2D

@export var maxRoomCount = 10
@onready var rooms: Node2D = $rooms
const ROOM1 = preload(“res://Scenes/Rooms/room_1.tscn”)

func _ready() → void:
_create_dungeon()

func _create_dungeon():
var roomCount := randi_range(4, maxRoomCount)
for room in roomCount:
await _create_room()

func _create_room():
var existingRoom = rooms.get_children()
var newRoom = ROOM1.instantiate()
rooms.add_child(newRoom)
newRoom.owner = get_tree().edited_scene_root
var isFirstRoom = existingRoom.is_empty()
if isFirstRoom: return
var possibleRooms =
for room in existingRoom:
if room == newRoom: continue
possibleRooms.append(room)
var selectedRoom = possibleRooms.pick_random()
var success = await newRoom.connect_with(selectedRoom)
var tries = 10
while not success and tries > 0:
selectedRoom = possibleRooms.pick_random()
success = await newRoom.connect_with(selectedRoom)
tries -= 1
if not success:
newRoom.queue_free()

I know I’m asking to much, but can you help me with generate multiple premade rooms?

Please repost with your code formatted as gdscript.

Can’t speak for anyone else, but if you want me to evaluate a large block of code I want it in a readable format - ideally looking the way it does in the editor.