Some improvements with path smoothing and interactions.

WorldChunkRefactoring
Martin Felis 2023-08-28 18:22:28 +02:00
parent d61ef6ba45
commit 39f20c8e01
2 changed files with 70 additions and 37 deletions

View File

@ -98,6 +98,23 @@ public class NavigationComponent : Spatial
{ {
Debug.Assert(TileWorld != null); Debug.Assert(TileWorld != null);
} }
public void PlanSmoothedPath(KinematicBody body, Transform fromTransformWorld, NavigationPoint navigationPoint)
{
if (navigationPoint.Flags.HasFlag(NavigationPoint.NavigationFlags.Position)
&& navigationPoint.Flags.HasFlag(NavigationPoint.NavigationFlags.Orientation))
{
FindPath(body, fromTransformWorld.origin, navigationPoint);
}
else if (navigationPoint.Flags.HasFlag(NavigationPoint.NavigationFlags.Position))
{
FindPath(body, fromTransformWorld.origin, navigationPoint.WorldPosition);
}
else
{
throw new NotImplementedException();
}
}
public void FindPath(KinematicBody body, Vector3 fromPositionWorld, Vector3 toPositionWorld) public void FindPath(KinematicBody body, Vector3 fromPositionWorld, Vector3 toPositionWorld)
{ {
@ -124,26 +141,34 @@ public class NavigationComponent : Spatial
} }
List<HexCell> path = TileWorld.HexGrid.FindPath(fromCell, toCell); List<HexCell> path = TileWorld.HexGrid.FindPath(fromCell, toCell);
// GD.Print("Planning path and have " + TileWorld.HexGrid.Obstacles.Count + " obstacles:"); // Generate grid navigation points
// GD.Print(TileWorld.HexGrid.Obstacles);
// foreach (Vector2 coord in TileWorld.HexGrid.Obstacles.Keys)
// {
// HexCell cell = new HexCell(coord);
// GD.Print(" " + cell.OffsetCoords);
// }
_planningPathWorldNavigationPoints = new List<NavigationPoint>(); _planningPathWorldNavigationPoints = new List<NavigationPoint>();
foreach (int index in Enumerable.Range(0, path.Count)) foreach (int index in Enumerable.Range(0, path.Count))
{ {
// GD.Print("Step " + index + ": " + path[index].OffsetCoords);
_planningPathWorldNavigationPoints.Add( _planningPathWorldNavigationPoints.Add(
new NavigationPoint(TileWorld.GetHexCenterFromOffset(path[index].OffsetCoords))); new NavigationPoint(TileWorld.GetHexCenterFromOffset(path[index].OffsetCoords)));
} }
// Ensure the last point coincides with the target position
if ((_planningPathWorldNavigationPoints.Last().WorldPosition - toPositionWorld).LengthSquared() <
0.5f * 0.5f)
{
_planningPathWorldNavigationPoints[_planningPathWorldNavigationPoints.Count - 1].WorldPosition = toPositionWorld;
}
// Perform smoothing
_planningPathSmoothedWorldNavigationPoints = SmoothPath(body, _planningPathWorldNavigationPoints); _planningPathSmoothedWorldNavigationPoints = SmoothPath(body, _planningPathWorldNavigationPoints);
} }
public void FindPath(KinematicBody body, Vector3 fromPositionWorld, NavigationPoint navigationPoint)
{
FindPath(body, fromPositionWorld, navigationPoint.WorldPosition);
_planningPathWorldNavigationPoints[_planningPathWorldNavigationPoints.Count - 1] = navigationPoint;
_planningPathSmoothedWorldNavigationPoints[_planningPathSmoothedWorldNavigationPoints.Count - 1] = navigationPoint;
}
public void PlanGridPath(KinematicBody body, Vector3 fromPositionWorld, Vector3 toPositionWorld) public void PlanGridPath(KinematicBody body, Vector3 fromPositionWorld, Vector3 toPositionWorld)
{ {
Vector2 fromPositionOffset = TileWorld.WorldToOffsetCoords(fromPositionWorld); Vector2 fromPositionOffset = TileWorld.WorldToOffsetCoords(fromPositionWorld);

View File

@ -11,11 +11,11 @@ public class Player : Entity, IInteractionInterface
{ {
// public members // public members
[Export] public NodePath TileWorldNode; [Export] public NodePath TileWorldNode;
public int GoldCount = 0; public int GoldCount = 0;
public TaskQueueComponent TaskQueueComponent; public TaskQueueComponent TaskQueueComponent;
public NavigationComponent Navigation public NavigationComponent Navigation
{ {
get { return _navigationComponent; } get { return _navigationComponent; }
@ -23,7 +23,7 @@ public class Player : Entity, IInteractionInterface
[Signal] [Signal]
delegate void GoldCountChanged(int goldCount); delegate void GoldCountChanged(int goldCount);
// private members // private members
private WorldInfoComponent _worldInfo; private WorldInfoComponent _worldInfo;
private GroundMotionComponent _groundMotion; private GroundMotionComponent _groundMotion;
@ -36,6 +36,7 @@ public class Player : Entity, IInteractionInterface
private AnimationTree _animationTree; private AnimationTree _animationTree;
private DebugGeometry _debugGeometry; private DebugGeometry _debugGeometry;
private InteractionComponent _interactionComponent; private InteractionComponent _interactionComponent;
public InteractionComponent InteractionComponent public InteractionComponent InteractionComponent
{ {
get => _interactionComponent; get => _interactionComponent;
@ -50,7 +51,7 @@ public class Player : Entity, IInteractionInterface
_navigationComponent = (NavigationComponent)FindNode("Navigation", false); _navigationComponent = (NavigationComponent)FindNode("Navigation", false);
_navigationComponent.TileWorld = GetNode<TileWorld>(TileWorldNode); _navigationComponent.TileWorld = GetNode<TileWorld>(TileWorldNode);
TaskQueueComponent = new TaskQueueComponent(); TaskQueueComponent = new TaskQueueComponent();
_itemAttractorArea = (Area)FindNode("ItemAttractorArea", false); _itemAttractorArea = (Area)FindNode("ItemAttractorArea", false);
if (_itemAttractorArea == null) if (_itemAttractorArea == null)
{ {
@ -61,7 +62,7 @@ public class Player : Entity, IInteractionInterface
_itemAttractorArea.Connect("body_entered", this, nameof(OnItemAttractorBodyEntered)); _itemAttractorArea.Connect("body_entered", this, nameof(OnItemAttractorBodyEntered));
_itemAttractorArea.Connect("body_exited", this, nameof(OnItemAttractorBodyExited)); _itemAttractorArea.Connect("body_exited", this, nameof(OnItemAttractorBodyExited));
} }
_itemPickupArea = (Area)FindNode("ItemPickupArea", false); _itemPickupArea = (Area)FindNode("ItemPickupArea", false);
if (_itemPickupArea == null) if (_itemPickupArea == null)
{ {
@ -76,9 +77,10 @@ public class Player : Entity, IInteractionInterface
Debug.Assert(_playerAnimationPlayer != null); Debug.Assert(_playerAnimationPlayer != null);
_animationTree = GetNode<AnimationTree>("Geometry/AnimationTree"); _animationTree = GetNode<AnimationTree>("Geometry/AnimationTree");
Debug.Assert(_animationTree != null); Debug.Assert(_animationTree != null);
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback"); AnimationNodeStateMachinePlayback stateMachine =
(AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback");
stateMachine.Start("Idle"); stateMachine.Start("Idle");
_toolAttachement = (BoneAttachment)FindNode("ToolAttachement"); _toolAttachement = (BoneAttachment)FindNode("ToolAttachement");
if (_toolAttachement == null) if (_toolAttachement == null)
{ {
@ -97,7 +99,7 @@ public class Player : Entity, IInteractionInterface
{ {
return; return;
} }
if (TaskQueueComponent != null && TaskQueueComponent.Queue.Count > 0) if (TaskQueueComponent != null && TaskQueueComponent.Queue.Count > 0)
{ {
TaskQueueComponent.Process(this, delta); TaskQueueComponent.Process(this, delta);
@ -109,13 +111,15 @@ public class Player : Entity, IInteractionInterface
if (navigationTask != null && navigationTask.PlanningComplete == false) if (navigationTask != null && navigationTask.PlanningComplete == false)
{ {
// _navigationComponent.PlanGridPath(this, GlobalTransform, navigationTask.NavigationPoint); // _navigationComponent.PlanGridPath(this, GlobalTransform, navigationTask.NavigationPoint);
_navigationComponent.FindPath(this, GlobalTranslation, navigationTask.NavigationPoint.WorldPosition); _navigationComponent.PlanSmoothedPath(this, GlobalTransform, navigationTask.NavigationPoint);
_navigationComponent.ActivatePlannedPath(); _navigationComponent.ActivatePlannedPath();
navigationTask.PlanningComplete = true; navigationTask.PlanningComplete = true;
} }
_navigationComponent.UpdateCurrentGoal(GlobalTransform); _navigationComponent.UpdateCurrentGoal(GlobalTransform);
_groundMotion.PhysicsProcess(delta, this, _navigationComponent.CurrentGoalPositionWorld, _navigationComponent.CurrentGoalOrientationWorld, _worldInfo.TileWorld); _groundMotion.PhysicsProcess(delta, this, _navigationComponent.CurrentGoalPositionWorld,
_navigationComponent.CurrentGoalOrientationWorld, _worldInfo.TileWorld);
} }
} }
} }
@ -127,16 +131,16 @@ public class Player : Entity, IInteractionInterface
{ {
_navigationComponent.UpdateCurrentGoal(GlobalTransform); _navigationComponent.UpdateCurrentGoal(GlobalTransform);
} }
foreach (Node node in _attractedItemList) foreach (Node node in _attractedItemList)
{ {
if (node is GoldBar) if (node is GoldBar)
{ {
GoldBar bar = (GoldBar)node; GoldBar bar = (GoldBar)node;
bar.SetTarget(GlobalTransform.origin); bar.SetTarget(GlobalTransform.origin);
} }
} }
UpdateDebugGeometry(); UpdateDebugGeometry();
} }
@ -146,16 +150,15 @@ public class Player : Entity, IInteractionInterface
{ {
return; return;
} }
_debugGeometry.Clear(); _debugGeometry.Clear();
_debugGeometry.GlobalTransform = Transform.Identity; _debugGeometry.GlobalTransform = Transform.Identity;
if (_navigationComponent != null) if (_navigationComponent != null)
{ {
_navigationComponent.DebugDraw(this, _debugGeometry); _navigationComponent.DebugDraw(this, _debugGeometry);
return; return;
} }
} }
public void OnItemAttractorBodyEntered(Node node) public void OnItemAttractorBodyEntered(Node node)
@ -163,16 +166,17 @@ public class Player : Entity, IInteractionInterface
GD.Print("Item entered " + node); GD.Print("Item entered " + node);
_attractedItemList.Add(node); _attractedItemList.Add(node);
} }
public void OnItemAttractorBodyExited(Node node) public void OnItemAttractorBodyExited(Node node)
{ {
GD.Print("Item exited " + node); GD.Print("Item exited " + node);
if (node is GoldBar) if (node is GoldBar)
{ {
GoldBar bar = (GoldBar)node; GoldBar bar = (GoldBar)node;
bar.UnsetTarget(); bar.UnsetTarget();
} }
_attractedItemList.Remove(node); _attractedItemList.Remove(node);
} }
@ -190,7 +194,7 @@ public class Player : Entity, IInteractionInterface
GoldCount++; GoldCount++;
EmitSignal("GoldCountChanged", GoldCount); EmitSignal("GoldCountChanged", GoldCount);
} }
body.QueueFree(); body.QueueFree();
} }
@ -200,7 +204,8 @@ public class Player : Entity, IInteractionInterface
if (toolName == "Axe") if (toolName == "Axe")
{ {
_toolAttachement.Visible = true; _toolAttachement.Visible = true;
} else if (toolName == "") }
else if (toolName == "")
{ {
_toolAttachement.Visible = false; _toolAttachement.Visible = false;
} }
@ -208,14 +213,16 @@ public class Player : Entity, IInteractionInterface
public void OnInteractionStart() public void OnInteractionStart()
{ {
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback"); AnimationNodeStateMachinePlayback stateMachine =
(AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback");
Debug.Assert(stateMachine != null); Debug.Assert(stateMachine != null);
if (_interactionComponent.TargetEntity is Chest) if (_interactionComponent.TargetEntity is Chest)
{ {
GD.Print("Player Opening Box"); GD.Print("Player Opening Box");
stateMachine.Travel("Interaction"); stateMachine.Travel("Interaction");
} else if (_interactionComponent.TargetEntity is Tree) }
else if (_interactionComponent.TargetEntity is Tree)
{ {
GD.Print("Player Chopping Tree"); GD.Print("Player Chopping Tree");
stateMachine.Travel("Hit"); stateMachine.Travel("Hit");
@ -223,9 +230,10 @@ public class Player : Entity, IInteractionInterface
} }
public void OnInteractionEnd() public void OnInteractionEnd()
{ {
GD.Print("Player Stopping Interaction"); GD.Print("Player Stopping Interaction");
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback"); AnimationNodeStateMachinePlayback stateMachine =
(AnimationNodeStateMachinePlayback)_animationTree.Get("parameters/playback");
Debug.Assert(stateMachine != null); Debug.Assert(stateMachine != null);
stateMachine.Travel("Idle"); stateMachine.Travel("Idle");
} }