fuzzyworld

godot-shooter / files / scenes / World.gd

World.gd

8.1 KB · history · blame

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