123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- extends Node2D
- class_name Game
- @onready var health_bar: HealthBar = $HealthBar
- @onready var overlay: CanvasLayer = $Overlay
- @onready var transition: Transition = $Overlay/Transition
- @onready var player_spawn: PlayerSpawnZone = $PlayerSpawnZone
- @onready var spawn_timer: Timer = $Timer
- @onready var ui_root: Control = $UI/Root
- @onready var wave_label: Label = $UI/Root/WaveLabel
- @onready var phase_label: Label = $UI/Root/PhaseLabel
- @onready var next_phase_button: Button = $UI/Root/NextPhaseButton
- @onready var combat_start_sound: AudioStreamPlayer = $Sounds/CombatStartSound
- @onready var main_menu: PackedScene = load("res://screens/main_menu.tscn")
- @onready var bot_scene: PackedScene = load("res://assets/scenes/bot.tscn")
- @onready var game_over_scene: PackedScene = load("res://assets/scenes/game_over.tscn")
- @onready var victory_scene: PackedScene = load("res://assets/scenes/victory.tscn")
- @onready var intro_scene: PackedScene = load("res://assets/scenes/intro.tscn")
- @onready var left_enemy_label: Label = $UI/Root/LeftEnemyLabel
- @onready var right_enemy_label: Label = $UI/Root/RightEnemyLabel
- @onready var top_enemy_label: Label = $UI/Root/TopEnemyLabel
- @onready var spawn_points: Array[Marker2D] = [
- $EnemySpawns/EnemySpawn_Left,
- $EnemySpawns/EnemySpawn_Right,
- $EnemySpawns/EnemySpawn_Top,
- ]
- @onready var enemy_labels: Array[Label] = [
- $UI/Root/LeftEnemyLabel,
- $UI/Root/RightEnemyLabel,
- $UI/Root/TopEnemyLabel,
- ]
- enum Phase {
- PHASE_SETUP,
- PHASE_COMBAT,
- PHASE_LOOT,
- }
- enum Loot {
- LOOT_SURVIVOR,
- LOOT_HEAL,
- LOOT_LOWER_COOLDOWN,
- }
- const RELOAD_TIME: float = 4.0
- static var reload_time: float = RELOAD_TIME # seconds
- static var max_ammo: int = 1 # shots
- static var base_accuracy: float = 0.33 # percent
- var phase: Phase = Phase.PHASE_SETUP:
- set(new_value):
- phase = new_value
- match new_value:
- Phase.PHASE_SETUP:
- phase_label.text = "PHASE: SETUP"
- Phase.PHASE_COMBAT:
- phase_label.text = "PHASE: COMBAT"
- Phase.PHASE_LOOT:
- phase_label.text = "PHASE: LOOT"
- var waves_completed: int = 0:
- set(new_value):
- waves_completed = new_value
- wave_label.text = "WAVE: %d" % (new_value + 1)
- func update_enemy_labels() -> void:
- for n in 3:
- var enemies = spawn_points[n].get_child_count()
- enemy_labels[n].text = str(enemies)
- func set_enemy_label_visible(value: bool) -> void:
- for label in enemy_labels:
- label.visible = value
- func _ready() -> void:
- Game.reload_time = RELOAD_TIME # seconds
- Game.max_ammo = 1 # shots
- Game.base_accuracy = 0.33 # percent
- waves_completed = 0
- phase = Phase.PHASE_SETUP
- overlay.visible = true
- start_setup()
- player_spawn.add_survivor()
-
- var intro: Intro = null
- if Config.show_tutorial:
- intro = intro_scene.instantiate()
- add_child(intro)
- ui_root.visible = false
-
- transition.slide_out()
- await transition.game_fully_visible
-
- if intro != null:
- intro.start()
- await intro.finished
- await transition.transition("WAVE 1", func ():
- ui_root.visible = true
- intro.queue_free()
- )
- func _process(_delta: float) -> void:
- var intro_visible: bool = get_tree().get_first_node_in_group("intro") != null
-
- if Input.is_action_pressed("ui_cancel") && not intro_visible:
- go_to_main_menu()
- if phase == Phase.PHASE_COMBAT:
- if get_foes().is_empty() and health_bar.health != 0:
- end_combat()
- func go_to_main_menu() -> void:
- var tree = get_tree()
- transition.text = ""
- tree.paused = true
- transition.slide_in()
- await transition.game_fully_hidden
- tree.change_scene_to_packed(main_menu)
- tree.paused = false
- func spawn_bot(spawn: Marker2D, index: int) -> void:
- var bot: Bot = bot_scene.instantiate()
- bot.name = "Bot #%d" % (index + 1)
- bot.speed += waves_completed
- bot.visible = false
- spawn.add_child(bot)
- bot.position = Vector2.ZERO
- func get_foes() -> Array[Area2D]:
- var foes: Array[Area2D] = []
- foes.assign(get_tree().get_nodes_in_group("foe"))
- return foes
- func get_survivors() -> Array[Area2D]:
- var survivors: Array[Area2D] = []
- survivors.assign(get_tree().get_nodes_in_group("survivor"))
- return survivors
- func get_waiting_foes() -> Array[Area2D]:
- return get_foes().filter(func (foe): return not foe.visible)
- func get_active_foes() -> Array[Area2D]:
- return get_foes().filter(func (foe): return foe.visible)
-
- func activate_foe() -> void:
- var foes = get_waiting_foes()
- if not foes.is_empty():
- foes.pick_random().visible = true
- func reset_survivors() -> void:
- var survivors = get_survivors()
- #for survivor in survivors:
- # survivor.reparent(self)
- for survivor in survivors:
- #player_spawn.drop(survivor)
- #survivor.position = Vector2.ZERO
- #survivor.rotation = 0.0
- survivor.ammo = Game.max_ammo
- func _on_timer_timeout() -> void:
- activate_foe()
- func base_hit() -> void:
- health_bar.health -= 1
- if health_bar.health == 0:
- await game_over()
- func game_over() -> void:
- spawn_timer.stop()
- var foes = get_tree().get_nodes_in_group("foe")
- for foe in foes:
- foe.queue_free()
-
- var gos: GameOver = game_over_scene.instantiate()
- gos.message = "YOU DIED AFTER\nCOMPLETING %d WAVES!" % waves_completed
- ui_root.add_child(gos)
- await gos.closed
- await go_to_main_menu()
- func _on_base_area_entered(area: Area2D) -> void:
- if area.is_in_group("foe") || area.is_in_group("foe_weapons"):
- base_hit()
- func start_setup() -> void:
- for n in (waves_completed + 1):
- var spawner = spawn_points.pick_random()
- spawn_bot(spawner, n)
- update_enemy_labels()
- set_enemy_label_visible(true)
- func start_combat() -> void:
- set_enemy_label_visible(false)
- GlobalInput.dragging_disabled = true
- spawn_timer.wait_time = lerpf(3.5, 0.5, minf(float(waves_completed)/20.0, 1.0))
- spawn_timer.start()
- combat_start_sound.play()
- activate_foe()
- const LOOT_SURVIVOR: String = "+1 SURVIVOR"
- const LOOT_HEALTH: String = "+3 HEALTH"
- const LOOT_AMMO: String = "BIGGER MAGAZINES"
- const LOOT_RELOAD_TIME: String = "FASTER RELOADING"
- const LOOT_ACCURACY: String = "HIGHER ACCURACY"
- const LOOTS: Array[String] = [LOOT_SURVIVOR, LOOT_HEALTH, LOOT_AMMO, LOOT_RELOAD_TIME, LOOT_ACCURACY]
- func end_combat() -> void:
- phase = Phase.PHASE_LOOT
- spawn_timer.stop()
- await get_tree().create_timer(1.5).timeout
- var vs: Victory = victory_scene.instantiate()
- ui_root.add_child(vs)
- var loots: Array[String] = []
- loots.assign(LOOTS)
- if get_survivors().size() >= 6: # this is, so the player has a reason to move survivors even later
- loots.erase(LOOT_SURVIVOR)
- loots.shuffle()
- vs.set_loot_options(loots[0], loots[1], loots[2])
- await vs.loot_selected
- var loot: String = loots[vs.selection]
- print("selected loot: " + str(loot))
- var next_wave = waves_completed + 2
- await transition.transition("WAVE %d" % next_wave, func ():
- self.waves_completed += 1
- self.phase = Phase.PHASE_SETUP
- self.next_phase_button.disabled = false
- match loot:
- LOOT_SURVIVOR:
- self.player_spawn.add_survivor()
- LOOT_HEALTH:
- self.health_bar.health += 3
- LOOT_RELOAD_TIME:
- Game.reload_time *= 0.9
- LOOT_AMMO:
- Game.max_ammo += 1
- LOOT_ACCURACY:
- Game.base_accuracy += 0.1
- self.reset_survivors()
- self.start_setup()
- )
- GlobalInput.dragging_disabled = false
- func _on_next_phase_button_pressed() -> void:
- match phase:
- Phase.PHASE_SETUP:
- phase = Phase.PHASE_COMBAT
- next_phase_button.disabled = true
- start_combat()
- Phase.PHASE_COMBAT:
- pass # this should not happen
- Phase.PHASE_LOOT:
- pass # this should not happen
|