a game about throwing hammers made for the github game off
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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)