Files
slopvivors/scenes/managers/enemy_manager.gd

104 lines
2.8 KiB
GDScript

class_name EnemyManager
extends Node2D
@export var max_enemies: int
@export var spawn_rate: float
@export var target: CollisionObject2D
@export var camera: Camera2D
@onready var timer: Timer = $Timer
const ENEMY_RAT = preload("res://scenes/enemies/enemy_rat.tscn")
const ENEMY_BAT = preload("res://scenes/enemies/enemy_bat.tscn")
const ENEMY_SLIME_SMALL = preload("res://scenes/enemies/enemy_slime_small.tscn")
const SLIME_COLOR_VARIATIONS: Array[Color]= [ Color.CHARTREUSE, Color.FUCHSIA, Color.DARK_ORANGE ]
func _ready() -> void:
timer.wait_time = 1 / spawn_rate
timer.start()
GlobalConst.sig_stop_spawning.connect(_on_stop_spawning)
GlobalConst.sig_set_spawn_rate.connect(_on_set_spawn_rate)
func _on_timer_timeout() -> void:
var enemies = get_tree().get_nodes_in_group(GlobalConst.GROUP_ENEMY)
GlobalConst.sig_debug_stats_set.emit("enemy_count", "%s" % len(enemies))
var next_enemy: PackedScene
match randi() % 3:
0:
next_enemy = ENEMY_BAT
1:
next_enemy = ENEMY_RAT
2:
next_enemy = ENEMY_SLIME_SMALL
if len(enemies) < max_enemies:
var new_enemy = next_enemy.instantiate()
new_enemy.position = _get_spawn_pos()
new_enemy.target = target
if is_instance_of(new_enemy, EnemySlimeSmall):
var slime_color: Color = SLIME_COLOR_VARIATIONS.pick_random()
new_enemy.color = slime_color
add_child(new_enemy)
func _get_spawn_pos() -> Vector2:
var rect = _get_camera_rect()
var side = randi() % 4
var margin = 50
var pos: Vector2
match side:
0: # Top
pos = Vector2(
randf_range(rect.position.x, rect.position.x + rect.size.x),
rect.position.y - margin
)
1: # Bottom
pos = Vector2(
randf_range(rect.position.x, rect.position.x + rect.size.x),
rect.position.y + rect.size.y + margin
)
2: # Left
pos = Vector2(
rect.position.x - margin,
randf_range(rect.position.y, rect.position.y + rect.size.y)
)
3: # Right
pos = Vector2(
rect.position.x + rect.size.x + margin,
randf_range(rect.position.y, rect.position.y + rect.size.y)
)
if !_is_pos_valid(pos):
pos = _get_spawn_pos()
return pos
func _is_pos_valid(pos: Vector2) -> bool:
var space = get_world_2d().direct_space_state
var parameters = PhysicsPointQueryParameters2D.new()
parameters.collide_with_areas = false
parameters.collide_with_bodies = true
parameters.collision_mask = 1
parameters.position = pos
var result = space.intersect_point(parameters, 1)
return result.size() == 0
func _get_camera_rect() -> Rect2:
var viewport_size = camera.get_viewport_rect().size
var half_size = viewport_size * 0.5
var top_left = camera.global_position - half_size
return Rect2(top_left, viewport_size)
func _on_stop_spawning(val: bool):
if val:
timer.stop()
elif timer.is_stopped():
timer.start()
func _on_set_spawn_rate(val: float):
timer.wait_time = 1 / val