class_name EnemyBase extends Area2D ## 敌机基类:血量、受击闪白、死亡结算与爆炸。 var hp := 1 var score_value := 100 var dead := false var drops_powerup := false ## 激光命中判定的近似半径(水平覆盖 + 垂直截断) var hit_radius := 16.0 func apply_damage(dmg: int) -> void: if dead: return hp -= dmg if hp <= 0: dead = true _die() else: _flash() func _die() -> void: _spawn_drop() var game := get_tree().get_first_node_in_group("game") as Game if game != null: game.add_score(score_value) game.spawn_explosion(global_position, 1.0) queue_free() ## 死亡时按标记掉落道具(可能在物理信号回调中调用,需延迟入树)。 ## forced 为 -1 时随机 P/B(各 50%)。 func _spawn_drop(forced := -1) -> void: if not drops_powerup: return var container := get_tree().get_first_node_in_group("powerups") if container == null: return var pickup := Powerup.new() pickup.position = global_position if forced >= 0: pickup.kind = forced else: pickup.kind = Powerup.Kind.BOMB if randf() < 0.5 else Powerup.Kind.POWER container.call_deferred("add_child", pickup) func _flash() -> void: modulate = Color(3.0, 3.0, 3.0) create_tween().tween_property(self, "modulate", Color.WHITE, 0.12) ## 朝玩家方向的单位向量;玩家不存在或不活跃时朝正下方 func _aim_direction() -> Vector2: var game := get_tree().get_first_node_in_group("game") as Game if game != null and is_instance_valid(game.player) and game.player.active: var to_player: Vector2 = game.player.global_position - global_position if to_player.length() > 1.0: return to_player.normalized() return Vector2.DOWN ## 向敌方弹幕容器发射一发子弹 func _fire_bullet(velocity: Vector2, muzzle_offset := Vector2(0.0, 14.0)) -> void: var container := get_tree().get_first_node_in_group("enemy_bullets") if container == null: return var bullet := EnemyBullet.new() bullet.velocity = velocity container.add_child(bullet) bullet.global_position = global_position + muzzle_offset