Improved interactions.
- Interactions can now be stopped by both participating Entities. - Player animation now controlled by AnimationTree.WorldChunkRefactoring
parent
22ad86319d
commit
2e7f30e214
|
@ -1,11 +1,47 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
[gd_scene load_steps=12 format=2]
|
||||
|
||||
[ext_resource path="res://assets/Characters/Pirate.glb" type="PackedScene" id=1]
|
||||
[ext_resource path="res://assets/Objects/toolAxe.tscn" type="PackedScene" id=2]
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id=1]
|
||||
animation = "Hit-loop"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id=2]
|
||||
animation = "Idle-loop"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id=3]
|
||||
animation = "Interaction-loop"
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id=4]
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id=5]
|
||||
switch_mode = 2
|
||||
xfade_time = 0.2
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id=6]
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id=7]
|
||||
switch_mode = 2
|
||||
xfade_time = 0.2
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachine" id=8]
|
||||
states/Hit/node = SubResource( 1 )
|
||||
states/Hit/position = Vector2( 415, 45 )
|
||||
states/Idle/node = SubResource( 2 )
|
||||
states/Idle/position = Vector2( 149, 39 )
|
||||
states/Interaction/node = SubResource( 3 )
|
||||
states/Interaction/position = Vector2( 176, 157 )
|
||||
transitions = [ "Idle", "Hit", SubResource( 4 ), "Hit", "Idle", SubResource( 5 ), "Idle", "Interaction", SubResource( 6 ), "Interaction", "Idle", SubResource( 7 ) ]
|
||||
start_node = "Idle"
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachinePlayback" id=9]
|
||||
|
||||
[node name="Pirate" instance=ExtResource( 1 )]
|
||||
transform = Transform( 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0 )
|
||||
|
||||
[node name="Skeleton" parent="Armature" index="0"]
|
||||
bones/4/bound_children = [ NodePath("ToolAttachement") ]
|
||||
|
||||
[node name="ToolAttachement" type="BoneAttachment" parent="Armature/Skeleton" index="5"]
|
||||
transform = Transform( 1, 8.68458e-08, -1.04308e-07, 1.74623e-07, -1, -1.30385e-07, 1.41561e-07, 1.50874e-07, -1, -0.72, 0.45, 3.28113e-08 )
|
||||
visible = false
|
||||
|
@ -15,3 +51,9 @@ bone_name = "HandTip.R"
|
|||
transform = Transform( -1.12419e-14, 8.74228e-08, -2, 2, -8.74228e-08, -1.39841e-13, -8.74228e-08, -2, -8.74228e-08, 2.38419e-07, -0.151768, 0.615043 )
|
||||
|
||||
[node name="toolAxe" parent="Armature/Skeleton/ToolAttachement/Tool" index="0" instance=ExtResource( 2 )]
|
||||
|
||||
[node name="AnimationTree" type="AnimationTree" parent="." index="2"]
|
||||
tree_root = SubResource( 8 )
|
||||
anim_player = NodePath("../AnimationPlayer")
|
||||
active = true
|
||||
parameters/playback = SubResource( 9 )
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using Godot;
|
||||
|
||||
namespace GodotComponentTest.components;
|
||||
|
||||
public class InteractionComponent: Component
|
||||
{
|
||||
[Signal]
|
||||
delegate void InteractionStart(Entity owningEntity, Entity targetEntity);
|
||||
|
||||
[Signal]
|
||||
delegate void InteractionEnd(Entity owningEntity, Entity targetEntity);
|
||||
|
||||
public Entity OwningEntity;
|
||||
public Entity TargetEntity;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using Godot;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using GodotComponentTest.components;
|
||||
using GodotComponentTest.entities;
|
||||
|
||||
public class Chest : Entity, IInteractionInterface
|
||||
|
@ -20,6 +21,13 @@ public class Chest : Entity, IInteractionInterface
|
|||
private MeshInstance _mesh;
|
||||
private AnimationPlayer _animationPlayer;
|
||||
|
||||
private InteractionComponent _interactionComponent;
|
||||
public InteractionComponent InteractionComponent
|
||||
{
|
||||
get => _interactionComponent;
|
||||
set => _interactionComponent = value;
|
||||
}
|
||||
|
||||
[Signal]
|
||||
delegate void EntityClicked(Entity entity);
|
||||
|
||||
|
@ -105,5 +113,10 @@ public class Chest : Entity, IInteractionInterface
|
|||
);
|
||||
GetParent().AddChild(bar);
|
||||
}
|
||||
|
||||
if (_interactionComponent != null)
|
||||
{
|
||||
_interactionComponent.EmitSignal("InteractionEnd");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,11 +65,14 @@ tracks/2/loop_wrap = true
|
|||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/keys = {
|
||||
"times": PoolRealArray( 0.3 ),
|
||||
"transitions": PoolRealArray( 1 ),
|
||||
"times": PoolRealArray( 0.3, 1 ),
|
||||
"transitions": PoolRealArray( 1, 1 ),
|
||||
"values": [ {
|
||||
"args": [ ],
|
||||
"method": "OnChestOpened"
|
||||
}, {
|
||||
"args": [ ],
|
||||
"method": "OnChestOpened"
|
||||
} ]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
using GodotComponentTest.components;
|
||||
|
||||
namespace GodotComponentTest.entities;
|
||||
|
||||
public interface IInteractionInterface
|
||||
{
|
||||
void OnInteractionStart();
|
||||
void OnInteractionEnd();
|
||||
|
||||
InteractionComponent InteractionComponent
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using GodotComponentTest.components;
|
||||
using GodotComponentTest.entities;
|
||||
|
||||
public class Player : Entity, IInteractionInterface
|
||||
|
@ -30,6 +31,13 @@ public class Player : Entity, IInteractionInterface
|
|||
private List<Node> _attractedItemList = new List<Node>();
|
||||
private BoneAttachment _toolAttachement;
|
||||
private AnimationPlayer _playerAnimationPlayer;
|
||||
private AnimationTree _animationTree;
|
||||
private InteractionComponent _interactionComponent;
|
||||
public InteractionComponent InteractionComponent
|
||||
{
|
||||
get => _interactionComponent;
|
||||
set => _interactionComponent = value;
|
||||
}
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
|
@ -61,8 +69,12 @@ public class Player : Entity, IInteractionInterface
|
|||
_itemPickupArea.Connect("body_entered", this, nameof(OnItemPickupAreaBodyEntered));
|
||||
}
|
||||
|
||||
_playerAnimationPlayer = (AnimationPlayer)GetNode<AnimationPlayer>("Geometry/AnimationPlayer");
|
||||
_playerAnimationPlayer = GetNode<AnimationPlayer>("Geometry/AnimationPlayer");
|
||||
Debug.Assert(_playerAnimationPlayer != null);
|
||||
_animationTree = GetNode<AnimationTree>("Geometry/AnimationTree");
|
||||
Debug.Assert(_animationTree != null);
|
||||
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback");
|
||||
stateMachine.Start("Idle");
|
||||
|
||||
_toolAttachement = (BoneAttachment)FindNode("ToolAttachement");
|
||||
if (_toolAttachement == null)
|
||||
|
@ -168,14 +180,25 @@ public class Player : Entity, IInteractionInterface
|
|||
|
||||
public void OnInteractionStart()
|
||||
{
|
||||
GD.Print("Player Starting Interaction");
|
||||
_playerAnimationPlayer.CurrentAnimation = "Hit-loop";
|
||||
_playerAnimationPlayer.Play();
|
||||
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback");
|
||||
Debug.Assert(stateMachine != null);
|
||||
|
||||
if (_interactionComponent.TargetEntity is Chest)
|
||||
{
|
||||
GD.Print("Player Opening Box");
|
||||
stateMachine.Travel("Interaction");
|
||||
} else if (_interactionComponent.TargetEntity is Tree)
|
||||
{
|
||||
GD.Print("Player Chopping Tree");
|
||||
stateMachine.Travel("Hit");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnInteractionEnd()
|
||||
{
|
||||
GD.Print("Player Stopping Interaction");
|
||||
_playerAnimationPlayer.CurrentAnimation = "Idle-loop";
|
||||
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback");
|
||||
Debug.Assert(stateMachine != null);
|
||||
stateMachine.Travel("Idle");
|
||||
}
|
||||
}
|
|
@ -1,17 +1,25 @@
|
|||
using Godot;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using GodotComponentTest.components;
|
||||
using GodotComponentTest.entities;
|
||||
|
||||
public class Tree : StaticBody, IInteractionInterface
|
||||
public class Tree : Entity, IInteractionInterface
|
||||
{
|
||||
[Export] public float ChopDuration = 2;
|
||||
public bool IsMouseOver = false;
|
||||
public bool IsMouseOver;
|
||||
|
||||
private MeshInstance _geometry;
|
||||
private AnimationPlayer _animationPlayer;
|
||||
private float _health = 100;
|
||||
private bool _isBeingChopped = false;
|
||||
private bool _isBeingChopped;
|
||||
|
||||
private InteractionComponent _interactionComponent;
|
||||
public InteractionComponent InteractionComponent
|
||||
{
|
||||
get => _interactionComponent;
|
||||
set => _interactionComponent = value;
|
||||
}
|
||||
|
||||
[Signal]
|
||||
delegate void EntityClicked(Entity entity);
|
||||
|
|
|
@ -50,7 +50,7 @@ tracks/0/imported = false
|
|||
tracks/0/enabled = true
|
||||
tracks/0/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1.5, 1, 1.5, 0.5, 1, 0, 0, 0, 0, 0, 0, 1, 1.5, 0.6, 1.5, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1.5, 1, 1.5 )
|
||||
|
||||
[node name="Tree" type="StaticBody"]
|
||||
[node name="Tree" type="KinematicBody"]
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="Geometry" type="MeshInstance" parent="."]
|
||||
|
|
|
@ -2,6 +2,7 @@ using Godot;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Godot.Collections;
|
||||
using GodotComponentTest.components;
|
||||
using GodotComponentTest.entities;
|
||||
using Array = System.Array;
|
||||
using NodePair = System.Tuple<Godot.Node, Godot.Node>;
|
||||
|
@ -38,6 +39,7 @@ public class InteractionSystem : Node
|
|||
if (interactableB != null)
|
||||
{
|
||||
interactableB.OnInteractionEnd();
|
||||
interactableB.InteractionComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,10 +49,9 @@ public class InteractionSystem : Node
|
|||
if (interactableA != null)
|
||||
{
|
||||
interactableA.OnInteractionEnd();
|
||||
interactableA.InteractionComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
foreach (NodePair pair in invalidInteractionPairs)
|
||||
|
@ -59,21 +60,29 @@ public class InteractionSystem : Node
|
|||
}
|
||||
}
|
||||
|
||||
public void OnStartInteraction(Node nodeA, Node nodeB)
|
||||
public void OnStartInteraction(Entity owningEntity, Entity targetEntity)
|
||||
{
|
||||
IInteractionInterface interactableA = nodeA as IInteractionInterface;
|
||||
if (interactableA != null)
|
||||
{
|
||||
interactableA.OnInteractionStart();
|
||||
}
|
||||
InteractionComponent interactionComponent = new InteractionComponent();
|
||||
interactionComponent.OwningEntity = owningEntity;
|
||||
interactionComponent.TargetEntity = targetEntity;
|
||||
|
||||
ConnectInteractionSignals(owningEntity, interactionComponent);
|
||||
ConnectInteractionSignals(targetEntity, interactionComponent);
|
||||
|
||||
interactionComponent.EmitSignal("InteractionStart");
|
||||
|
||||
IInteractionInterface interactableB = nodeB as IInteractionInterface;
|
||||
if (interactableB != null)
|
||||
{
|
||||
interactableB.OnInteractionStart();
|
||||
}
|
||||
NodePair pair = new NodePair(owningEntity, targetEntity);
|
||||
_interactionPairs.Add(new NodePair(owningEntity, targetEntity));
|
||||
}
|
||||
|
||||
NodePair pair = new NodePair(nodeA, nodeB);
|
||||
_interactionPairs.Add(new NodePair(nodeA, nodeB));
|
||||
private static void ConnectInteractionSignals(Entity entity, InteractionComponent interactionComponent)
|
||||
{
|
||||
IInteractionInterface interactable = entity as IInteractionInterface;
|
||||
if (interactable != null)
|
||||
{
|
||||
interactable.InteractionComponent = interactionComponent;
|
||||
interactionComponent.Connect("InteractionStart", entity, nameof(interactable.OnInteractionStart));
|
||||
interactionComponent.Connect("InteractionEnd", entity, nameof(interactable.OnInteractionEnd));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue