diff --git a/data/spawn_stages.json b/data/spawn_stages.json index fc4350e..45066d6 100644 --- a/data/spawn_stages.json +++ b/data/spawn_stages.json @@ -1,26 +1,28 @@ [ { - "time_start": 0, - "time_end": 60, - "entries": [ - { "enemy": "res://scenes/slime.tscn", "count_at_start": 0, "count_at_end": 15, "min_interval": 0.5 } - ] + "time_start": 0, + "time_end": 60, + "elite_enemy": "res://scenes/slime.tscn", + "entries": [ + { "enemy": "res://scenes/slime.tscn", "count_at_start": 0, "count_at_end": 15, "min_interval": 0.5 } + ] }, { - "time_start": 60, - "time_end": 180, - "entries": [ - { "enemy": "res://scenes/slime.tscn", "count_at_start": 15, "count_at_end": 40, "min_interval": 0.3 }, - { "enemy": "res://scenes/blue_slime.tscn", "count_at_start": 0, "count_at_end": 10, "min_interval": 0.8 } - ] + "time_start": 60, + "time_end": 180, + "elite_enemy": "res://scenes/blue_slime.tscn", + "entries": [ + { "enemy": "res://scenes/slime.tscn", "count_at_start": 15, "count_at_end": 40, "min_interval": 0.3 }, + { "enemy": "res://scenes/blue_slime.tscn", "count_at_start": 0, "count_at_end": 10, "min_interval": 0.8 } + ] }, { - "time_start": 180, - "time_end": -1, - "entries": [ - { "enemy": "res://scenes/slime.tscn", "count_at_start": 40, "count_at_end": 100, "min_interval": 0.2 }, - { "enemy": "res://scenes/blue_slime.tscn", "count_at_start": 10, "count_at_end": 60, "min_interval": 0.5 }, - { "enemy": "res://scenes/fire_slime.tscn", "count_at_start": 0, "count_at_end": 40, "min_interval": 0.6 } - ] + "time_start": 180, + "time_end": -1, + "entries": [ + { "enemy": "res://scenes/slime.tscn", "count_at_start": 40, "count_at_end": 100, "min_interval": 0.2 }, + { "enemy": "res://scenes/blue_slime.tscn", "count_at_start": 10, "count_at_end": 60, "min_interval": 0.5 }, + { "enemy": "res://scenes/fire_slime.tscn", "count_at_start": 0, "count_at_end": 40, "min_interval": 0.6 } + ] } ] diff --git a/scripts/SpawnStage.gd b/scripts/SpawnStage.gd index 186b8f7..5ac3e26 100644 --- a/scripts/SpawnStage.gd +++ b/scripts/SpawnStage.gd @@ -2,5 +2,6 @@ extends Resource class_name SpawnStage @export var time_start: float = 0.0 -@export var time_end: float = -1.0 # -1 = forever +@export var time_end: float = -1.0 +@export var elite_enemy: PackedScene = null @export var entries: Array[StageEntry] diff --git a/scripts/spawn_control.gd b/scripts/spawn_control.gd index 2f0330b..762c687 100644 --- a/scripts/spawn_control.gd +++ b/scripts/spawn_control.gd @@ -8,11 +8,13 @@ var elapsed_time: float = 0.0 const STAGES_JSON = "res://data/spawn_stages.json" -var stages: Array[SpawnStage] = [] +const ELITE_HP_MULT := 10 +const ELITE_SPD_MULT := 0.25 +const ELITE_SCALE := 3.0 -# _state keys: Vector2i(stage_idx, entry_idx) -# values: { "timer": float, "alive": int } +var stages: Array[SpawnStage] = [] var _state: Dictionary = {} +var current_stage_idx: int = -1 func _ready() -> void: var camera: Camera2D = get_parent().get_node("Camera2D") @@ -44,6 +46,8 @@ func _load_stages(path: String) -> void: var stage = SpawnStage.new() stage.time_start = float(sd["time_start"]) stage.time_end = float(sd["time_end"]) + if sd.has("elite_enemy"): + stage.elite_enemy = load(sd["elite_enemy"]) for ed in sd["entries"]: var entry = StageEntry.new() entry.enemy = load(ed["enemy"]) @@ -72,9 +76,31 @@ func get_spawn_position() -> Vector2: spawn_y = randf_range(up_right.y, down_right.y) return Vector2(spawn_x, spawn_y) +func _active_stage_idx() -> int: + for si in stages.size(): + var s: SpawnStage = stages[si] + if elapsed_time >= s.time_start and (s.time_end == -1.0 or elapsed_time < s.time_end): + return si + return stages.size() - 1 + +func _spawn_elite(scene: PackedScene) -> void: + var enemy = scene.instantiate() + enemy.global_position = get_spawn_position() + add_child(enemy) + enemy.scale = Vector2(ELITE_SCALE, ELITE_SCALE) + enemy.max_hp = enemy.max_hp * ELITE_HP_MULT + enemy.hp = enemy.max_hp + enemy.speed *= ELITE_SPD_MULT + func _process(delta: float) -> void: elapsed_time += delta + var new_idx := _active_stage_idx() + if new_idx != current_stage_idx: + if current_stage_idx >= 0 and stages[current_stage_idx].elite_enemy != null: + _spawn_elite(stages[current_stage_idx].elite_enemy) + current_stage_idx = new_idx + for si in stages.size(): var stage: SpawnStage = stages[si] if elapsed_time < stage.time_start: