Add door behavior interface and implementations for animation and linear movement
This commit is contained in:
10
Code/Interfaces/IDoorBehavior.cs
Normal file
10
Code/Interfaces/IDoorBehavior.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using GameCore.ECS;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace cryptonymthunder.Code.Interfaces;
|
||||||
|
|
||||||
|
public interface IDoorBehavior
|
||||||
|
{
|
||||||
|
void Initialize(Node3D doorNode, World world);
|
||||||
|
void UpdateProgress(float progress, float delta);
|
||||||
|
}
|
||||||
1
Code/Interfaces/IDoorBehavior.cs.uid
Normal file
1
Code/Interfaces/IDoorBehavior.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cligtc5v1wl7o
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using CryptonymThunder.Code.Resources;
|
||||||
using GameCore.ECS;
|
using GameCore.ECS;
|
||||||
using GameCore.ECS.Interfaces;
|
using GameCore.ECS.Interfaces;
|
||||||
using GameCore.Interaction;
|
using GameCore.Interaction;
|
||||||
@@ -6,13 +7,11 @@ using Godot;
|
|||||||
namespace CryptonymThunder.Code.Presenters;
|
namespace CryptonymThunder.Code.Presenters;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
public partial class DoorPresenter : AnimatableBody3D, IEntityPresenter, IPresenterComponent
|
public partial class DoorPresenter : CharacterBody3D, IEntityPresenter, IPresenterComponent
|
||||||
{
|
{
|
||||||
[Export] private AnimationPlayer _animationPlayer;
|
[Export] private DoorBehaviorResource _behavior;
|
||||||
[Export] private string _openAnimationName = "Open";
|
|
||||||
|
|
||||||
private DoorComponent _doorComponent;
|
private DoorComponent _doorComponent;
|
||||||
private Animation _openAnimation;
|
|
||||||
|
|
||||||
public Entity CoreEntity { get; set; }
|
public Entity CoreEntity { get; set; }
|
||||||
|
|
||||||
@@ -21,31 +20,21 @@ public partial class DoorPresenter : AnimatableBody3D, IEntityPresenter, IPresen
|
|||||||
CoreEntity = coreEntity;
|
CoreEntity = coreEntity;
|
||||||
_doorComponent = world.GetComponent<DoorComponent>(CoreEntity);
|
_doorComponent = world.GetComponent<DoorComponent>(CoreEntity);
|
||||||
|
|
||||||
if (_animationPlayer == null)
|
if (_behavior == null)
|
||||||
{
|
{
|
||||||
world.Logger.Error($"DoorPresenter '{Name}' is missing an AnimationPlayer!");
|
world.Logger.Error($"DoorPresenter '{Name}' is missing a DoorBehaviorResource!");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_animationPlayer.HasAnimation(_openAnimationName))
|
|
||||||
{
|
|
||||||
world.Logger.Error($"DoorPresenter '{Name}' AnimationPlayer is missing animation: '{_openAnimationName}'");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_openAnimation = _animationPlayer.GetAnimation(_openAnimationName);
|
_behavior.Initialize(this, world);
|
||||||
_animationPlayer.Play(_openAnimationName);
|
|
||||||
_animationPlayer.Pause();
|
|
||||||
SyncToPresentation(0f);
|
SyncToPresentation(0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SyncToPresentation(float delta)
|
public void SyncToPresentation(float delta)
|
||||||
{
|
{
|
||||||
if (_doorComponent == null || _openAnimation == null) return;
|
if (_doorComponent == null || _behavior == null) return;
|
||||||
|
_behavior.UpdateProgress(_doorComponent.OpenProgress, delta);
|
||||||
var targetTime = _doorComponent.OpenProgress * _openAnimation.Length;
|
|
||||||
|
|
||||||
_animationPlayer.Seek(targetTime, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SyncToCore(float delta)
|
public void SyncToCore(float delta)
|
||||||
|
|||||||
49
Code/Resources/AnimationPlayerDoorBehavior.cs
Normal file
49
Code/Resources/AnimationPlayerDoorBehavior.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Code/Resources/AnimationPlayerDoorBehavior.cs.uid
Normal file
1
Code/Resources/AnimationPlayerDoorBehavior.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b8b28akam7skl
|
||||||
16
Code/Resources/DoorBehaviorResource.cs
Normal file
16
Code/Resources/DoorBehaviorResource.cs
Normal 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Code/Resources/DoorBehaviorResource.cs.uid
Normal file
1
Code/Resources/DoorBehaviorResource.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b35aei3jl2524
|
||||||
64
Code/Resources/LerpDoorBehavior.cs
Normal file
64
Code/Resources/LerpDoorBehavior.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Code/Resources/LerpDoorBehavior.cs.uid
Normal file
1
Code/Resources/LerpDoorBehavior.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cratjw4trngpr
|
||||||
@@ -1,10 +1,17 @@
|
|||||||
[gd_scene load_steps=13 format=3 uid="uid://b1d2gc8goj6gx"]
|
[gd_scene load_steps=12 format=3 uid="uid://b1d2gc8goj6gx"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://bxqite0b1di2b" path="res://Code/Presenters/DoorPresenter.cs" id="1_0k8gl"]
|
[ext_resource type="Script" uid="uid://bxqite0b1di2b" path="res://Code/Presenters/DoorPresenter.cs" id="1_0k8gl"]
|
||||||
|
[ext_resource type="Script" uid="uid://cratjw4trngpr" path="res://Code/Resources/LerpDoorBehavior.cs" id="2_3dbp0"]
|
||||||
[ext_resource type="Script" uid="uid://b6x8llipvutqs" path="res://Code/Presenters/SceneEntity.cs" id="2_l5dry"]
|
[ext_resource type="Script" uid="uid://b6x8llipvutqs" path="res://Code/Presenters/SceneEntity.cs" id="2_l5dry"]
|
||||||
[ext_resource type="Script" uid="uid://dnyfoaprv6bhw" path="res://Code/Resources/RequiresItemRequirementResource.cs" id="3_3dbp0"]
|
[ext_resource type="Script" uid="uid://dnyfoaprv6bhw" path="res://Code/Resources/RequiresItemRequirementResource.cs" id="3_3dbp0"]
|
||||||
[ext_resource type="Script" uid="uid://ymtyxkea76mv" path="res://Code/Resources/DoorComponentResource.cs" id="4_g4ryb"]
|
[ext_resource type="Script" uid="uid://ymtyxkea76mv" path="res://Code/Resources/DoorComponentResource.cs" id="4_g4ryb"]
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_3dbp0"]
|
||||||
|
script = ExtResource("2_3dbp0")
|
||||||
|
_nodeToMovePath = NodePath(".")
|
||||||
|
_openRotationDegrees = Vector3(0, 45, 0)
|
||||||
|
metadata/_custom_type_script = "uid://cratjw4trngpr"
|
||||||
|
|
||||||
[sub_resource type="BoxMesh" id="BoxMesh_u2oqr"]
|
[sub_resource type="BoxMesh" id="BoxMesh_u2oqr"]
|
||||||
size = Vector3(1, 2, 0.3)
|
size = Vector3(1, 2, 0.3)
|
||||||
|
|
||||||
@@ -14,42 +21,6 @@ albedo_color = Color(0.14891627, 0.744422, 0, 1)
|
|||||||
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_l5dry"]
|
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_l5dry"]
|
||||||
points = PackedVector3Array(-0.5, -1, -0.15, -0.5, -1, 0.15, -0.5, 1, -0.15, 0.5, -1, -0.15, 0.5, -1, 0.15, -0.5, 1, 0.15, 0.5, 1, -0.15, 0.5, 1, 0.15)
|
points = PackedVector3Array(-0.5, -1, -0.15, -0.5, -1, 0.15, -0.5, 1, -0.15, 0.5, -1, -0.15, 0.5, -1, 0.15, -0.5, 1, 0.15, 0.5, 1, -0.15, 0.5, 1, 0.15)
|
||||||
|
|
||||||
[sub_resource type="Animation" id="Animation_rv1pd"]
|
|
||||||
resource_name = "open"
|
|
||||||
tracks/0/type = "value"
|
|
||||||
tracks/0/imported = false
|
|
||||||
tracks/0/enabled = true
|
|
||||||
tracks/0/path = NodePath(".:position")
|
|
||||||
tracks/0/interp = 1
|
|
||||||
tracks/0/loop_wrap = true
|
|
||||||
tracks/0/keys = {
|
|
||||||
"times": PackedFloat32Array(0, 1),
|
|
||||||
"transitions": PackedFloat32Array(1, 1),
|
|
||||||
"update": 0,
|
|
||||||
"values": [Vector3(0, 0, 0), Vector3(0, 3, 0)]
|
|
||||||
}
|
|
||||||
|
|
||||||
[sub_resource type="Animation" id="Animation_me0pg"]
|
|
||||||
length = 0.001
|
|
||||||
tracks/0/type = "value"
|
|
||||||
tracks/0/imported = false
|
|
||||||
tracks/0/enabled = true
|
|
||||||
tracks/0/path = NodePath(".:position")
|
|
||||||
tracks/0/interp = 1
|
|
||||||
tracks/0/loop_wrap = true
|
|
||||||
tracks/0/keys = {
|
|
||||||
"times": PackedFloat32Array(0),
|
|
||||||
"transitions": PackedFloat32Array(1),
|
|
||||||
"update": 0,
|
|
||||||
"values": [Vector3(0, 0, 0)]
|
|
||||||
}
|
|
||||||
|
|
||||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_dgrt5"]
|
|
||||||
_data = {
|
|
||||||
&"RESET": SubResource("Animation_me0pg"),
|
|
||||||
&"open": SubResource("Animation_rv1pd")
|
|
||||||
}
|
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_g2hal"]
|
[sub_resource type="Resource" id="Resource_g2hal"]
|
||||||
script = ExtResource("3_3dbp0")
|
script = ExtResource("3_3dbp0")
|
||||||
metadata/_custom_type_script = "uid://dnyfoaprv6bhw"
|
metadata/_custom_type_script = "uid://dnyfoaprv6bhw"
|
||||||
@@ -60,11 +31,9 @@ InitialState = 0
|
|||||||
Requirements = Array[Object]([SubResource("Resource_g2hal")])
|
Requirements = Array[Object]([SubResource("Resource_g2hal")])
|
||||||
metadata/_custom_type_script = "uid://ymtyxkea76mv"
|
metadata/_custom_type_script = "uid://ymtyxkea76mv"
|
||||||
|
|
||||||
[node name="GreenDoor" type="AnimatableBody3D" node_paths=PackedStringArray("_animationPlayer")]
|
[node name="GreenDoor" type="CharacterBody3D"]
|
||||||
script = ExtResource("1_0k8gl")
|
script = ExtResource("1_0k8gl")
|
||||||
_animationPlayer = NodePath("AnimationPlayer")
|
_behavior = SubResource("Resource_3dbp0")
|
||||||
_openAnimationName = "open"
|
|
||||||
metadata/_custom_type_script = "uid://bxqite0b1di2b"
|
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||||
mesh = SubResource("BoxMesh_u2oqr")
|
mesh = SubResource("BoxMesh_u2oqr")
|
||||||
@@ -73,11 +42,6 @@ surface_material_override/0 = SubResource("StandardMaterial3D_l4yuh")
|
|||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
shape = SubResource("ConvexPolygonShape3D_l5dry")
|
shape = SubResource("ConvexPolygonShape3D_l5dry")
|
||||||
|
|
||||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
|
||||||
libraries = {
|
|
||||||
&"": SubResource("AnimationLibrary_dgrt5")
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="SceneEntity" type="Node" parent="." groups=["SceneEntities"]]
|
[node name="SceneEntity" type="Node" parent="." groups=["SceneEntities"]]
|
||||||
script = ExtResource("2_l5dry")
|
script = ExtResource("2_l5dry")
|
||||||
ComponentResources = Array[Resource]([SubResource("Resource_fyehb")])
|
ComponentResources = Array[Resource]([SubResource("Resource_fyehb")])
|
||||||
|
|||||||
Reference in New Issue
Block a user