Interaction with Chests!
parent
48f7081134
commit
3a652ef683
|
@ -36,6 +36,41 @@ public class NavigationComponent : Node
|
|||
WorldOrientation = worldOrientation;
|
||||
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; }
|
||||
|
@ -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()
|
||||
{
|
||||
if (_pathWorldNavigationPoints.Count == 0)
|
||||
|
@ -145,37 +196,8 @@ public class NavigationComponent : Node
|
|||
{
|
||||
_currentGoalOrientationWorld = currentTransformWorld.basis.Quat();
|
||||
}
|
||||
|
||||
Vector3 currentPositionWorld = currentTransformWorld.origin;
|
||||
Quat currentOrientationWorld = currentTransformWorld.basis.Quat();
|
||||
|
||||
Vector2 currentPositionPlane = new Vector2(currentPositionWorld.x, currentPositionWorld.z);
|
||||
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)
|
||||
if (_currentGoal.IsReached(currentTransformWorld))
|
||||
{
|
||||
_pathWorldNavigationPoints.RemoveAt(0);
|
||||
UpdateCurrentGoal();
|
||||
|
|
|
@ -5,26 +5,46 @@ using System.Diagnostics;
|
|||
|
||||
public class TaskQueueComponent : Component
|
||||
{
|
||||
public class Task
|
||||
public abstract class Task
|
||||
{
|
||||
public abstract bool PerformTask(Entity entity, float delta);
|
||||
}
|
||||
|
||||
public class NavigationTask : Task
|
||||
{
|
||||
[Flags] public enum Flags
|
||||
public NavigationComponent.NavigationPoint NavigationPoint;
|
||||
|
||||
public NavigationTask(NavigationComponent.NavigationPoint navigationPoint)
|
||||
{
|
||||
Position = 1,
|
||||
Orientation = 2
|
||||
NavigationPoint = navigationPoint;
|
||||
}
|
||||
|
||||
public Vector3 TargetPositionWorld = Vector3.Zero;
|
||||
public Quat TargetOrientationWorld = Quat.Identity;
|
||||
public Flags NavigationFlags = Flags.Position | Flags.Orientation;
|
||||
public override bool PerformTask(Entity entity, float delta)
|
||||
{
|
||||
return NavigationPoint.IsReached(entity.GlobalTransform);
|
||||
}
|
||||
}
|
||||
|
||||
public class InteractionTask : Task
|
||||
{
|
||||
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;
|
||||
|
@ -39,4 +59,24 @@ public class TaskQueueComponent : Component
|
|||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,9 +7,17 @@ public class Chest : Entity
|
|||
// private int a = 2;
|
||||
// private string b = "text";
|
||||
|
||||
public enum LidState
|
||||
{
|
||||
Closed,
|
||||
Open
|
||||
}
|
||||
|
||||
public LidState State = LidState.Closed;
|
||||
public bool IsMouseOver = false;
|
||||
private MeshInstance _mesh;
|
||||
private SpatialMaterial _previousMaterial;
|
||||
private AnimationPlayer _animationPlayer;
|
||||
|
||||
[Signal]
|
||||
delegate void EntityClicked(Entity entity);
|
||||
|
@ -18,6 +26,7 @@ public class Chest : Entity
|
|||
public override void _Ready()
|
||||
{
|
||||
_mesh = GetNode<MeshInstance>("Armature/Skeleton/Chest");
|
||||
_animationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
|
||||
|
||||
Connect("input_event", this, nameof(OnAreaInputEvent));
|
||||
Connect("mouse_entered", this, nameof(OnAreaMouseEntered));
|
||||
|
@ -38,6 +47,7 @@ public class Chest : Entity
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnAreaMouseEntered()
|
||||
{
|
||||
IsMouseOver = true;
|
||||
|
@ -46,9 +56,27 @@ public class Chest : Entity
|
|||
_mesh.MaterialOverride = overrideMaterial;
|
||||
}
|
||||
|
||||
|
||||
public void OnAreaMouseExited()
|
||||
{
|
||||
IsMouseOver = false;
|
||||
_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
|
@ -50,11 +50,16 @@ public class Player : Entity
|
|||
|
||||
if (TaskQueueComponent != null && TaskQueueComponent.Queue.Count > 0)
|
||||
{
|
||||
var currentTask = TaskQueueComponent.Queue.Peek();
|
||||
if (currentTask is TaskQueueComponent.NavigationTask)
|
||||
TaskQueueComponent.Process(this, delta);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ public class Game : Spatial
|
|||
_tileWorld = GetNode<TileWorld>("TileWorld");
|
||||
_camera = GetNode<Camera>("Camera");
|
||||
_cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation;
|
||||
|
||||
|
||||
Debug.Assert(_tileWorld != null);
|
||||
|
||||
// resources
|
||||
|
@ -76,12 +76,12 @@ public class Game : Spatial
|
|||
|
||||
// update data
|
||||
_worldTextureRect.RectSize = _tileWorld.Size;
|
||||
|
||||
|
||||
// connect signals
|
||||
_streamContainerArea.Connect("input_event", this, nameof(OnAreaInputEvent));
|
||||
_streamContainer.Connect("TileClicked", this, nameof(OnTileClicked));
|
||||
_tileWorld.Connect("WorldGenerated", this, nameof(OnWorldGenerated));
|
||||
|
||||
|
||||
// register entity events
|
||||
Array entityNodes = FindNode("Entities").GetChildren();
|
||||
foreach (Node node in entityNodes)
|
||||
|
@ -91,7 +91,7 @@ public class Game : Spatial
|
|||
node.Connect("EntityClicked", this, nameof(OnEntityClicked));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// perform dependency injection
|
||||
//_streamContainer.SetWorld(_tileWorld);
|
||||
WorldInfoComponent worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo");
|
||||
|
@ -99,7 +99,7 @@ public class Game : Spatial
|
|||
{
|
||||
worldInfoComponent.SetWorld(_tileWorld);
|
||||
}
|
||||
|
||||
|
||||
_tileWorld.Generate();
|
||||
UpdateCurrentTile();
|
||||
_streamContainer.SetCenterTile(_currentTile);
|
||||
|
@ -139,7 +139,6 @@ public class Game : Spatial
|
|||
}
|
||||
|
||||
|
||||
|
||||
public override void _Process(float delta)
|
||||
{
|
||||
_framesPerSecondLabel.Text = Engine.GetFramesPerSecond().ToString();
|
||||
|
@ -181,7 +180,7 @@ public class Game : Spatial
|
|||
_mouseTileLabel.Text = cellAtCursor.OffsetCoords.ToString();
|
||||
_mouseTileHighlight.Transform = highlightTransform;
|
||||
|
||||
if (inputEvent is InputEventMouseButton && ((InputEventMouseButton) inputEvent).Pressed)
|
||||
if (inputEvent is InputEventMouseButton && ((InputEventMouseButton)inputEvent).Pressed)
|
||||
{
|
||||
_streamContainer.EmitSignal("TileClicked", _streamContainer.GetTile3dAt(cellAtCursor.OffsetCoords));
|
||||
}
|
||||
|
@ -195,12 +194,9 @@ public class Game : Spatial
|
|||
return;
|
||||
}
|
||||
|
||||
if (_player.Navigation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_player.Navigation.Plan(_player.GlobalTranslation, tile.GlobalTranslation);
|
||||
_player.TaskQueueComponent.Reset();
|
||||
_player.TaskQueueComponent.Queue.Enqueue(new TaskQueueComponent.NavigationTask(
|
||||
new NavigationComponent.NavigationPoint(tile.GlobalTranslation)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -211,8 +207,10 @@ public class Game : Spatial
|
|||
Spatial mountPoint = (Spatial)entity.FindNode("MountPoint");
|
||||
if (mountPoint != null)
|
||||
{
|
||||
GD.Print("Mount point!");
|
||||
_player.Navigation.Plan(_player.GlobalTranslation, mountPoint.GlobalTranslation, mountPoint.GlobalTransform.basis.Quat());
|
||||
_player.TaskQueueComponent.Reset();
|
||||
_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");
|
||||
ImageTexture new_world_texture = new ImageTexture();
|
||||
|
||||
|
||||
_tileWorld.Heightmap.Unlock();
|
||||
new_world_texture.CreateFromImage(_tileWorld.Heightmap);
|
||||
_tileWorld.Heightmap.Lock();
|
||||
|
|
185
scenes/Game.tscn
185
scenes/Game.tscn
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue