Now About Social Code
summaryrefslogtreecommitdiff
path: root/scripts/level_generator.gd
blob: 94a87ddc42344f4367d4853f29b305df22900086 (plain)
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
extends Node3D

@export var width: int = 10
@export var height: int = 10

var room = preload("res://prefabs/round_room.tscn")
var door = preload("res://prefabs/door.tscn")

var bounds: Vector3 = Vector3.ZERO
var astar: AStar3D

signal astar_created

func get_grid_index(pos: Vector2i) -> int:
	return pos.y*height + pos.x
	
func set_grid_index(grid: Array[int], pos: Vector2i):
	# If the point lies outside the grid we return
	if pos.x < 0 or pos.x >= width or pos.y < 0 or pos.y >= height:
		return
		
	var index = get_grid_index(pos)
	
	# If we already set this point we exit
	if grid[index] != 0:
		return
		
	grid[index] = 1
	var new_room: Node3D = room.instantiate()
	var mesh = new_room.find_child("MeshInstance3D")
	# TODO can we just load and cache the bounds?
	bounds = mesh.get_aabb().size
	var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2)
	new_room.position = (offset_pos * bounds)
	#print("Placing at ", pos)
	add_child(new_room)
	
	var next = [pos + Vector2i.UP,
				pos + Vector2i.LEFT,
				pos + Vector2i.DOWN,
				pos + Vector2i.RIGHT]
				 
	for n in next:
		var chance = randi_range(0, 1)
		if chance == 0:
			set_grid_index(grid, n)
			
func place_door(grid: Array[int], pos: Vector2i):
	var index = get_grid_index(pos)
	if grid[index] == 0:
		return
	
	var next = [pos + Vector2i.UP,
				pos + Vector2i.LEFT,
				pos + Vector2i.DOWN,
				pos + Vector2i.RIGHT]
			
	var angle = -90
	for n in next:
		angle += 90
		var next_index = get_grid_index(n)
		if n.x < 0 or n.x >= width or n.y < 0 or n.y >= height or grid[next_index] == 0:
			var new_door: Node3D = door.instantiate()
			var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2)
			new_door.position = (offset_pos * bounds)
			new_door.rotate_y(deg_to_rad(angle))
			add_child(new_door)

func place_doors(grid: Array[int]):
	for y in range(0, height):
		for x in range(0, width):
			place_door(grid, Vector2i(x, y))
			
func compute_astar(grid: Array[int]):
	for y in range(0, height):
		for x in range(0, width):
			var pos = Vector2i(x, y)
			var index = get_grid_index(pos)
			if grid[index] == 0:
				continue
			var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2)
			astar.add_point(index, offset_pos * bounds)

	for y in range(0, height):
		for x in range(0, width):
			var pos = Vector2i(x, y)
			var index = get_grid_index(pos)
			if grid[index] == 0:
				continue
				
			var next = [pos + Vector2i.UP,
						pos + Vector2i.LEFT,
						pos + Vector2i.DOWN,
						pos + Vector2i.RIGHT]
			for n in next:
				var next_index = get_grid_index(n)
				if n.x < 0 or n.x >= width or n.y < 0 or n.y >= height or grid[next_index] == 0:
					continue
					
				astar.connect_points(index, next_index)

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	astar = AStar3D.new()
	var grid: Array[int] = [0]
	grid.resize(width*height)
	grid.fill(0)
	
	var middle_x: int = width / 2
	var middle_y: int = height / 2
	
	var pos = Vector2i(middle_x, middle_y)
	set_grid_index(grid, pos)
	
	place_doors(grid)
	compute_astar(grid)
	
	astar_created.emit(astar)