fuzzyworld

godot-shooter / asteroids / files / scenes / World.gd

Branch asteroids · default branch · all branches

World.gd

8.6 KB · history · blame

1extends Node2D
2
3const Enemy = preload("res://actors/Enemy.tscn")
4const Bomb = preload("res://weapons/Bomb.tscn")
5const Asteroid = preload("res://items/Asteroid.tscn")
6
7const Utils = preload("res://utils/Utils.gd")
8const Weapons = preload("res://weapons/Weapons.gd")
9const PowerUp = preload("res://items/PowerUp.tscn")
10const Settings = preload("res://utils/Settings.gd")
11onready var player: Player = $Player
12onready var update_timer = $UpdateTimer
13onready var navigation_polygon_instance: NavigationPolygonInstance = $NavigationPolygonInstance
14onready var environment_node = $Environment
15
16var generators = [
17 ConstantItemGenerator.new("create_enemy", self, "enemies", 5),
18 ConstantItemGenerator.new("create_health", self, "health", 20),
19 ConstantItemGenerator.new("create_weapon", self, "weapon", 10),
20 ConstantItemGenerator.new("create_bomb", self, "bombs", 10),
21 LevelItemGenerator.new(5, "create_gold", self, "gold", 5),
22 ConstantItemGenerator.new("create_asteroid", self, "asteroids", 10),
23]
24var completed_objectives = 0
25var max_objectives = 5
26var item_replacement_distance = 2000
27var is_dragging = false
28var is_game_over = false
29export var starting_zoom = 1.5
30
31func enemy_killed(_position: Vector2):
32 player.score += 5
33func health_consumed(_power_up):
34 player.heal(20)
35 player.score += 1
36func gold_consumed(_power_up):
37 completed_objectives += 1
38 var points = 5 * (completed_objectives+1)
39 player.score += points
40 player.show_message("+%d points" % points)
41 player.health = player.max_health
42func weapon_consumed(power_up):
43 var data = power_up.data
44 var weapon: Weapon = data
45 var is_same_weapon = player.weapon.name == weapon.name
46 if is_same_weapon && weapon.ammo != INF:
47 player.weapon.ammo += player.weapon.reload_size
48 else:
49 player.weapon = weapon
50func bomb_consumed(power_up):
51 var pos: Vector2 = power_up.global_position
52 var bomb = Bomb.instance()
53 environment_node.call_deferred("add_child",bomb)
54 bomb.position = pos
55
56func create_enemy() -> Enemy:
57 var enemy = Enemy.instance()
58 enemy.position = get_new_environment_position(1)
59 enemy.connect("enemy_killed", self, "enemy_killed")
60 return enemy
61func create_health() -> PowerUp:
62 var health = PowerUp.instance()
63 health.position = get_new_environment_position(randf() + .5)
64 health.connect("consumed", self, "health_consumed")
65 health.label = "+HP"
66 health.color = Color.green
67 return health
68func create_bomb() -> PowerUp:
69 var bomb = PowerUp.instance()
70 var pos = get_new_environment_position(randf() + .5)
71 bomb.position = pos
72 bomb.connect("consumed", self, "bomb_consumed")
73 bomb.label = "BOMB"
74 bomb.color = Color.purple
75 return bomb
76func create_gold(pos: Vector2 = get_new_environment_position(1 + randf())) -> PowerUp:
77 var gold = PowerUp.instance()
78 gold.position = pos
79 gold.connect("consumed", self, "gold_consumed")
80 gold.label = ""
81 gold.color = Color.gold
82 return gold
83func create_weapon() -> PowerUp:
84 var weapon: PowerUp = PowerUp.instance()
85 weapon.position = get_new_environment_position(randf() + .5)
86 var _err = weapon.connect("consumed", self, "weapon_consumed")
87 var r = randf()
88 if r < .45:
89 weapon.data = Weapons.create_rocket_gun()
90 weapon.label = "ROC"
91 weapon.color = Color.red
92 elif r < .9:
93 weapon.data = Weapons.create_smg_gun()
94 weapon.label = "SMG"
95 weapon.color = Color.orange
96 else:
97 weapon.data = Weapons.create_basic_gun()
98 weapon.label = "LZR"
99 weapon.color = Color.pink
100 return weapon
101func create_asteroid() -> Asteroid:
102 var asteroid: Asteroid = Asteroid.instance()
103 asteroid.position = get_new_environment_position(randf() * 2)
104 asteroid.spin_rate = randf() * 2 - 1
105 asteroid.scale *= (randf() * 2 + .5)
106 asteroid.velocity = Vector2.UP.rotated(randf() * PI * 2) * randf() * 100
107 return asteroid
108
109func get_new_item_pos(dist_ratio: float = 1.0) -> Vector2:
110 var pos_angle = randi() % 360
111 var unit_vector = Vector2.UP.rotated(pos_angle)
112 var size = get_viewport().get_visible_rect().size
113 var max_side = max(size.x, size.y)
114 var screen_radius = max_side + 10
115 var enemy_spawn_dist = screen_radius * dist_ratio
116 var pos = unit_vector * enemy_spawn_dist + $Player.global_position
117 return pos
118func get_new_environment_position(dist_ratio: float = 1.0) -> Vector2:
119 var potential_pos: Vector2
120 while true:
121 # find the positions of the closest Environment items
122 var items = environment_node.get_children()
123 potential_pos = get_new_item_pos(dist_ratio)
124 var closest_pos = 10000
125 for i in items:
126 var item: Node2D = i
127 var pos = item.global_position
128 var dist = potential_pos.distance_to(pos)
129 if dist < closest_pos:
130 closest_pos = dist
131 var is_too_close = closest_pos < 50
132 var found_one = !is_too_close
133 if found_one:
134 break
135 return potential_pos
136
137func _ready() -> void:
138 player.camera.zoom = Vector2(starting_zoom, starting_zoom)
139 run_generators()
140# # position first two enemies
141# var enemies = get_tree().get_nodes_in_group("enemies")
142# var enemy1: Enemy = enemies[0]
143# enemy1.position = Vector2(-300, 200)
144# var enemy2: Enemy = enemies[1]
145# enemy2.position = Vector2(300, 200)
146 pass
147
148func run_generators() -> void:
149 for g in generators:
150 var generator = g
151 while true:
152 var is_done = generator.run($Environment)
153 if is_done:
154 break
155 pass
156
157func _input(_event: InputEvent) -> void:
158 if player.dead:
159 return
160
161func _process(_delta: float) -> void:
162 if is_game_over:
163 return
164
165 # move navigation polygon around the player, navigation won't work outside of this polygon
166 var nav_size = Vector2(item_replacement_distance * 2 * 5, item_replacement_distance * 2 * 5)
167 var nav_pos = player.global_position - (nav_size * 0.5)
168 var vertices = PoolVector2Array([
169 nav_pos,
170 nav_pos + Vector2(nav_size.x, 0),
171 nav_pos + nav_size,
172 nav_pos + Vector2(0, nav_size.y)
173 ])
174 var polygon = NavigationPolygon.new()
175 polygon.set_vertices(vertices)
176 var indices = PoolIntArray([0, 1, 2, 3])
177 polygon.add_polygon(indices)
178 navigation_polygon_instance.navpoly = polygon
179
180 # set the objective text
181 player.set_objective("%s / %s" % [completed_objectives, max_objectives])
182
183 # if all objectives are complete, show the game finished menu
184 var all_done = completed_objectives == max_objectives
185 if all_done:
186 is_game_over = true
187 var score = player.score
188 player.add_high_score(score)
189 var final_message = "You won with %s points!" % score
190 $Player/UI/GameFinishedMenu.find_node("Label").text = final_message
191 $Player/UI/GameFinishedMenu.show()
192 $Player/UI/HUD.is_game_over = true
193 get_tree().paused = true
194 return
195
196 run_generators()
197
198 # position the destination
199 $Destination.visible = player.is_destination_set
200 $Destination.global_position = player.destination
201
202 # clear radar and populate with all items
203 var enemies = get_tree().get_nodes_in_group("enemies")
204 var filteredEnemies = Utils.filter(funcref(self,"filter_invalid_enemies"), enemies)
205 player.clear_radar()
206 player.update_radar(get_tree().get_nodes_in_group("gold"), Color.gold)
207 player.update_radar(filteredEnemies, Color.red)
208 if player.settings.show_items:
209 player.update_radar(get_tree().get_nodes_in_group("health"), Color.gray)
210 player.update_radar(get_tree().get_nodes_in_group("weapons"), Color.white)
211 player.update_radar(get_tree().get_nodes_in_group("bombs"), Color.purple)
212
213func _on_Destination_body_entered(body: Node) -> void:
214 if body == player:
215 player.clear_destination()
216
217func filter_invalid_enemies(enemy: Enemy) -> bool:
218 if enemy.dead:
219 return false
220 return true
221
222func _on_ShootTimer_timeout() -> void:
223 if player.dead:
224 return
225
226func _on_Button_pressed() -> void:
227 get_tree().paused = false
228 $UI/PauseMenu.hide()
229
230func _on_Game_over_button_pressed() -> void:
231 $UI/GameFinishedMenu.hide()
232 restart()
233
234func restart() -> void:
235 get_tree().paused = false
236 var _err = get_tree().reload_current_scene()
237
238func _on_Player_debug() -> void:
239# player.score += 1
240# player.kill()
241# player.score = 123
242# completed_objectives = max_objectives
243# player.debug()
244# weapon_consumed(Weapons.create_rocket_gun())
245 pass
246
247func _on_Player_destination_set() -> void:
248 $Destination.visible = player.is_destination_set
249 $Destination.global_position = player.destination
250 pass
251
252func _on_UpdateTimer_timeout() -> void:
253 var env_items = environment_node.get_children()
254 for ei in env_items:
255 var item = ei as Node2D
256 var enemy := item as Enemy
257
258# # if item is enemy, have them target the player
259# if enemy:
260# enemy.set_target($Player.position)
261
262 # if the item is too far from the player, teleport it to a closer location
263 var diff = item.global_position - player.global_position
264 var dist = diff.length()
265 var is_too_far = dist > item_replacement_distance
266 if is_too_far:
267 var new_pos = get_new_environment_position(1 + randf())
268 Utils.log("moving distant item from", item.global_position, "to", new_pos)
269 if enemy:
270 enemy.teleport(new_pos)
271 else:
272 item.global_position = new_pos