Roguelike dungeon room instantiation

Godot Version

Godot 4.3

Question

Hey friends! i was following a zenva course on youtube on how to do roguelike dungeon generation, and nearing the end of the video he was showing how to instantiate the rooms, but im getting an error.

The error reads: “Invalid access of index ‘7’ on a base object of: ‘Array’”

how can i solve this and make the code work as intended?

Heres the code, and yes it is EXACT to the tutorial.

var map_width : int = 7
var map_height : int = 7

func instantiate_rooms() -> void:
	if rooms_instantiated:
		return
	rooms_instantiated = true
	
	for x in range(map_width):
		for y in range(map_height):
			if map[x][y] == false:
				continue
			
			var room = room_scene.instantiate()
			room.position = Vector2(x, y) * 816
			
			if y > 0 and map[x][y - 1] == true:
				room.north()
			
			if y < map_height and map[x][y + 1] == true:
				room.south()
			
			if x > 0 and map[x - 1][y] == true:
				room.west()
			
			if x < map_width and map[x + 1][y] == true:
				room.east()
			
			if(first_room_pos != Vector2(x, y)):
				room.Generation = self
			
			$"..".call_deferred("add_child", room)
			room_nodes.append(room)
	
	get_tree().create_timer(1)
	calculate_key_and_exit()

In an array, the numbers start at slot 0, which would mean that access to array[7] will lead to an error if the array.size() is just 7.
I would set a breakpoint inside your for loop and then go through each line until the error appears. This is where you’ll need to see if map[?][?] is not somehow out of bound.

the error occurs on the second if statement, and to be honest i have no idea what im looking at in the output console. im gonna post the entire script, to see if someone else can see what i cant.

extends Node


@onready var room_scene : PackedScene = load("res://Scenes/Nodes/room.tscn")


var map_width : int = 7
var map_height : int = 7
var rooms_to_generate : int = 12
var room_count : int = 0
var rooms_instantiated : int
var first_room_pos : Vector2

var map : Array
var room_nodes : Array

# Spawn Chance
@export var enemy_spawn_chance : float
@export var coin_spawn_chance : float
@export var heart_spawn_chance : float

@export var max_enemies_per_room : int
@export var max_hearts_per_room : int
@export var max_coins_per_room : int

func _ready() -> void:
	for i in range(map_width):
		map.append([])
		for j in range(map_height):
			map[i].append(false)
	seed(3141592)
	generate()

func generate() -> void:
	check_room(3, 3, 0, Vector2.ZERO, true)
	instantiate_rooms()
	$"../Player".global_position = (first_room_pos * 816) + Vector2(262, 262)

func check_room(x : int, y : int, remaining : int, general_direction : Vector2, first_room : bool = false) -> void:
	if room_count >= rooms_to_generate:
		return
	
	if x < 0 or x > map_width - 1 or y < 0 or y> map_height - 1:
		return
	
	if first_room == false and remaining <= 0:
		return
	
	if map[x][y] == true:
		return
	
	if first_room:
		first_room_pos = Vector2(x, y)
	
	room_count += 1
	map[x][y] = true

	var north : bool = randf() > (0.2 if general_direction == Vector2.UP else 0.8)
	var south : bool = randf() > (0.2 if general_direction == Vector2.DOWN else 0.8)
	var east : bool = randf() > (0.2 if general_direction == Vector2.RIGHT else 0.8)
	var west : bool = randf() > (0.2 if general_direction == Vector2.LEFT else 0.8)

	var max_remaining : int = rooms_to_generate / 4

	if north or first_room:
		check_room(x, y + 1, max_remaining if first_room else remaining - 1, Vector2.UP if first_room else general_direction)
	if south or first_room:
		check_room(x, y - 1, max_remaining if first_room else remaining - 1, Vector2.DOWN if first_room else general_direction)
	if east or first_room:
		check_room(x + 1, y, max_remaining if first_room else remaining - 1, Vector2.LEFT if first_room else general_direction)
	if west or first_room:
		check_room(x - 1, y, max_remaining if first_room else remaining - 1, Vector2.RIGHT if first_room else general_direction)

func instantiate_rooms() -> void:
	if rooms_instantiated:
		return
	rooms_instantiated = true
	
	for x in range(map_width):
		for y in range(map_height):
			if map[x][y] == false:
				continue
			
			var room = room_scene.instantiate()
			room.position = Vector2(x, y) * 816
			
			if y > 0 and map[x][y - 1] == true:
				room.north()
			print(map[x][y])
			if y < map_height and map[x][y + 1] == true:
				room.south()
			
			if x > 0 and map[x - 1][y] == true:
				room.west()
			
			if x < map_width and map[x + 1][y] == true:
				room.east()
			
			if(first_room_pos != Vector2(x, y)):
				room.Generation = self
			
			$"..".call_deferred("add_child", room)
			room_nodes.append(room)
	
	get_tree().create_timer(1)
	calculate_key_and_exit()

func calculate_key_and_exit() -> void:
	pass

please help me out, what statement do you refer to when you say

the error occurs on the second if statement

right now I will just assume it’s the second if-statement inside of your instantiate_rooms() method.
That would be:

if map[x][y] == false:
    continue

I can already see the error inside because this will lead to an error if either x or y is higher than the array size. I am not sure how large your map array is because you are appending a lot of things into it.
For now, I would print out your map at that point and see how it looks.
At your breakpoint you are also able to see your current x and y values and also what map[y] is.

sorry for the miscommunication, im a bit sleepy. The error is occuring at

if y < map_height and map[x][y + 1] == true:
				room.south()

again, sorry for the mixup, and thanks for being patient

heya, i believe you should check the map[x][y + 1] portion to see if y can be higher than the array size of map[x]

okay ive recognized the issue, from the information youve been telling and another guy on reddit, i had to change the if statement

from:
if y < map_height and map[y + 1] == true:
to:
if y < map_height - 1 and map[y + 1] == true:

thx so much for help

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.