Add door behavior interface and implementations for animation and linear movement

This commit is contained in:
2025-10-30 01:31:20 +01:00
parent 5ae8b6f08c
commit f2ff758dcb
10 changed files with 162 additions and 66 deletions

View File

@@ -0,0 +1,49 @@
using cryptonymthunder.Code.Interfaces;
using GameCore.ECS;
using Godot;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class AnimationPlayerDoorBehavior : DoorBehaviorResource, IDoorBehavior
{
[Export] private NodePath _animationPlayerPath;
[Export] private string _animationName = "Open";
private AnimationPlayer _animationPlayer;
private Animation _animation;
public override void Initialize(Node3D doorNode, World world)
{
if (_animationPlayerPath == null)
{
world.Logger.Error($"[AnimationPlayerDoorBehavior] NodePath is not set for door '{doorNode.Name}'");
return;
}
_animationPlayer = doorNode.GetNode<AnimationPlayer>(_animationPlayerPath);
if (_animationPlayer == null)
{
world.Logger.Error($"[AnimationPlayerDoorBehavior] Could not find AnimationPlayer at path '{_animationPlayerPath}' on door '{doorNode.Name}'");
return;
}
if (!_animationPlayer.HasAnimation(_animationName))
{
world.Logger.Error($"[AnimationPlayerDoorBehavior] AnimationPlayer on '{doorNode.Name}' is missing animation: '{_animationName}'");
return;
}
_animation = _animationPlayer.GetAnimation(_animationName);
_animationPlayer.Play(_animationName);
_animationPlayer.Pause();
}
public override void UpdateProgress(float progress, float delta)
{
if (_animationPlayer == null || _animation == null) return;
var targetTime = progress * _animation.Length;
_animationPlayer.Seek(targetTime, true);
}
}

View File

@@ -0,0 +1 @@
uid://b8b28akam7skl

View File

@@ -0,0 +1,16 @@
using cryptonymthunder.Code.Interfaces;
using GameCore.ECS;
using Godot;
namespace CryptonymThunder.Code.Resources;
public partial class DoorBehaviorResource : Resource, IDoorBehavior
{
public virtual void Initialize(Node3D doorNode, World world)
{
}
public virtual void UpdateProgress(float progress, float delta)
{
}
}

View File

@@ -0,0 +1 @@
uid://b35aei3jl2524

View File

@@ -0,0 +1,64 @@
using cryptonymthunder.Code.Interfaces;
using GameCore.ECS;
using Godot;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class LerpDoorBehavior : DoorBehaviorResource, IDoorBehavior
{
[Export] private NodePath _nodeToMovePath;
[ExportGroup("Position")]
[Export] private Vector3 _closedPosition = Vector3.Zero;
[Export] private Vector3 _openPosition = Vector3.Up * 3f;
[ExportGroup("Rotation")]
[Export] private Vector3 _closedRotationDegrees = Vector3.Zero;
[Export] private Vector3 _openRotationDegrees = Vector3.Zero;
private Node3D _nodeToMove;
public override void Initialize(Node3D doorNode, World world)
{
if (_nodeToMovePath == null)
{
_nodeToMove = doorNode;
}
else
{
_nodeToMove = doorNode.GetNode<Node3D>(_nodeToMovePath);
if (_nodeToMove == null)
{
world.Logger.Error($"[LerpDoorBehavior] Could not find NodeToMove at path '{_nodeToMovePath}' on door '{doorNode.Name}'");
}
}
}
public override void UpdateProgress(float progress, float delta)
{
if (_nodeToMove == null) return;
_nodeToMove.RotationDegrees = _closedRotationDegrees.Lerp(_openRotationDegrees, progress);
var targetPosition = _closedPosition.Lerp(_openPosition, progress);
if (_nodeToMove is CharacterBody3D doorBody)
{
if (delta > 0f)
{
var velocity = (targetPosition - doorBody.Position) / delta;
doorBody.Velocity = velocity;
doorBody.MoveAndSlide();
}
else
{
doorBody.Position = targetPosition;
}
}
else
{
_nodeToMove.Position = targetPosition;
}
}
}

View File

@@ -0,0 +1 @@
uid://cratjw4trngpr