-
Notifications
You must be signed in to change notification settings - Fork 0
/
world.gd
190 lines (150 loc) · 4.92 KB
/
world.gd
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
extends Node3D
enum Direction {EAST, SOUTH, WEST, NORTH}
@export var wall_scene: PackedScene
@export var width: int = 10
@export var height: int = 10
@export var loops: bool = false
@export var entry: Vector2i = Vector2i(0, 0)
@export var exit: Vector2i = Vector2i(9, 9)
@export var entrance_direction: Direction = Direction.WEST
@export var exit_direction: Direction = Direction.EAST
var linear_velocity = 0
var exit_cell
var entry_cell
var cells
var floor_size
var floor_width
var floor_height
var cell_width
var cell_height
class Cell:
var walls
var wallsTraversed
var visited = false
var row
var col
var exit_cell
var finish
var exit
var start
var entrance
func _init(_row, _col):
row = _row
col = _col
walls = [true, true, true, true]
wallsTraversed = [false, false, false, false]
#--------------------------------------------------------------------------------
func get_cell(row, col):
return cells[col + row * width]
#======================================================================
func get_unvisited_neighbours(cell):
var neighbours = []
var next
if (cell.col > 0):
next = get_cell(cell.row, cell.col - 1)
if not next.visited:
neighbours.append(next)
if (cell.col < width - 1):
next = get_cell(cell.row, cell.col + 1)
if not next.visited:
neighbours.append(next)
if (cell.row > 0):
next = get_cell(cell.row - 1, cell.col)
if not next.visited:
neighbours.append(next)
if (cell.row < height - 1):
next = get_cell(cell.row + 1, cell.col)
if not next.visited:
neighbours.append(next)
return neighbours
#======================================================================
func removeCommonWall(cellA, cellB):
if cellA.col == cellB.col:
if cellA.row < cellB.row:
cellA.walls[Direction.SOUTH] = false
cellB.walls[Direction.NORTH] = false
else:
cellA.walls[Direction.NORTH] = false
cellB.walls[Direction.SOUTH] = false
else:
if cellA.col < cellB.col:
cellA.walls[Direction.EAST] = false
cellB.walls[Direction.WEST] = false
else:
cellA.walls[Direction.WEST] = false
cellB.walls[Direction.EAST] = false
#======================================================================
func new_setup():
cells = []
var stack = []
for row in range(height):
for col in range(width):
cells.append(Cell.new(row, col))
var current_cell = get_cell(entry.x, entry.y)
#current_cell.walls[entrance_direction] = false
current_cell.visited = true
entry_cell = current_cell
stack.append(entry_cell)
exit_cell = get_cell(exit.x, exit.y)
exit_cell.walls[exit_direction] = false
while (stack.size() > 0):
var cell = stack.pop_front()
var neighbours = get_unvisited_neighbours(cell)
if (neighbours.size() > 0):
stack.append(cell)
var selectedNeighbour = neighbours[randi() % neighbours.size()]
selectedNeighbour.visited = true
stack.append(selectedNeighbour)
removeCommonWall(cell, selectedNeighbour)
# TODO: Loops
func add_walls():
new_setup()
floor_size = $Floor/CollisionShape3D.shape.size
floor_width = $Floor/CollisionShape3D.shape.size.x
floor_height = $Floor/CollisionShape3D.shape.size.z
cell_width = floor_width / width
cell_height = floor_height / height
for row in range(height):
for col in range(width):
var cell = get_cell(row, col)
var cell_corner_x = -floor_width / 2 + col * cell_width
var cell_corner_z = -floor_height / 2 + row * cell_height
if cell.walls[Direction.NORTH]:
var wall = wall_scene.instantiate()
wall.scale.x = cell_width / 2
#wall.rotation.y = PI / 2
wall.position.x = cell_corner_x + cell_width / 2
wall.position.z = cell_corner_z
add_child(wall)
if cell.walls[Direction.SOUTH]:
var wall = wall_scene.instantiate()
wall.scale.x = cell_width / 2
#wall.rotation.y = PI / 2
wall.position.x = cell_corner_x + cell_width / 2
wall.position.z = cell_corner_z + cell_height
add_child(wall)
if cell.walls[Direction.WEST]:
var wall = wall_scene.instantiate()
wall.scale.x = cell_height / 2
wall.rotation.y = PI / 2
wall.position.x = cell_corner_x
wall.position.z = cell_corner_z + cell_height / 2
add_child(wall)
if cell.walls[Direction.EAST]:
var wall = wall_scene.instantiate()
wall.scale.x = cell_height / 2
wall.rotation.y = PI / 2
wall.position.x = cell_corner_x + cell_width
wall.position.z = cell_corner_z + cell_height / 2
add_child(wall)
# Called when the node enters the scene tree for the first time.
func _ready():
add_walls()
$Player.position.x = -$Floor/CollisionShape3D.shape.size.x / 2 + entry_cell.col * cell_width + cell_width / 2
$Player.position.z = -$Floor/CollisionShape3D.shape.size.x / 2 + entry_cell.col * cell_width + cell_width / 2
$Player/PlayerCamera.current = true
func _process(delta):
if Input.is_action_just_pressed("ui_home"):
$CheatCameraPivot/CheatCamera.current = true
if Input.is_action_just_pressed("ui_cancel"):
$Player/PlayerCamera.current = true