cirnogodot/Scripts/Components/FSM/Enemy/PlayerDetectionModule.cs

86 lines
2.8 KiB
C#
Raw Normal View History

2025-03-20 18:22:40 +01:00
using Cirno.Scripts.Enums;
using Godot;
using Godot.Collections;
namespace Cirno.Scripts.Components.FSM.Enemy;
public partial class PlayerDetectionModule : Area2D
{
[Signal]
public delegate void PlayerInRangeEventHandler();
[Signal]
public delegate void PlayerOutOfRangeEventHandler();
[Export(PropertyHint.Layers2DPhysics)]
public uint ObstaclesCollisionMask { get; private set; }
public Vector2? LastKnownPlayerPosition { get; private set; }
//public bool PlayerInActiveArea { get; private set; }
private CollisionShape2D _collisionShape2D;
public override void _Ready()
{
}
public void SetRange(float range)
{
_collisionShape2D ??= this.GetNode<CollisionShape2D>("CollisionShape2D");
if (_collisionShape2D.Shape is CircleShape2D shape2D)
{
shape2D.Radius = range;
}
}
public bool IsPlayerInRange(float range)
{
2025-03-20 19:28:40 +01:00
if (GameManager.Instance is null) return false;
if (!GameManager.Instance.PlayerPosition.HasValue)
2025-03-20 18:22:40 +01:00
{
return false;
}
2025-03-21 10:30:44 +01:00
return this.GlobalPosition.DistanceTo(GameManager.Instance.PlayerPosition.Value) <= range;
2025-03-20 18:22:40 +01:00
}
public bool IsPlayerInSight()
{
2025-03-20 19:28:40 +01:00
if (GameManager.Instance is null) return false;
2025-03-20 18:22:40 +01:00
//if (_cachedPlayer == null) return false;
2025-03-20 19:28:40 +01:00
if (!GameManager.Instance.PlayerPosition.HasValue) return false;
2025-03-20 18:22:40 +01:00
var spaceState = GetWorld2D().DirectSpaceState;
// It needs to use its own collision mask because it's detecting obstacles rather than the player
var query = PhysicsRayQueryParameters2D.Create(this.GlobalPosition, GameManager.Instance.PlayerPosition.Value, ObstaclesCollisionMask,
[GetRid()]);
//query.CollideWithBodies = true;
//query.CollideWithAreas = true;
// var query = PhysicsRayQueryParameters2D.Create(this.GlobalPosition, _cachedPlayer.GlobalPosition, CollisionMask, new Array<Rid> { GetRid() });
var result = spaceState.IntersectRay(query);
// If count is 0 then the player is in sight, otherwise there is level geometry in the way
var found = result.Count == 0;
if (found)
{
LastKnownPlayerPosition = GameManager.Instance.PlayerPosition;
}
return found;
}
private void _on_area_entered(Area2D area)
{
if (area is not InteractionController player) return;
EmitSignal(SignalName.PlayerInRange);
//PlayerInActiveArea = true;
}
private void _on_area_exited(Area2D area)
{
if (area is not InteractionController player) return;
EmitSignal(SignalName.PlayerOutOfRange);
//PlayerInActiveArea = false;
}
}