using Godot; using System; using System.Diagnostics; public partial class Enemy : Area2D { private InteractionController _cachedPlayer; private EnemyState _currentState = EnemyState.Idle; [Export] public PackedScene BulletScene { get; set; } // Called when the node enters the scene tree for the first time. public override void _Ready() { } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { switch (_currentState) { case EnemyState.Idle: break; case EnemyState.Primed: // Have the raycast follow the player and shoot if visible //HandlePlayerDetection(); break; //case EnemyState.Shooting: // Shoot //break; default: break; } } public override void _PhysicsProcess(double delta) { HandlePlayerDetection(); } private void HandlePlayerDetection() { if (_cachedPlayer == null || _currentState is not EnemyState.Primed) { return; } if (IsPlayerInSight()) { // SHOOT var bullet = BulletScene.Instantiate(); Owner.AddChild(bullet); bullet.Transform = this.GlobalTransform; bullet.Position = this.Position; bullet.SetDirection((_cachedPlayer.GlobalPosition - this.GlobalPosition).Normalized()); } } private bool IsPlayerInSight() { var spaceState = GetWorld2D().DirectSpaceState; var query = PhysicsRayQueryParameters2D.Create(this.GlobalPosition, _cachedPlayer.GlobalPosition, CollisionMask, new Godot.Collections.Array { GetRid() }); var result = spaceState.IntersectRay(query); // If count is 0 then the player is in sight, otherwise there is level geometry in the way return result.Count == 0; // if (result.Count > 0) // GD.Print("Hit at point: ", result["position"]); } private void _on_player_detection_area_entered(Area2D area) { // Assume area is player for now if (area is InteractionController player) { Debug.WriteLine("Enemy detection area Entered by interaction controller"); _cachedPlayer = player; if (_currentState is EnemyState.Idle) { _currentState = EnemyState.Primed; } } } private void _on_player_detection_area_exited(Area2D area) { if (_currentState is EnemyState.Primed) { _currentState = EnemyState.Idle; } } private enum EnemyState { Idle, Primed } }