Interaction with Chests!
parent
48f7081134
commit
3a652ef683
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
185
scenes/Game.tscn
185
scenes/Game.tscn
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue