mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-06-12 12:45:54 +00:00
Enemy AI
This commit is contained in:
parent
383fc740df
commit
ede8f2028a
34 changed files with 1418 additions and 417 deletions
120
Scripts/Components/FSM/Enemy/3D/PlayerDetection3D.cs
Normal file
120
Scripts/Components/FSM/Enemy/3D/PlayerDetection3D.cs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
using Cirno.Scripts.Components.FSM._3DPlayer;
|
||||
using Godot;
|
||||
|
||||
namespace Cirno.Scripts.Components.FSM.Enemy._3D;
|
||||
|
||||
public partial class PlayerDetection3D : Area3D
|
||||
{
|
||||
[Signal]
|
||||
public delegate void PlayerInRangeEventHandler();
|
||||
|
||||
[Signal]
|
||||
public delegate void PlayerOutOfRangeEventHandler();
|
||||
|
||||
[Export(PropertyHint.Layers3DPhysics)]
|
||||
public uint ObstaclesCollisionMask { get; private set; }
|
||||
|
||||
public Vector3? LastKnownPlayerPosition { get; set; }
|
||||
public Vector3? LastKnowPlayerVelocity { get; set; }
|
||||
|
||||
//public bool PlayerInActiveArea { get; private set; }
|
||||
private CollisionShape3D _collisionShape;
|
||||
|
||||
private bool _initialized = false;
|
||||
// public override void _Ready()
|
||||
// {
|
||||
// CallDeferred(MethodName.Initialize);
|
||||
// }
|
||||
|
||||
private CharacterBody3D _mainBody;
|
||||
|
||||
public void Initialize(CharacterBody3D mainBody)
|
||||
{
|
||||
_mainBody = mainBody;
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
public void SetRange(float range)
|
||||
{
|
||||
_collisionShape ??= this.GetNode<CollisionShape3D>("CollisionShape3D");
|
||||
if (_collisionShape.Shape is CylinderShape3D shape3D)
|
||||
{
|
||||
shape3D.Radius = range;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPlayerInRange(float range)
|
||||
{
|
||||
if (!_initialized) return false;
|
||||
if (GameController.Instance is null) return false;
|
||||
|
||||
if (!GameController.Instance.PlayerPosition.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.GlobalPosition.DistanceTo(GameController.Instance.PlayerPosition.Value) <= range;
|
||||
}
|
||||
|
||||
public bool IsPlayerInSight()
|
||||
{
|
||||
if (!_initialized) return false;
|
||||
if (GameController.Instance is null) return false;
|
||||
//if (_cachedPlayer == null) return false;
|
||||
if (!GameController.Instance.PlayerPosition.HasValue) return false;
|
||||
|
||||
var found = HasLineOfSight(this.GlobalPosition, GameController.Instance.PlayerPosition.Value);
|
||||
|
||||
// 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, GameController.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 = GameController.Instance.PlayerPosition;
|
||||
LastKnowPlayerVelocity = GameController.Instance.PlayerVelocity;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private void _on_body_entered(Node3D area)
|
||||
{
|
||||
if (area is not IsoPlayerFSMProxy player) return;
|
||||
EmitSignal(SignalName.PlayerInRange);
|
||||
//PlayerInActiveArea = true;
|
||||
}
|
||||
|
||||
private void _on_body_exited(Node3D area)
|
||||
{
|
||||
if (area is not IsoPlayerFSMProxy player) return;
|
||||
EmitSignal(SignalName.PlayerOutOfRange);
|
||||
//PlayerInActiveArea = false;
|
||||
}
|
||||
|
||||
public bool HasLineOfSight(Vector3 startPos, Vector3 endPos)
|
||||
{
|
||||
var spaceState = GetWorld3D().DirectSpaceState;
|
||||
|
||||
// It needs to use its own collision mask because it's detecting obstacles rather than the player
|
||||
var query = PhysicsRayQueryParameters3D.Create(startPos, endPos, ObstaclesCollisionMask,
|
||||
[GetRid(), _mainBody.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;
|
||||
|
||||
return found;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue