Interaction with Chests!

WorldChunkRefactoring
Martin Felis 2023-02-12 21:10:28 +01:00
parent 48f7081134
commit 3a652ef683
7 changed files with 270 additions and 240 deletions

View File

@ -36,6 +36,41 @@ public class NavigationComponent : Node
WorldOrientation = worldOrientation; WorldOrientation = worldOrientation;
Flags = NavigationFlags.Orientation; Flags = NavigationFlags.Orientation;
} }
public NavigationPoint(Transform worldTransform)
{
WorldPosition = worldTransform.origin;
WorldOrientation = worldTransform.basis.Quat();
Flags = NavigationFlags.Position | NavigationFlags.Orientation;
}
public bool IsReached(Transform worldTransform)
{
bool goalReached = false;
float positionErrorSquared = (worldTransform.origin - WorldPosition).LengthSquared();
float orientationError = Mathf.Abs(worldTransform.basis.Quat().AngleTo(WorldOrientation));
if (Flags.HasFlag(NavigationPoint.NavigationFlags.Position)
&& Flags.HasFlag(NavigationPoint.NavigationFlags.Orientation)
&& positionErrorSquared < Globals.EpsPositionSquared
&& orientationError < Globals.EpsRadians)
{
goalReached = true;
}
else if (Flags.HasFlag(NavigationPoint.NavigationFlags.Position) &&
positionErrorSquared < Globals.EpsPositionSquared)
{
goalReached = true;
}
else if (Flags.HasFlag(NavigationPoint.NavigationFlags.Orientation) &&
orientationError < Globals.EpsRadians)
{
goalReached = true;
}
return goalReached;
}
} }
public TileWorld TileWorld { set; get; } public TileWorld TileWorld { set; get; }
@ -106,6 +141,22 @@ public class NavigationComponent : Node
} }
public void Plan(Transform fromTransformWorld, NavigationPoint navigationPoint)
{
if (navigationPoint.Flags.HasFlag(NavigationPoint.NavigationFlags.Position)
&& navigationPoint.Flags.HasFlag(NavigationPoint.NavigationFlags.Orientation))
{
Plan(fromTransformWorld.origin, navigationPoint.WorldPosition, navigationPoint.WorldOrientation);
} else if (navigationPoint.Flags.HasFlag(NavigationPoint.NavigationFlags.Position))
{
Plan(fromTransformWorld.origin, navigationPoint.WorldPosition);
} else
{
throw new NotImplementedException();
}
}
private void UpdateCurrentGoal() private void UpdateCurrentGoal()
{ {
if (_pathWorldNavigationPoints.Count == 0) if (_pathWorldNavigationPoints.Count == 0)
@ -145,37 +196,8 @@ public class NavigationComponent : Node
{ {
_currentGoalOrientationWorld = currentTransformWorld.basis.Quat(); _currentGoalOrientationWorld = currentTransformWorld.basis.Quat();
} }
Vector3 currentPositionWorld = currentTransformWorld.origin;
Quat currentOrientationWorld = currentTransformWorld.basis.Quat();
Vector2 currentPositionPlane = new Vector2(currentPositionWorld.x, currentPositionWorld.z); if (_currentGoal.IsReached(currentTransformWorld))
Vector2 currentGoalPlane = new Vector2(_currentGoal.WorldPosition.x, _currentGoal.WorldPosition.z);
bool goalReached = false;
float positionErrorSquared = (currentPositionPlane - currentGoalPlane).LengthSquared();
float orientationError = _currentGoalOrientationWorld.AngleTo(currentOrientationWorld);
if (_currentGoal.Flags.HasFlag(NavigationPoint.NavigationFlags.Position)
&& _currentGoal.Flags.HasFlag(NavigationPoint.NavigationFlags.Orientation)
&& positionErrorSquared < Globals.EpsPositionSquared
&& orientationError < Globals.EpsRadians)
{
goalReached = true;
}
else if (_currentGoal.Flags.HasFlag(NavigationPoint.NavigationFlags.Position) &&
positionErrorSquared < Globals.EpsPositionSquared)
{
goalReached = true;
}
else if (_currentGoal.Flags.HasFlag(NavigationPoint.NavigationFlags.Orientation) &&
orientationError < Globals.EpsRadians)
{
goalReached = true;
}
if (goalReached)
{ {
_pathWorldNavigationPoints.RemoveAt(0); _pathWorldNavigationPoints.RemoveAt(0);
UpdateCurrentGoal(); UpdateCurrentGoal();

View File

@ -5,26 +5,46 @@ using System.Diagnostics;
public class TaskQueueComponent : Component public class TaskQueueComponent : Component
{ {
public class Task public abstract class Task
{ {
public abstract bool PerformTask(Entity entity, float delta);
} }
public class NavigationTask : Task public class NavigationTask : Task
{ {
[Flags] public enum Flags public NavigationComponent.NavigationPoint NavigationPoint;
public NavigationTask(NavigationComponent.NavigationPoint navigationPoint)
{ {
Position = 1, NavigationPoint = navigationPoint;
Orientation = 2
} }
public Vector3 TargetPositionWorld = Vector3.Zero; public override bool PerformTask(Entity entity, float delta)
public Quat TargetOrientationWorld = Quat.Identity; {
public Flags NavigationFlags = Flags.Position | Flags.Orientation; return NavigationPoint.IsReached(entity.GlobalTransform);
}
} }
public class InteractionTask : Task public class InteractionTask : Task
{ {
public Entity TargetEntity; public Entity TargetEntity;
public InteractionTask(Entity entity)
{
TargetEntity = entity;
}
public override bool PerformTask(Entity entity, float delta)
{
GD.Print("Interaction of " + entity + " with " + TargetEntity);
if (TargetEntity is Chest)
{
Chest chest = (Chest)TargetEntity;
chest.OnInteract();
}
return true;
}
} }
public Queue<Task> Queue; public Queue<Task> Queue;
@ -39,4 +59,24 @@ public class TaskQueueComponent : Component
{ {
Queue.Clear(); Queue.Clear();
} }
public void Process(Entity entity, float delta)
{
if (Queue.Count == 0)
{
return;
}
Task currentTask = Queue.Peek();
while (currentTask.PerformTask(entity, delta))
{
Queue.Dequeue();
if (Queue.Count == 0)
{
break;
}
currentTask = Queue.Peek();
}
}
} }

View File

@ -7,9 +7,17 @@ public class Chest : Entity
// private int a = 2; // private int a = 2;
// private string b = "text"; // private string b = "text";
public enum LidState
{
Closed,
Open
}
public LidState State = LidState.Closed;
public bool IsMouseOver = false; public bool IsMouseOver = false;
private MeshInstance _mesh; private MeshInstance _mesh;
private SpatialMaterial _previousMaterial; private SpatialMaterial _previousMaterial;
private AnimationPlayer _animationPlayer;
[Signal] [Signal]
delegate void EntityClicked(Entity entity); delegate void EntityClicked(Entity entity);
@ -18,6 +26,7 @@ public class Chest : Entity
public override void _Ready() public override void _Ready()
{ {
_mesh = GetNode<MeshInstance>("Armature/Skeleton/Chest"); _mesh = GetNode<MeshInstance>("Armature/Skeleton/Chest");
_animationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
Connect("input_event", this, nameof(OnAreaInputEvent)); Connect("input_event", this, nameof(OnAreaInputEvent));
Connect("mouse_entered", this, nameof(OnAreaMouseEntered)); Connect("mouse_entered", this, nameof(OnAreaMouseEntered));
@ -38,6 +47,7 @@ public class Chest : Entity
} }
} }
public void OnAreaMouseEntered() public void OnAreaMouseEntered()
{ {
IsMouseOver = true; IsMouseOver = true;
@ -46,9 +56,27 @@ public class Chest : Entity
_mesh.MaterialOverride = overrideMaterial; _mesh.MaterialOverride = overrideMaterial;
} }
public void OnAreaMouseExited() public void OnAreaMouseExited()
{ {
IsMouseOver = false; IsMouseOver = false;
_mesh.MaterialOverride = null; _mesh.MaterialOverride = null;
} }
public void OnInteract()
{
_animationPlayer.Stop();
if (State == LidState.Closed)
{
State = LidState.Open;
_animationPlayer.Play("ChestOpen");
}
else
{
_animationPlayer.PlayBackwards("ChestOpen");
State = LidState.Closed;
}
}
} }

File diff suppressed because one or more lines are too long

View File

@ -50,11 +50,16 @@ public class Player : Entity
if (TaskQueueComponent != null && TaskQueueComponent.Queue.Count > 0) if (TaskQueueComponent != null && TaskQueueComponent.Queue.Count > 0)
{ {
var currentTask = TaskQueueComponent.Queue.Peek(); TaskQueueComponent.Process(this, delta);
if (currentTask is TaskQueueComponent.NavigationTask)
if (TaskQueueComponent.Queue.Count > 0)
{ {
TaskQueueComponent.NavigationTask navigationTask = (TaskQueueComponent.NavigationTask)TaskQueueComponent.Queue.Dequeue(); var currentTask = TaskQueueComponent.Queue.Peek();
if (currentTask is TaskQueueComponent.NavigationTask)
{
TaskQueueComponent.NavigationTask navigationTask = (TaskQueueComponent.NavigationTask)currentTask;
_navigationComponent.Plan(GlobalTransform, navigationTask.NavigationPoint);
}
} }
} }

View File

@ -62,7 +62,7 @@ public class Game : Spatial
_tileWorld = GetNode<TileWorld>("TileWorld"); _tileWorld = GetNode<TileWorld>("TileWorld");
_camera = GetNode<Camera>("Camera"); _camera = GetNode<Camera>("Camera");
_cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation; _cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation;
Debug.Assert(_tileWorld != null); Debug.Assert(_tileWorld != null);
// resources // resources
@ -76,12 +76,12 @@ public class Game : Spatial
// update data // update data
_worldTextureRect.RectSize = _tileWorld.Size; _worldTextureRect.RectSize = _tileWorld.Size;
// connect signals // connect signals
_streamContainerArea.Connect("input_event", this, nameof(OnAreaInputEvent)); _streamContainerArea.Connect("input_event", this, nameof(OnAreaInputEvent));
_streamContainer.Connect("TileClicked", this, nameof(OnTileClicked)); _streamContainer.Connect("TileClicked", this, nameof(OnTileClicked));
_tileWorld.Connect("WorldGenerated", this, nameof(OnWorldGenerated)); _tileWorld.Connect("WorldGenerated", this, nameof(OnWorldGenerated));
// register entity events // register entity events
Array entityNodes = FindNode("Entities").GetChildren(); Array entityNodes = FindNode("Entities").GetChildren();
foreach (Node node in entityNodes) foreach (Node node in entityNodes)
@ -91,7 +91,7 @@ public class Game : Spatial
node.Connect("EntityClicked", this, nameof(OnEntityClicked)); node.Connect("EntityClicked", this, nameof(OnEntityClicked));
} }
} }
// perform dependency injection // perform dependency injection
//_streamContainer.SetWorld(_tileWorld); //_streamContainer.SetWorld(_tileWorld);
WorldInfoComponent worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo"); WorldInfoComponent worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo");
@ -99,7 +99,7 @@ public class Game : Spatial
{ {
worldInfoComponent.SetWorld(_tileWorld); worldInfoComponent.SetWorld(_tileWorld);
} }
_tileWorld.Generate(); _tileWorld.Generate();
UpdateCurrentTile(); UpdateCurrentTile();
_streamContainer.SetCenterTile(_currentTile); _streamContainer.SetCenterTile(_currentTile);
@ -139,7 +139,6 @@ public class Game : Spatial
} }
public override void _Process(float delta) public override void _Process(float delta)
{ {
_framesPerSecondLabel.Text = Engine.GetFramesPerSecond().ToString(); _framesPerSecondLabel.Text = Engine.GetFramesPerSecond().ToString();
@ -181,7 +180,7 @@ public class Game : Spatial
_mouseTileLabel.Text = cellAtCursor.OffsetCoords.ToString(); _mouseTileLabel.Text = cellAtCursor.OffsetCoords.ToString();
_mouseTileHighlight.Transform = highlightTransform; _mouseTileHighlight.Transform = highlightTransform;
if (inputEvent is InputEventMouseButton && ((InputEventMouseButton) inputEvent).Pressed) if (inputEvent is InputEventMouseButton && ((InputEventMouseButton)inputEvent).Pressed)
{ {
_streamContainer.EmitSignal("TileClicked", _streamContainer.GetTile3dAt(cellAtCursor.OffsetCoords)); _streamContainer.EmitSignal("TileClicked", _streamContainer.GetTile3dAt(cellAtCursor.OffsetCoords));
} }
@ -195,12 +194,9 @@ public class Game : Spatial
return; return;
} }
if (_player.Navigation == null) _player.TaskQueueComponent.Reset();
{ _player.TaskQueueComponent.Queue.Enqueue(new TaskQueueComponent.NavigationTask(
return; new NavigationComponent.NavigationPoint(tile.GlobalTranslation)));
}
_player.Navigation.Plan(_player.GlobalTranslation, tile.GlobalTranslation);
} }
@ -211,8 +207,10 @@ public class Game : Spatial
Spatial mountPoint = (Spatial)entity.FindNode("MountPoint"); Spatial mountPoint = (Spatial)entity.FindNode("MountPoint");
if (mountPoint != null) if (mountPoint != null)
{ {
GD.Print("Mount point!"); _player.TaskQueueComponent.Reset();
_player.Navigation.Plan(_player.GlobalTranslation, mountPoint.GlobalTranslation, mountPoint.GlobalTransform.basis.Quat()); _player.TaskQueueComponent.Queue.Enqueue(new TaskQueueComponent.NavigationTask(
new NavigationComponent.NavigationPoint(mountPoint.GlobalTransform)));
_player.TaskQueueComponent.Queue.Enqueue(new TaskQueueComponent.InteractionTask(entity));
} }
} }
@ -221,7 +219,7 @@ public class Game : Spatial
{ {
GD.Print("Using new map"); GD.Print("Using new map");
ImageTexture new_world_texture = new ImageTexture(); ImageTexture new_world_texture = new ImageTexture();
_tileWorld.Heightmap.Unlock(); _tileWorld.Heightmap.Unlock();
new_world_texture.CreateFromImage(_tileWorld.Heightmap); new_world_texture.CreateFromImage(_tileWorld.Heightmap);
_tileWorld.Heightmap.Lock(); _tileWorld.Heightmap.Lock();

File diff suppressed because one or more lines are too long