Added Elite enemies before wave switch

main^2
Artur 2026-06-02 17:01:57 +02:00
parent 89f0faea9a
commit 7d17c1312e
3 changed files with 51 additions and 22 deletions

View File

@ -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 }
]
}
]

View File

@ -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]

View File

@ -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: