extends Node class_name LevelManager signal world_generated(maze: Maze) ## One map to rule them all var map := [] ## The maze the map is generated from var maze: Maze = null ## Stores the levels that the player has completed--killed all enemys-- ## so that we can spawn the level without enemys when the palyer goes back var completed_levels: Array[Vector2i] = [] ## Maze size @export var size := Vector2i(10, 10) ## The current level var current_level: TileMap @export var start: PackedScene @export var player: Player @onready var main := get_parent() as Node2D var lvl_position := Vector2i(-1, -1) ## Timer used for debouncing multiple door enters. (some kind of physics bug there is probably a tracker for but i havent found it) var t: SceneTreeTimer ## type: PackedScene[14][∞] var levels := [] func _init() -> void: Globals.levelmanager = self func _ready() -> void: populate_levels() gen_map() Events.change_level.connect(go) if OS.is_debug_build(): # show sorted levels for i in len(levels): print(i, ":", " [") for l in levels[i]: print(l.resource_path.indent("\t")) print("],") # show the map var string := "" for row in map: for item in row: if "Start" in item.resource_path: string += "na " else: string += "%02d " % item.get_state().get_node_property_value(0, 1) string += "\n" print(string) # show the maze (for visual discrepancy parsing) string = "" for row in maze.maze: for item in row: string += "%02d " % item string += "\n" print(string) lvl_position = size / 2 current_level = start.instantiate() current_level.enabled_walls = maze.get_cellv(lvl_position) main.call_deferred(&"add_child", (current_level)) ## Goes to the next room in [param to] direction. func go(to: Vector2i) -> void: completed_levels.append(lvl_position) if t and t.time_left > 0: print("skipping door enter") return t = get_tree().create_timer(0.1) lvl_position += to current_level.queue_free() current_level = map[lvl_position.y][lvl_position.x].instantiate() as TileMap var v := Vector2i(128, 128) # center player.position = Vector2(v - (v * to)).move_toward(v, 24) player.velocity = Vector2.ZERO main.call_deferred(&"add_child", current_level) if lvl_position in completed_levels: current_level.completed = true prints("welcome back to", current_level.name) else: prints("welcome to", current_level.name) # apparently lambdas cant do it func __inner_populate_loop(path := "res://levels/rand"): var dir := DirAccess.open(path) dir.list_dir_begin() var file_name := dir.get_next() while not file_name.is_empty(): if dir.current_is_dir(): __inner_populate_loop(path.path_join(file_name)) else: file_name = file_name.trim_suffix('.remap') # <---- NEW var level: PackedScene = load(path.path_join(file_name)) as PackedScene # Split levels into wall groups groups. levels[level.get_state().get_node_property_value(0, 1)].append(level) file_name = dir.get_next() ## Populates the levels array func populate_levels() -> void: levels.clear() levels = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]] __inner_populate_loop() ## Generates the maze. func gen_map() -> void: maze = Maze.new(size) maze.image.save_png("res://maze.png") lvl_position = size / 2 map.clear() for row in maze.maze: var map_row: Array[PackedScene] = [] for i in row: map_row.append(levels[i][randi() % len(levels[i])]) map.append(map_row) map[lvl_position.x][lvl_position.y] = start world_generated.emit(maze)