Vastly improved interactivity, wired up some animations.

WorldChunkRefactoring
Martin Felis 2023-06-23 15:39:07 +02:00
parent 2663b469fc
commit c982ec783c
33 changed files with 1603 additions and 103 deletions

View File

@ -19,6 +19,18 @@
</ItemGroup>
<ItemGroup>
<Content Include="entities\Axe.gd" />
<Content Include="entities\Axe.tscn" />
<Content Include="entities\Chest.tscn" />
<Content Include="entities\GoldBar.tscn" />
<Content Include="entities\Player3D.tscn" />
<Content Include="entities\PlayerEntity.gd" />
<Content Include="entities\PlayerEntity.tscn" />
<Content Include="entities\SimpleEntity.gd" />
<Content Include="entities\SimpleEntity.tscn" />
<Content Include="entities\Tree.tscn" />
<Content Include="entities\WanderingEntity.gd" />
<Content Include="entities\WanderingEntity.tscn" />
<Content Include="scenes\Tests\HexTile3DMaterialAssign.tscn" />
</ItemGroup>
</Project>

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
[gd_scene load_steps=3 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]
[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="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
bone_name = "HandTip.R"
[node name="Tool" type="Spatial" parent="Armature/Skeleton/ToolAttachement" index="0"]
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 )]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,18 +0,0 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://assets/KenneySurvivalKit/Models/tree.glb" type="PackedScene" id=1]
[sub_resource type="CapsuleShape" id=1]
radius = 0.329139
height = 0.936801
[node name="tree" instance=ExtResource( 1 )]
[node name="tree" parent="." index="0"]
transform = Transform( 1.5, 0, 0, 0, 1, 0, 0, 0, 1.5, 0, 0, 0 )
[node name="StaticBody" type="StaticBody" parent="." index="1"]
[node name="CollisionShape" type="CollisionShape" parent="StaticBody" index="0"]
transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.519998, 0 )
shape = SubResource( 1 )

View File

@ -5,4 +5,4 @@
[node name="toolAxe" instance=ExtResource( 1 )]
[node name="toolAxe" parent="." index="0"]
transform = Transform( 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0 )
transform = Transform( 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0 )

View File

@ -2,11 +2,20 @@ using Godot;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using GodotComponentTest.entities;
using Object = Godot.Object;
public class TaskQueueComponent : Component
{
public abstract class Task
[Signal]
delegate void StartInteraction(Entity entity, Entity targetEntity);
public abstract class Task : Object
{
/// <summary>
/// Executes a Task on the specified entity.
/// </summary>
/// <returns>true when the Task is complete, false otherwise</returns>
public abstract bool PerformTask(Entity entity, float delta);
}
@ -36,13 +45,6 @@ public class TaskQueueComponent : Component
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;
}
}
@ -52,6 +54,7 @@ public class TaskQueueComponent : Component
public TaskQueueComponent()
{
Queue = new Queue<Task>();
Reset();
}
@ -67,25 +70,23 @@ public class TaskQueueComponent : Component
return;
}
Task currentTask = Queue.Peek();
while (currentTask.PerformTask(entity, delta))
do
{
Queue.Dequeue();
if (Queue.Count == 0)
Task currentTask = Queue.Peek();
InteractionTask interactionTask = currentTask as InteractionTask;
if (interactionTask != null)
{
EmitSignal("StartInteraction", entity, interactionTask.TargetEntity);
}
if (currentTask.PerformTask(entity, delta))
{
Queue.Dequeue();
}
else
{
break;
}
currentTask = Queue.Peek();
if (currentTask is NavigationTask)
{
NavigationTask navigationTask = (NavigationTask)currentTask;
if (navigationTask != null && navigationTask.NavigationPoint.Flags ==
NavigationComponent.NavigationPoint.NavigationFlags.Orientation)
{
GD.Print("Current task is orientation task!");
}
}
}
} while (Queue.Count > 0);
}
}

11
entities/Axe.cs Normal file
View File

@ -0,0 +1,11 @@
using Godot;
using System;
public class Axe : StaticBody
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
}
}

16
entities/Axe.gd Normal file
View File

@ -0,0 +1,16 @@
extends StaticBody
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

20
entities/Axe.tscn Normal file
View File

@ -0,0 +1,20 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://assets/Objects/toolAxe.tscn" type="PackedScene" id=1]
[ext_resource path="res://entities/Axe.cs" type="Script" id=2]
[sub_resource type="CylinderShape" id=1]
height = 0.846435
radius = 0.687167
[node name="Axe" type="StaticBody"]
collision_layer = 9
collision_mask = 0
script = ExtResource( 2 )
[node name="CollisionShape" type="CollisionShape" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.428358, 0 )
shape = SubResource( 1 )
[node name="toolAxe" parent="." instance=ExtResource( 1 )]
transform = Transform( 0.707107, 0.707107, -3.09086e-08, 4.37114e-08, 1.91069e-15, 1, 0.707107, -0.707107, -3.09086e-08, -0.323064, 0.0760467, 0.348457 )

View File

@ -1,8 +1,9 @@
using Godot;
using System;
using System.Linq;
using GodotComponentTest.entities;
public class Chest : Entity
public class Chest : Entity, IInteractionInterface
{
// resources
private PackedScene _goldBarScene = GD.Load<PackedScene>("res://entities/GoldBar.tscn");
@ -15,6 +16,7 @@ public class Chest : Entity
public LidState State = LidState.Closed;
public bool IsMouseOver = false;
private MeshInstance _mesh;
private AnimationPlayer _animationPlayer;
@ -27,7 +29,7 @@ public class Chest : Entity
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_mesh = GetNode<MeshInstance>("Armature/Skeleton/Chest");
_mesh = GetNode<MeshInstance>("Geometry/Skeleton/Chest");
_animationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
Connect("input_event", this, nameof(OnAreaInputEvent));
@ -67,7 +69,7 @@ public class Chest : Entity
}
public void OnInteract()
public void OnInteractionStart()
{
_animationPlayer.Stop();
@ -83,6 +85,12 @@ public class Chest : Entity
}
}
public void OnInteractionEnd()
{
}
public void OnChestOpened()
{
GD.Print("Chest now opened!");

View File

@ -45,14 +45,14 @@ bind/1/pose = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.693102, -1.13623, -1.5266
resource_name = "ChestOpen"
length = 0.333333
tracks/0/type = "transform"
tracks/0/path = NodePath("Armature/Skeleton:Lid")
tracks/0/path = NodePath("Geometry/Skeleton:Lid")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.0666667, 1, 0, 0, 0, 0, 0, -0.079364, 0.996846, 1, 1, 1, 0.133333, 1, 0, 0, 0, 0, 0, -0.489957, 0.871747, 1, 1, 1, 0.2, 1, 0, 0, 0, 0, 0, -0.855809, 0.517292, 1, 1, 1, 0.266667, 1, 2.37487e-08, 0, 0, 4.03449e-08, -3.99897e-08, 0.919654, -0.39273, 1, 1, 1, 0.333333, 1, 0, 0, 0, -1.45046e-08, 1.43769e-08, -0.808978, 0.587839, 1, 1, 1 )
tracks/1/type = "transform"
tracks/1/path = NodePath("Armature/Skeleton:Body")
tracks/1/path = NodePath("Geometry/Skeleton:Body")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
@ -83,10 +83,10 @@ extents = Vector3( 0.19, 0.19, 0.332 )
[node name="Chest" type="KinematicBody"]
script = ExtResource( 1 )
[node name="Armature" type="Spatial" parent="."]
[node name="Geometry" type="Spatial" parent="."]
transform = Transform( -0.259808, 0, 0.15, 0, 0.3, 0, -0.15, 0, -0.259808, 0, 0, 0 )
[node name="Skeleton" type="Skeleton" parent="Armature"]
[node name="Skeleton" type="Skeleton" parent="Geometry"]
bones/0/name = "Body"
bones/0/parent = -1
bones/0/rest = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.697618, -0.0422799, -5.68067e-09 )
@ -98,15 +98,13 @@ bones/1/rest = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00451577, 1.17851, 1.583
bones/1/enabled = true
bones/1/bound_children = [ ]
[node name="Chest" type="MeshInstance" parent="Armature/Skeleton"]
[node name="Chest" type="MeshInstance" parent="Geometry/Skeleton"]
mesh = SubResource( 12 )
skin = SubResource( 13 )
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
anims/ChestOpen = SubResource( 3 )
[node name="State" type="Node" parent="."]
[node name="MountPoint" type="Spatial" parent="."]
transform = Transform( -0.524001, 0, -0.851718, 0, 1, 0, 0.851718, 0, -0.524001, 0.717306, 0, 0.400936 )

View File

@ -42,16 +42,16 @@ public class GoldBar : KinematicBody
}
else
{
if (Mathf.Abs(Transform.origin.y) < 0.01)
{
// apply damping when on ground
velocity = velocity - velocity.Normalized() * 0.9f * delta;
}
velocity.y = velocity.y - 9.81f * delta;
}
velocity = MoveAndSlide(velocity);
velocity = MoveAndSlide(velocity, Vector3.Up);
if (IsOnFloor() || Mathf.Abs(Transform.origin.y) < 0.01)
{
// apply damping when on ground
velocity = velocity - velocity.Normalized() * 0.9f * delta;
}
if (velocity.LengthSquared() < 0.01)
{

View File

@ -0,0 +1,7 @@
namespace GodotComponentTest.entities;
public interface IInteractionInterface
{
void OnInteractionStart();
void OnInteractionEnd();
}

View File

@ -1,12 +1,15 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using GodotComponentTest.entities;
public class Player : Entity
public class Player : Entity, IInteractionInterface
{
// public members
public Vector3 TargetPosition = Vector3.Zero;
public int goldCount = 0;
public TaskQueueComponent TaskQueueComponent;
@ -15,6 +18,9 @@ public class Player : Entity
get { return _navigationComponent; }
}
[Signal]
delegate void GoldCountChanged(int goldCount);
// private members
private WorldInfoComponent _worldInfo;
private GroundMotionComponent _groundMotion;
@ -22,6 +28,8 @@ public class Player : Entity
private Area _itemAttractorArea;
private Area _itemPickupArea;
private List<Node> _attractedItemList = new List<Node>();
private BoneAttachment _toolAttachement;
private AnimationPlayer _playerAnimationPlayer;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
@ -53,6 +61,14 @@ public class Player : Entity
_itemPickupArea.Connect("body_entered", this, nameof(OnItemPickupAreaBodyEntered));
}
_playerAnimationPlayer = (AnimationPlayer)GetNode<AnimationPlayer>("Geometry/AnimationPlayer");
Debug.Assert(_playerAnimationPlayer != null);
_toolAttachement = (BoneAttachment)FindNode("ToolAttachement");
if (_toolAttachement == null)
{
GD.PushWarning("No ToolAttachement found!");
}
}
@ -94,9 +110,9 @@ public class Player : Entity
foreach (Node node in _attractedItemList)
{
GoldBar bar = (GoldBar)node;
if (bar != null)
if (node is GoldBar)
{
GoldBar bar = (GoldBar)node;
bar.SetTarget(GlobalTransform.origin);
}
}
@ -111,9 +127,10 @@ public class Player : Entity
public void OnItemAttractorBodyExited(Node node)
{
GD.Print("Item exited " + node);
GoldBar bar = (GoldBar)node;
if (bar != null)
if (node is GoldBar)
{
GoldBar bar = (GoldBar)node;
bar.UnsetTarget();
}
_attractedItemList.Remove(node);
@ -121,11 +138,44 @@ public class Player : Entity
public void OnItemPickupAreaBodyEntered(Node body)
{
GD.Print("Picking up item: " + body);
GD.Print("Picking up item: " + body.Name);
if (body is Axe)
{
SetActiveTool("Axe");
}
if (body is GoldBar)
{
GoldBar bar = (GoldBar)body;
bar.QueueFree();
goldCount++;
EmitSignal("GoldCountChanged", goldCount);
}
body.QueueFree();
}
public void SetActiveTool(String toolName)
{
Debug.Assert(_toolAttachement != null);
if (toolName == "Axe")
{
_toolAttachement.Visible = true;
} else if (toolName == "")
{
_toolAttachement.Visible = false;
}
}
public void OnInteractionStart()
{
GD.Print("Player Starting Interaction");
_playerAnimationPlayer.CurrentAnimation = "Hit-loop";
_playerAnimationPlayer.Play();
}
public void OnInteractionEnd()
{
GD.Print("Player Stopping Interaction");
_playerAnimationPlayer.CurrentAnimation = "Idle-loop";
}
}

90
entities/Tree.cs Normal file
View File

@ -0,0 +1,90 @@
using Godot;
using System;
using System.Diagnostics;
using GodotComponentTest.entities;
public class Tree : StaticBody, IInteractionInterface
{
[Export] public float ChopDuration = 2;
public bool IsMouseOver = false;
private MeshInstance _geometry;
private AnimationPlayer _animationPlayer;
private float _health = 100;
private bool _isBeingChopped = false;
[Signal]
delegate void EntityClicked(Entity entity);
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_geometry = GetNode<MeshInstance>("Geometry");
Debug.Assert(_geometry != null);
_animationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
Debug.Assert(_animationPlayer != null);
Connect("input_event", this, nameof(OnAreaInputEvent));
Connect("mouse_entered", this, nameof(OnAreaMouseEntered));
Connect("mouse_exited", this, nameof(OnAreaMouseExited));
}
public override void _Process(float delta)
{
base._Process(delta);
if (_isBeingChopped)
{
_health = Math.Max(0, _health - delta * 100 / ChopDuration);
}
if (_health == 0)
{
QueueFree();
}
}
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal,
int shapeIndex)
{
if (IsMouseOver && inputEvent is InputEventMouseButton)
{
InputEventMouseButton mouseButtonEvent = (InputEventMouseButton)inputEvent;
if (mouseButtonEvent.ButtonIndex == 1 && mouseButtonEvent.Pressed)
{
EmitSignal("EntityClicked", this);
}
}
}
public void OnAreaMouseEntered()
{
IsMouseOver = true;
SpatialMaterial overrideMaterial = new SpatialMaterial();
overrideMaterial.AlbedoColor = new Color(1, 0, 0);
_geometry.MaterialOverride = overrideMaterial;
}
public void OnAreaMouseExited()
{
IsMouseOver = false;
_geometry.MaterialOverride = null;
}
public void OnInteractionStart()
{
GD.Print("Starting tree animationplayer");
_animationPlayer.CurrentAnimation = "TreeShake";
_animationPlayer.Play();
_isBeingChopped = true;
}
public void OnInteractionEnd()
{
_animationPlayer.Stop();
}
}

81
entities/Tree.tscn Normal file

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,8 @@ public class Game : Spatial
private TextureRect _worldTextureRect;
private TextureRect _heightTextureRect;
private Button _generateWorldButton;
private Control _gameUI;
private Label _goldCountLabel;
// scene nodes
private Spatial _tileHighlight;
@ -25,7 +27,6 @@ public class Game : Spatial
private Area _streamContainerArea;
private Spatial _streamContainerActiveTiles;
private Player _player;
private Chest _chest;
private TileWorld _tileWorld;
private Camera _camera;
@ -39,13 +40,14 @@ public class Game : Spatial
private HexCell _currentTile;
private Vector3 _cameraOffset;
private ImageTexture _blackWhitePatternTexture;
private InteractionSystem _interactionSystem;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
// debugStatsContainer
Container debugStatsContainer = (Container) FindNode("DebugStatsContainer");
Container debugStatsContainer = (Container)FindNode("DebugStatsContainer");
_framesPerSecondLabel = debugStatsContainer.GetNode<Label>("fps_label");
_tileLabel = debugStatsContainer.GetNode<Label>("tile_label");
_tileOffsetLabel = debugStatsContainer.GetNode<Label>("tile_offset_label");
@ -60,17 +62,19 @@ public class Game : Spatial
_worldTextureRect = worldGeneratorContainer.GetNode<TextureRect>("WorldTextureRect");
_heightTextureRect = worldGeneratorContainer.GetNode<TextureRect>("HeightTextureRect");
_generateWorldButton = worldGeneratorContainer.GetNode<Button>("WorldGenerateButton");
_gameUI = (Control)FindNode("GameUI");
_goldCountLabel = _gameUI.GetNode<Label>("GoldCount");
Debug.Assert(_goldCountLabel != null);
// scene nodes
_tileHighlight = GetNode<Spatial>("TileHighlight");
_mouseTileHighlight = GetNode<Spatial>("MouseTileHighlight");
_streamContainer = (StreamContainer)FindNode("StreamContainer");
_streamContainerArea = _streamContainer.GetNode<Area>("Area");
_streamContainerActiveTiles = _streamContainer.GetNode<Spatial>("ActiveTiles");
_player = GetNode<Player>("Player");
_chest = GetNode<Chest>("Entities/Chest");
_tileWorld = GetNode<TileWorld>("TileWorld");
_camera = (Camera)FindNode("Camera");
_cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation;
@ -78,7 +82,7 @@ public class Game : Spatial
// populate UI values
Slider generatorWorldSizeSlider = worldGeneratorContainer.GetNode<Slider>("HBoxContainer/WorldSizeSlider");
generatorWorldSizeSlider.Value = _tileWorld.Size;
Debug.Assert(_tileWorld != null);
// resources
@ -89,12 +93,14 @@ public class Game : Spatial
_blackWhitePatternTexture = new ImageTexture();
Image image = new Image();
image.Load("assets/4x4checker.png");
_blackWhitePatternTexture.CreateFromImage(image, (uint) (Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
_blackWhitePatternTexture.CreateFromImage(image, (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
// other members
_lastTile = new HexCell();
_currentTile = new HexCell();
_hexGrid = new HexGrid();
_interactionSystem = GetNode<InteractionSystem>("InteractionSystem");
Debug.Assert(_interactionSystem != null);
// update data
_worldTextureRect.RectSize = Vector2.One * _tileWorld.Size;
@ -106,12 +112,13 @@ public class Game : Spatial
_streamContainer.Connect("TileHovered", this, nameof(OnTileHovered));
_tileWorld.Connect("WorldGenerated", this, nameof(OnWorldGenerated));
_generateWorldButton.Connect("pressed", this, nameof(OnGenerateButton));
_player.TaskQueueComponent.Connect("StartInteraction", _interactionSystem, nameof(_interactionSystem.OnStartInteraction));
_player.Connect("GoldCountChanged", this, nameof(OnGoldCountChanged));
// register entity events
Array entityNodes = FindNode("Entities").GetChildren();
foreach (Node node in entityNodes)
foreach (Node node in GetNode("Entities").GetChildren())
{
if (node is Chest)
if (node.HasSignal("EntityClicked"))
{
node.Connect("EntityClicked", this, nameof(OnEntityClicked));
}
@ -157,9 +164,9 @@ public class Game : Spatial
Vector3 cameraNormal = _camera.ProjectRayNormal(_camera.GetViewport().Size * 0.5f);
Vector3 cameraPosition = _camera.ProjectRayOrigin(_camera.GetViewport().Size * 0.5f);
Vector3 cameraDir = cameraNormal - cameraPosition;
Vector3 centerCoord;
if (Mathf.Abs(cameraDir.y) > Globals.EpsPosition)
{
centerCoord = cameraPosition + cameraNormal * (-cameraPosition.y / cameraNormal.y);
@ -169,7 +176,7 @@ public class Game : Spatial
centerCoord = _camera.GlobalTranslation;
centerCoord.y = 0;
}
_currentTile = _hexGrid.GetHexAt(new Vector2(centerCoord.x, centerCoord.z));
@ -215,10 +222,11 @@ public class Game : Spatial
GD.PrintErr("Could not find WorldSizeSlider!");
return;
}
_tileWorld.Seed = _tileWorld.Seed + 1;
_tileWorld.Generate((int)worldSizeSlider.Value);
}
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal,
int shapeIndex)
@ -280,8 +288,9 @@ public class Game : Spatial
playerStartTransform.origin.y = height;
_player.Transform = playerStartTransform;
_player.TaskQueueComponent.Reset();
_player.Navigation.PlanDirectPath(playerStartTransform.origin, playerStartTransform.origin, playerStartTransform.basis.Quat());
_player.Navigation.PlanDirectPath(playerStartTransform.origin, playerStartTransform.origin,
playerStartTransform.basis.Quat());
foreach (Spatial entity in GetNode("Entities").GetChildren())
{
Transform entityTransform = entity.Transform;
@ -296,20 +305,39 @@ public class Game : Spatial
public void OnWorldGenerated()
{
GD.Print("Using new map. Size: " + (int)_tileWorld.Colormap.GetSize().x);
_goldCountLabel.Text = "0";
ImageTexture newWorldTexture = new ImageTexture();
newWorldTexture.CreateFromImage(_tileWorld.Colormap, (uint) (Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
newWorldTexture.CreateFromImage(_tileWorld.Colormap,
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
_worldTextureRect.Texture = newWorldTexture;
_tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture);
_tileMaterial.SetShaderParam("TextureSize", (int)_tileWorld.Colormap.GetSize().x);
ImageTexture newHeightTexture = new ImageTexture();
newHeightTexture.CreateFromImage(_tileWorld.Heightmap, (uint) (Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
newHeightTexture.CreateFromImage(_tileWorld.Heightmap,
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
_heightTextureRect.Texture = newHeightTexture;
_streamContainer.OnWorldGenerated();
// Reset player transform to offset 0,0 and at current height
ResetGameState();
// Connect all signals of the generated world
foreach (Node node in _tileWorld.Entities.GetChildren())
{
if (node.HasSignal("EntityClicked"))
{
node.Connect("EntityClicked", this, nameof(OnEntityClicked));
}
}
}
public void OnGoldCountChanged(int goldCount)
{
_goldCountLabel.Text = goldCount.ToString();
}
}

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=20 format=2]
[gd_scene load_steps=21 format=2]
[ext_resource path="res://scenes/StreamContainer.cs" type="Script" id=1]
[ext_resource path="res://components/NavigationComponent.cs" type="Script" id=2]
@ -10,9 +10,10 @@
[ext_resource path="res://scenes/TileWorld.tscn" type="PackedScene" id=8]
[ext_resource path="res://scenes/Game.cs" type="Script" id=9]
[ext_resource path="res://scenes/DebugCamera.gd" type="Script" id=10]
[ext_resource path="res://assets/CreatusPiratePack/Models/Characters/gltf/Pirate1final.glb" type="PackedScene" id=11]
[ext_resource path="res://assets/Characters/Pirate.tscn" type="PackedScene" id=11]
[ext_resource path="res://ui/WorldGeneratorUI.gd" type="Script" id=12]
[ext_resource path="res://assets/Objects/toolAxe.tscn" type="PackedScene" id=13]
[ext_resource path="res://entities/Axe.tscn" type="PackedScene" id=14]
[ext_resource path="res://systems/InteractionSystem.cs" type="Script" id=15]
[sub_resource type="CubeMesh" id=1]
size = Vector3( 1, 1, 1 )
@ -47,6 +48,30 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0 )
[node name="TileWorld" parent="." instance=ExtResource( 8 )]
Size = 32
[node name="GameUI" type="HBoxContainer" parent="."]
anchor_left = 1.0
anchor_right = 1.0
margin_left = -40.0
margin_right = -10.0
margin_bottom = 40.0
grow_horizontal = 0
alignment = 2
[node name="GoldLabel" type="Label" parent="GameUI"]
margin_top = 13.0
margin_right = 30.0
margin_bottom = 27.0
text = "Gold"
[node name="GoldCount" type="Label" parent="GameUI"]
margin_left = 34.0
margin_top = 13.0
margin_right = 84.0
margin_bottom = 27.0
rect_min_size = Vector2( 50, 0 )
text = "0"
align = 2
[node name="DebugContainer" type="PanelContainer" parent="."]
visible = false
self_modulate = Color( 1, 1, 1, 0.443137 )
@ -272,6 +297,9 @@ current = true
fov = 60.0
script = ExtResource( 10 )
[node name="InteractionSystem" type="Node" parent="."]
script = ExtResource( 15 )
[node name="Player" type="KinematicBody" parent="."]
collision_mask = 0
axis_lock_motion_y = true
@ -284,11 +312,6 @@ shape = SubResource( 7 )
[node name="Movable" parent="Player" instance=ExtResource( 4 )]
[node name="Geometry" type="Spatial" parent="Player"]
transform = Transform( 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0 )
[node name="Pirate1final" parent="Player/Geometry" instance=ExtResource( 11 )]
[node name="WorldInfo" type="Node" parent="Player"]
script = ExtResource( 6 )
World = NodePath("../../TileWorld")
@ -313,6 +336,8 @@ monitorable = false
[node name="CollisionShape" type="CollisionShape" parent="Player/ItemPickupArea"]
shape = SubResource( 23 )
[node name="Geometry" parent="Player" instance=ExtResource( 11 )]
[node name="Entities" type="Spatial" parent="."]
[node name="Chest" parent="Entities" instance=ExtResource( 7 )]
@ -324,8 +349,9 @@ transform = Transform( 0.550568, 0, -0.83479, 0, 1, 0, 0.83479, 0, 0.550568, 4.8
[node name="Chest2" parent="Entities" instance=ExtResource( 7 )]
transform = Transform( 0.793576, 0, -0.608471, 0, 1, 0, 0.608471, 0, 0.793576, 2.79265, 0, -5.36551 )
[node name="toolAxe" parent="Entities" instance=ExtResource( 13 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81635, 0, 0 )
[node name="Axe" parent="Entities" instance=ExtResource( 14 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.79762, 0, 0 )
input_ray_pickable = false
[connection signal="value_changed" from="Generator Container/WorldGeneratorContainer/HBoxContainer/WorldSizeSlider" to="Generator Container/WorldGeneratorContainer" method="_on_HSlider_value_changed"]

View File

@ -226,13 +226,13 @@ public class StreamContainer : Spatial
public void OnTileClicked(HexTile3D tile)
{
GD.Print("Clicked on Tile at " + tile.OffsetCoords);
// GD.Print("Clicked on Tile at " + tile.OffsetCoords);
EmitSignal("TileClicked", tile);
}
public void OnTileHovered(HexTile3D tile)
{
GD.Print("Hovered on Tile at " + tile.OffsetCoords);
// GD.Print("Hovered on Tile at " + tile.OffsetCoords);
EmitSignal("TileHovered", tile);
}

View File

@ -33,6 +33,7 @@ public class TileWorld : Spatial
public Image Heightmap;
public Image Colormap;
public int Seed = 0;
public Spatial Entities;
// private members
private HexGrid _hexGrid;
@ -84,6 +85,7 @@ public class TileWorld : Spatial
}
_environmentNode = GetNode<Spatial>("Environment");
Entities = GetNode<Spatial>("Entities");
Generate(Size);
}
@ -161,6 +163,11 @@ public class TileWorld : Spatial
{
child.QueueFree();
}
foreach (Node child in Entities.GetChildren())
{
child.QueueFree();
}
}
private void OnHeightMapChanged()
@ -231,7 +238,7 @@ public class TileWorld : Spatial
Spatial treeAsset = SelectAsset(offsetCoord, _treeAssets, environmentRandom, 0.10);
if (treeAsset != null)
{
_environmentNode.AddChild(treeAsset);
Entities.AddChild(treeAsset);
}
}
}

View File

@ -8,7 +8,7 @@
[ext_resource path="res://assets/Environment/rockC.tscn" type="PackedScene" id=6]
[ext_resource path="res://assets/Environment/rockA.tscn" type="PackedScene" id=7]
[ext_resource path="res://assets/Environment/grassLarge.tscn" type="PackedScene" id=8]
[ext_resource path="res://assets/Environment/tree.tscn" type="PackedScene" id=9]
[ext_resource path="res://entities/Tree.tscn" type="PackedScene" id=9]
[node name="TileWorld" type="Spatial"]
script = ExtResource( 1 )
@ -70,3 +70,5 @@ visible = false
[node name="tree" parent="Assets/Trees" instance=ExtResource( 9 )]
[node name="Environment" type="Spatial" parent="."]
[node name="Entities" type="Spatial" parent="."]

View File

@ -0,0 +1,79 @@
using Godot;
using System;
using System.Collections.Generic;
using Godot.Collections;
using GodotComponentTest.entities;
using Array = System.Array;
using NodePair = System.Tuple<Godot.Node, Godot.Node>;
public class InteractionSystem : Node
{
private List<NodePair> _interactionPairs;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_interactionPairs = new List<NodePair>();
}
public override void _Process(float delta)
{
base._Process(delta);
List<NodePair> invalidInteractionPairs = new List<NodePair>();
foreach (Tuple<Node, Node> pair in _interactionPairs)
{
Node nodeA = pair.Item1;
Node nodeB = pair.Item2;
if (nodeA == null || nodeA.IsQueuedForDeletion() || nodeB == null || nodeB.IsQueuedForDeletion()) {
invalidInteractionPairs.Add(pair);
}
if (nodeA == null || nodeA.IsQueuedForDeletion())
{
IInteractionInterface interactableB = nodeB as IInteractionInterface;
if (interactableB != null)
{
interactableB.OnInteractionEnd();
}
}
if (nodeB == null || nodeB.IsQueuedForDeletion())
{
IInteractionInterface interactableA = nodeA as IInteractionInterface;
if (interactableA != null)
{
interactableA.OnInteractionEnd();
}
}
}
foreach (NodePair pair in invalidInteractionPairs)
{
_interactionPairs.Remove(pair);
}
}
public void OnStartInteraction(Node nodeA, Node nodeB)
{
IInteractionInterface interactableA = nodeA as IInteractionInterface;
if (interactableA != null)
{
interactableA.OnInteractionStart();
}
IInteractionInterface interactableB = nodeB as IInteractionInterface;
if (interactableB != null)
{
interactableB.OnInteractionStart();
}
NodePair pair = new NodePair(nodeA, nodeB);
_interactionPairs.Add(new NodePair(nodeA, nodeB));
}
}