diff --git a/components/NavigationComponent.cs b/components/NavigationComponent.cs index beca70d..edc681a 100644 --- a/components/NavigationComponent.cs +++ b/components/NavigationComponent.cs @@ -169,9 +169,9 @@ public class NavigationComponent : Node _currentGoalPositionWorld = _pathWorldNavigationPoints[0].WorldPosition; _currentGoalOrientationWorld = _pathWorldNavigationPoints[0].WorldOrientation; - GD.Print("Navigation Goal: pos " + _currentGoal.WorldPosition + " " + " rot: " + _currentGoal.WorldOrientation + - " flags: " + _currentGoal.Flags + " path length: " + - _pathWorldNavigationPoints.Count); +// GD.Print("Navigation Goal: pos " + _currentGoal.WorldPosition + " " + " rot: " + _currentGoal.WorldOrientation + +// " flags: " + _currentGoal.Flags + " path length: " + +// _pathWorldNavigationPoints.Count); } diff --git a/entities/Chest.cs b/entities/Chest.cs index c50aacb..fb7276c 100644 --- a/entities/Chest.cs +++ b/entities/Chest.cs @@ -1,11 +1,11 @@ using Godot; using System; +using System.Linq; public class Chest : Entity { - // Declare member variables here. Examples: - // private int a = 2; - // private string b = "text"; + // resources + private PackedScene _goldBarScene = GD.Load("res://entities/GoldBar.tscn"); public enum LidState { @@ -18,22 +18,27 @@ public class Chest : Entity private MeshInstance _mesh; private SpatialMaterial _previousMaterial; private AnimationPlayer _animationPlayer; - + private Random _coinSpawnerRandom; + [Signal] delegate void EntityClicked(Entity entity); - + + [Signal] + delegate void ChestOpened(Entity entity); + // Called when the node enters the scene tree for the first time. public override void _Ready() { _mesh = GetNode("Armature/Skeleton/Chest"); _animationPlayer = GetNode("AnimationPlayer"); - + Connect("input_event", this, nameof(OnAreaInputEvent)); Connect("mouse_entered", this, nameof(OnAreaMouseEntered)); Connect("mouse_exited", this, nameof(OnAreaMouseExited)); + Connect("ChestOpened", this, nameof(ChestOpened)); } - + public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal, int shapeIndex) { @@ -47,7 +52,7 @@ public class Chest : Entity } } - + public void OnAreaMouseEntered() { IsMouseOver = true; @@ -56,7 +61,7 @@ public class Chest : Entity _mesh.MaterialOverride = overrideMaterial; } - + public void OnAreaMouseExited() { IsMouseOver = false; @@ -67,7 +72,7 @@ public class Chest : Entity public void OnInteract() { _animationPlayer.Stop(); - + if (State == LidState.Closed) { State = LidState.Open; @@ -79,4 +84,20 @@ public class Chest : Entity State = LidState.Closed; } } -} + + public void OnChestOpened() + { + GD.Print("Chest now opened!"); + foreach (int i in Enumerable.Range(0, 10)) + { + GoldBar bar = (GoldBar)_goldBarScene.Instance(); + bar.Transform = new Transform(Transform.basis.Rotated(Vector3.Up, GD.Randf() * 2 * Mathf.Pi), Transform.origin + Vector3.Up * 0.8f); + bar.velocity = new Vector3( + (GD.Randf() * 2f - 1f) * 2, + 5, + (GD.Randf() * 2f - 1f) * 2 + ); + GetParent().AddChild(bar); + } + } +} \ No newline at end of file diff --git a/entities/Chest.tscn b/entities/Chest.tscn index a28a608..de7eedd 100644 --- a/entities/Chest.tscn +++ b/entities/Chest.tscn @@ -58,6 +58,20 @@ tracks/1/loop_wrap = true tracks/1/imported = false tracks/1/enabled = true tracks/1/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.133333, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.266667, 1, 0, 0, 0, -5.57256e-17, 1.47956e-08, -0.0876532, 0.996151, 1, 1, 1, 0.333333, 1, 0, 0, 0, -1.11023e-16, -2.8211e-10, 0.00209969, 0.999998, 1, 1, 1 ) +tracks/2/type = "method" +tracks/2/path = NodePath(".") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/keys = { +"times": PoolRealArray( 0.3 ), +"transitions": PoolRealArray( 1 ), +"values": [ { +"args": [ ], +"method": "OnChestOpened" +} ] +} [sub_resource type="CubeMesh" id=14] @@ -67,6 +81,7 @@ tracks/1/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.133333, 1, extents = Vector3( 0.19, 0.19, 0.332 ) [node name="Chest" type="KinematicBody"] +collision_mask = 0 script = ExtResource( 1 ) [node name="Armature" type="Spatial" parent="."] diff --git a/entities/GoldBar.cs b/entities/GoldBar.cs new file mode 100644 index 0000000..1e90217 --- /dev/null +++ b/entities/GoldBar.cs @@ -0,0 +1,64 @@ +using Godot; +using System; + +public class GoldBar : KinematicBody +{ + private Vector3 targetPosition; + private bool hasTarget = false; + public Vector3 velocity; + + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + targetPosition = GlobalTransform.origin; + } + + public void SetTarget(Vector3 target) + { + targetPosition = target; + hasTarget = true; + } + + public void UnsetTarget() + { + hasTarget = false; + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _PhysicsProcess(float delta) + { + if (hasTarget) + { + if (targetPosition.IsEqualApprox(GlobalTransform.origin)) + { + targetPosition = GlobalTransform.origin; + velocity = Vector3.Zero; + } + + + Vector3 targetDirection = (targetPosition - GlobalTransform.origin).Normalized(); + velocity = targetDirection * (velocity.Length() + 10 * delta); + Transform = new Transform(this.Transform.basis.Rotated(Vector3.Up, delta * 2.0f), Transform.origin); + } + 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; + } + + if (velocity.LengthSquared() < 0.01) + { + velocity = Vector3.Zero; + } + else + { + + velocity = MoveAndSlide(velocity); + } + } +} diff --git a/entities/GoldBar.tscn b/entities/GoldBar.tscn new file mode 100644 index 0000000..1e62185 --- /dev/null +++ b/entities/GoldBar.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://entities/GoldBar.cs" type="Script" id=1] +[ext_resource path="res://assets/Objects/Gold_Bar.tscn" type="PackedScene" id=2] + +[sub_resource type="BoxShape" id=21] +extents = Vector3( 0.354271, 0.0817164, 0.173406 ) + +[node name="Gold" type="KinematicBody"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.250567, 0, -3.89129 ) +collision_layer = 9 +collision_mask = 0 +script = ExtResource( 1 ) + +[node name="CollisionShape" type="CollisionShape" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.084728, 0 ) +shape = SubResource( 21 ) + +[node name="Geometry" parent="." instance=ExtResource( 2 )] diff --git a/entities/Player.cs b/entities/Player.cs index 6564ae8..c813cd5 100644 --- a/entities/Player.cs +++ b/entities/Player.cs @@ -1,5 +1,7 @@ using Godot; using System; +using System.Collections.Generic; +using System.Linq; public class Player : Entity { @@ -19,6 +21,9 @@ public class Player : Entity private WorldInfoComponent _worldInfo; private GroundMotionComponent _groundMotion; private NavigationComponent _navigationComponent; + private Area _itemAttractorArea; + private Area _itemPickupArea; + private List _attractedItemList = new List(); // Called when the node enters the scene tree for the first time. public override void _Ready() @@ -29,6 +34,28 @@ public class Player : Entity _navigationComponent.TileWorld = _worldInfo.TileWorld; TaskQueueComponent = new TaskQueueComponent(); _geometry = (Spatial)FindNode("Geometry", false); + + _itemAttractorArea = (Area)FindNode("ItemAttractorArea", false); + if (_itemAttractorArea == null) + { + GD.PushWarning("No ItemAttractorArea node found for " + this.GetClass()); + } + else + { + _itemAttractorArea.Connect("body_entered", this, nameof(OnItemAttractorBodyEntered)); + _itemAttractorArea.Connect("body_exited", this, nameof(OnItemAttractorBodyExited)); + } + + _itemPickupArea = (Area)FindNode("ItemPickupArea", false); + if (_itemPickupArea == null) + { + GD.PushWarning("No ItemPickupArea node found for " + this.GetClass()); + } + else + { + _itemPickupArea.Connect("body_entered", this, nameof(OnItemPickupAreaBodyEntered)); + } + } @@ -67,5 +94,41 @@ public class Player : Entity { _navigationComponent.UpdateCurrentGoal(GlobalTransform); } + + foreach (Node node in _attractedItemList) + { + GoldBar bar = (GoldBar)node; + if (bar != null) + { + bar.SetTarget(GlobalTransform.origin); + } + } + } + + public void OnItemAttractorBodyEntered(Node node) + { + GD.Print("Item entered " + node); + _attractedItemList.Add(node); + } + + public void OnItemAttractorBodyExited(Node node) + { + GD.Print("Item exited " + node); + GoldBar bar = (GoldBar)node; + if (bar != null) + { + bar.UnsetTarget(); + } + _attractedItemList.Remove(node); + } + + public void OnItemPickupAreaBodyEntered(Node body) + { + GD.Print("Picking up item: " + body); + if (body is GoldBar) + { + GoldBar bar = (GoldBar)body; + bar.QueueFree(); + } } } \ No newline at end of file diff --git a/project.godot b/project.godot index d772b01..afb22bb 100644 --- a/project.godot +++ b/project.godot @@ -9,17 +9,17 @@ config_version=4 _global_script_classes=[ { -"base": "Node", +"base": "Reference", "class": "ClickableComponent", "language": "GDScript", "path": "res://components/ClickableComponent.gd" }, { -"base": "KinematicBody2D", +"base": "Reference", "class": "CollisionLine", "language": "GDScript", "path": "res://utils/CollisionLine.gd" }, { -"base": "Node", +"base": "Reference", "class": "ColorComponent", "language": "GDScript", "path": "res://components/ColorComponent.gd" @@ -54,7 +54,7 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://utils/SpringDamper.gd" }, { -"base": "Sprite", +"base": "Reference", "class": "TintedSpriteComponent", "language": "GDScript", "path": "res://components/TintedSpriteComponent.gd" @@ -87,6 +87,10 @@ window/size/test_height=768 window/stretch/mode="viewport" window/stretch/aspect="expand" +[global] + +collision=false + [input] Forward={ @@ -110,6 +114,13 @@ Right={ ] } +[layer_names] + +3d_physics/layer_1="World" +3d_physics/layer_2="Player" +3d_physics/layer_3="Enemies" +3d_physics/layer_4="Collectables" + [mono] project/assembly_name="GodotComponentTest" diff --git a/scenes/Game.tscn b/scenes/Game.tscn index 606eed2..ca7b1d1 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=27 format=2] +[gd_scene load_steps=24 format=2] [ext_resource path="res://scenes/StreamContainer.cs" type="Script" id=1] [ext_resource path="res://components/NavigationComponent.cs" type="Script" id=2] @@ -11,8 +11,6 @@ [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/characters/Pirate1final_0.01.glb" type="PackedScene" id=13] -[ext_resource path="res://components/ClickableComponent.cs" type="Script" id=14] -[ext_resource path="res://entities/Flower.cs" type="Script" id=15] [sub_resource type="OpenSimplexNoise" id=10] period = 39.6 @@ -49,6 +47,12 @@ radial_segments = 16 [sub_resource type="PrismMesh" id=15] +[sub_resource type="CylinderShape" id=24] +height = 0.2 + +[sub_resource type="SphereShape" id=23] +radius = 0.1 + [node name="Game" type="Spatial"] script = ExtResource( 9 ) @@ -235,6 +239,7 @@ fov = 60.0 script = ExtResource( 10 ) [node name="Player" type="KinematicBody" parent="."] +collision_mask = 0 axis_lock_motion_y = true move_lock_y = true script = ExtResource( 3 ) @@ -276,31 +281,27 @@ World = NodePath("../../TileWorld") [node name="Navigation" type="Node" parent="Player"] script = ExtResource( 2 ) +[node name="ItemAttractorArea" type="Area" parent="Player"] +collision_layer = 0 +collision_mask = 8 +monitorable = false + +[node name="CollisionShape" type="CollisionShape" parent="Player/ItemAttractorArea"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.123516, 0 ) +shape = SubResource( 24 ) + +[node name="ItemPickupArea" type="Area" parent="Player"] +collision_layer = 0 +collision_mask = 8 +monitorable = false + +[node name="CollisionShape" type="CollisionShape" parent="Player/ItemPickupArea"] +shape = SubResource( 23 ) + [node name="Entities" type="Spatial" parent="."] [node name="Chest" parent="Entities" instance=ExtResource( 7 )] -transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 2.01499, 0, -1.3224 ) - -[node name="Flower" type="KinematicBody" parent="Entities"] -transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.75737, 0, -3.73012 ) -input_ray_pickable = false -script = ExtResource( 15 ) - -[node name="MeshInstance" type="MeshInstance" parent="Entities/Flower"] -transform = Transform( 0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0 ) -mesh = SubResource( 17 ) - -[node name="CollisionShape" type="CollisionShape" parent="Entities/Flower"] -shape = SubResource( 18 ) - -[node name="ClickableComponent" type="Spatial" parent="Entities/Flower"] -script = ExtResource( 14 ) - -[node name="Area" type="Area" parent="Entities/Flower/ClickableComponent"] - -[node name="CollisionShape" type="CollisionShape" parent="Entities/Flower/ClickableComponent/Area"] -transform = Transform( 0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0 ) -shape = SubResource( 19 ) +transform = Transform( -0.068085, 0, -0.99768, 0, 1, 0, 0.99768, 0, -0.068085, 2.01499, 0, -1.3224 ) [node name="Chest3" parent="Entities" instance=ExtResource( 7 )] transform = Transform( 0.550568, 0, -0.83479, 0, 1, 0, 0.83479, 0, 0.550568, 4.88275, 0, -1.70504 ) diff --git a/script_templates/.gdignore b/script_templates/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/script_templates/Default.cs b/script_templates/Default.cs new file mode 100644 index 0000000..e9878ac --- /dev/null +++ b/script_templates/Default.cs @@ -0,0 +1,31 @@ +using Godot; +using System; + +public class %CLASS% : %BASE% +{ + // ui elements + + // scene nodes + + // resources + + // exports + // [Export] public Vector2 Size = new Vector2(1, 1); + + // signals + // delegate void OnCoordClicked(Vector2 world_pos); + + // other members + + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + + } + +// // Called every frame. 'delta' is the elapsed time since the previous frame. +// public override void _Process(float delta) +// { +// +// } +}