-
Notifications
You must be signed in to change notification settings - Fork 0
/
Level.gd
232 lines (189 loc) · 6.88 KB
/
Level.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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
extends Node
const Block = preload("res://Block.tscn")
const Enemy = preload("res://Enemy.tscn")
const AggresiveEnemy = preload("res://AggresiveEnemy.tscn")
const Apple = preload("res://Apple.tscn")
const Raspberry = preload("res://Raspberry.tscn")
const Lemon = preload("res://Lemon.tscn")
const Life = preload("res://Life.tscn")
const Health = preload("res://Health.tscn")
onready var SCREEN_HEIGHT = get_viewport().get_visible_rect().size.y
onready var SCREEN_WIDTH = get_viewport().get_visible_rect().size.x
const FIRST_BLOCK_POSITION = Vector2(62.5, 12.5)
const BLOCK_SIZE = 25
const LEVELS = [[
"XXXXX XXXXXXXX XXXXX",
"","","","",
" XXXXXXX XXXXXXX ",
"", "", "",
" XXXXXXXXXXXXXXXXXXXXXX ",
"","","",
"XXXXXXXXX XXXXXXXXX",
"","",""
],
[
"XXXX XXXXXXXXXXXX XXXX",
"","","","",
" XXXXXXXXXXXXXXXXXXXX ",
"","","",
"XXXXXX XXXXXX",
" X X ",
" X X ",
" X X ",
" X X ",
"","",""
],
[
"XXXX XXXX XXXX XXXX",
"","","","",
" XXXXXXXX XXXXXXXX ",
"","","",
"XXXX XXXXXXXX XXXX",
"","","",
" XXXXXX XXXXXX ",
"","",""
]]
const ENEMY_DIRECTIONS = [-1, 1]
signal level_cleared
signal enemy_spawned(enemy)
signal enemy_fired(position,direction)
var level_no = 0 setget set_level_no
var enemies = []
var active_enemies = []
var collectible_spawn_points = []
var next_enemy_timer
var level_cleared_timer = 0
var collectible_spawn_timer
func _ready():
randomize()
start()
func set_level_no(new_level):
level_no = new_level
SoundEffectPlayer.play("level")
start()
func get_maximum_enemies_on_screen():
return min(int((level_no + 6) / 2), 8)
func get_maximum_enemies():
return level_no + 10
func get_aggresive_enemies_number():
return 1 + int(level_no / 1.5)
func get_normal_enemies_number():
return get_maximum_enemies() - get_aggresive_enemies_number()
func generate_enemies():
for enemy in active_enemies:
enemy.queue_free()
enemies = []
active_enemies = []
reset_enemy_spawn_timer()
for _i in range(0, get_normal_enemies_number()):
var enemy = Enemy.instance()
enemies.append(enemy)
for _i in range(0, get_aggresive_enemies_number()):
var enemy = AggresiveEnemy.instance()
enemies.append(enemy)
for enemy in enemies:
enemy.level = level_no
enemy.connect("tree_exited", self, "on_enemy_died", [enemy])
enemy.connect("fire", self, "on_enenmy_fired")
enemies.shuffle()
func on_enemy_died(enemy):
active_enemies.erase(enemy)
if active_enemies.size() == 0 && enemies.size() == 0:
level_cleared_timer = 4
func on_enenmy_fired(position, direction):
emit_signal("enemy_fired", position, direction)
func start():
for child in get_children():
if child.is_in_group("collectibles"):
child.queue_free()
$Background.set_frame(level_no%4)
generate_collectible_spawn_points()
generate_enemies()
draw_level()
if collectible_spawn_timer != null && collectible_spawn_timer.is_connected("timeout", self, "_on_spawn_timer_timeout"):
collectible_spawn_timer.disconnect("timeout", self, "_on_spawn_timer_timeout")
collectible_spawn_timer = get_tree().create_timer(2 + randf() * 5)
collectible_spawn_timer.connect("timeout", self, "_on_spawn_timer_timeout")
func generate_collectible_spawn_points():
collectible_spawn_points = []
var y = FIRST_BLOCK_POSITION.y
var level = LEVELS[level_no%3]
for line in level:
var x = FIRST_BLOCK_POSITION.x
if line.length() == 0:
line = " "
for c in line:
if c == " ":
collectible_spawn_points.append(Vector2(x, y))
x += BLOCK_SIZE
y += BLOCK_SIZE
func draw_level():
for child in get_children():
if child.is_in_group("level_blocks"):
child.queue_free()
var y = FIRST_BLOCK_POSITION.y
var level = LEVELS[level_no%3]
for line in level:
draw_line(line, y)
y += BLOCK_SIZE
draw_line(level[0], y)
func draw_line(line, y):
var x = FIRST_BLOCK_POSITION.x
if line.length() == 0:
return
for c in line:
if c != " ":
var block = Block.instance()
block.type = level_no % 4
block.position = Vector2(x, y)
block.add_to_group("level_blocks")
add_child(block)
x += BLOCK_SIZE
func reset_enemy_spawn_timer():
next_enemy_timer = 2 + randf() * 2
func get_spawn_point():
var top_row = LEVELS[level_no%3][0]
var number_of_cols = top_row.length()
var r = randi() % number_of_cols;
for i in range(number_of_cols):
var grid_x = (r+i) % number_of_cols
if top_row[grid_x] == " ":
return BLOCK_SIZE * grid_x + FIRST_BLOCK_POSITION.x
return SCREEN_WIDTH / 2
func spawn_enemy():
if active_enemies.size() >= get_maximum_enemies_on_screen() || enemies.size() == 0:
return
var enemy = enemies.pop_front()
enemy.position = Vector2(get_spawn_point(), 0)
enemy.direction = ENEMY_DIRECTIONS[randi() % ENEMY_DIRECTIONS.size()]
active_enemies.append(enemy)
add_child(enemy)
emit_signal("enemy_spawned", enemy)
reset_enemy_spawn_timer()
func spawn_collectible(position, bonus):
var available = []
if not bonus:
available = [Apple, Raspberry, Lemon]
else:
print("BONUS!")
for _i in 10:
available += [Apple, Raspberry, Lemon]
for _i in 9:
available += [Health]
available += [Life]
var type = available[randi() % available.size()]
var instance = type.instance()
instance.position = position
add_child(instance)
func _on_spawn_timer_timeout():
spawn_collectible(collectible_spawn_points[randi() % collectible_spawn_points.size()], false)
collectible_spawn_timer = get_tree().create_timer(2 + randf() * 5)
collectible_spawn_timer.connect("timeout", self, "_on_spawn_timer_timeout")
func _process(delta):
next_enemy_timer -= delta
if next_enemy_timer <= 0:
spawn_enemy()
if level_cleared_timer > 0:
level_cleared_timer -= delta
if level_cleared_timer <= 0 && enemies.size()==0 && active_enemies.size()==0:
emit_signal("level_cleared")