extends Node2D @export var min_spawn_interval: float = 3.0 @export var max_spawn_interval: float = 6.0 @export var spawn_margin: float = 150.0 # #96: this spawner is the only place the player meets an enemy off an # authored map, so a new open-space enemy has to take a share of it or it # only ever exists in the setup editor. Kept a minority of the wave: the # lancer is punctuation against a background of chasers, and a screen of # them would be all telegraph and no fight. @export var lancer_chance: float = 0.25 @onready var fleet: Node2D = get_node("../Fleet") var enemy_scene: PackedScene = preload("res://enemies/Enemy.tscn") var timer: float = 0.0 var next_spawn_time: float = 0.0 func _ready() -> void: randomize() _reset_timer() func _process(delta: float) -> void: timer += delta if timer >= next_spawn_time: timer = 0.0 _reset_timer() _spawn_enemy() func _reset_timer() -> void: next_spawn_time = randf_range(min_spawn_interval, max_spawn_interval) func _spawn_enemy() -> void: if fleet.ships.is_empty(): return var visible_rect: Rect2 = ViewUtils.get_visible_world_rect(self) var radius: float = visible_rect.size.length() / 2.0 + spawn_margin var angle: float = randf() * TAU var spawn_pos: Vector2 = fleet.get_centroid() + Vector2(cos(angle), sin(angle)) * radius var enemy: Node2D = enemy_scene.instantiate() # Set before add_child: Enemy._ready() is what resolves enemy_id into a # definition, and it runs the moment the node enters the tree. enemy.enemy_id = "lancer" if randf() < lancer_chance else "chaser" enemy.position = spawn_pos get_parent().add_child(enemy)