From f0f717e00e49d67a7a6f894c35ecc674dbefce9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Thu, 21 Aug 2025 06:11:09 +0200 Subject: [PATCH] game: improve enemy-manager --- scenes/main.tscn | 4 ++- scenes/managers/enemy_manager.gd | 53 +++++++++++++++++++++++++++++++- scenes/player.gd | 3 +- scenes/weapons/weapon_base.gd | 5 ++- scenes/weapons/weapon_sword.gd | 2 ++ 5 files changed, 63 insertions(+), 4 deletions(-) diff --git a/scenes/main.tscn b/scenes/main.tscn index a017e5d..4b5bd52 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -25,8 +25,10 @@ position = Vector2(1057, 798) camera = NodePath("../MainCamera") main_ui = NodePath("../MainUI") -[node name="EnemyManager" parent="." node_paths=PackedStringArray("target") instance=ExtResource("5_tbgi4")] +[node name="EnemyManager" parent="." node_paths=PackedStringArray("target", "camera") instance=ExtResource("5_tbgi4")] +spawn_rate = 1.5 target = NodePath("../Player") +camera = NodePath("../MainCamera") [node name="PickupMagnet" parent="." instance=ExtResource("6_tefeu")] position = Vector2(1697, 414) diff --git a/scenes/managers/enemy_manager.gd b/scenes/managers/enemy_manager.gd index 7ef1b50..8bc1c9a 100644 --- a/scenes/managers/enemy_manager.gd +++ b/scenes/managers/enemy_manager.gd @@ -4,6 +4,7 @@ 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 @@ -22,11 +23,61 @@ func _on_timer_timeout() -> void: GlobalConst.sig_debug_stats_set.emit("enemy_count", "%s" % len(enemies)) if len(enemies) < max_enemies: var new_enemy = ENEMY_RAT.instantiate() - new_enemy.position = target.position + Vector2(50, 50) + new_enemy.position = _get_spawn_pos() new_enemy.target = target 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() diff --git a/scenes/player.gd b/scenes/player.gd index 5fc982f..442d018 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -16,10 +16,12 @@ var dead: bool = false var death_anim_done: bool = false var god_mode: bool = false + func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("active"): weapon.do_active() + func _ready() -> void: camera.position = global_position main_ui.player_ui.update_hp() @@ -27,7 +29,6 @@ func _ready() -> void: if not weapon: weapon = WEAPON_SWORD.instantiate() add_child(weapon) - func _physics_process(delta: float) -> void: diff --git a/scenes/weapons/weapon_base.gd b/scenes/weapons/weapon_base.gd index e63942f..623f248 100644 --- a/scenes/weapons/weapon_base.gd +++ b/scenes/weapons/weapon_base.gd @@ -9,6 +9,7 @@ extends Node2D @onready var active_cd_timer: Timer = $ActiveCDTimer + func _on_attack_cd_timer_timeout() -> void: do_attack() @@ -16,16 +17,18 @@ func _on_attack_cd_timer_timeout() -> void: func do_attack() -> void: push_error("%s does not implement do_attack" % self) + func do_active() -> void: if not active_cd_timer.is_stopped(): return active_cd_timer.start() _do_active() - + func _do_active() -> void: push_error("%s does not implement do_active" % self) + func find_target_in_radius() -> EnemyBase: var space_state: PhysicsDirectSpaceState2D = get_world_2d().direct_space_state var shape := CircleShape2D.new() diff --git a/scenes/weapons/weapon_sword.gd b/scenes/weapons/weapon_sword.gd index 9b73a21..a8d081b 100644 --- a/scenes/weapons/weapon_sword.gd +++ b/scenes/weapons/weapon_sword.gd @@ -27,6 +27,7 @@ func do_attack() -> void: projectile.on_hit_sig = projectile_hit add_child(projectile) + func _do_active() -> void: var radius = targeting_range_shape.shape.radius var count = 15 @@ -41,6 +42,7 @@ func _do_active() -> void: projectile.on_hit_sig = projectile_hit add_child(projectile) + func deal_damage(enemy: EnemyBase, damage_mult: float): var crit_chance = _player.player_stats.get_final("crit_chance", _player.modifiers) var damage_dealt = attack_damage * damage_mult