diff --git a/BoundingBoxes/InteractionReceiver.cs b/BoundingBoxes/InteractionReceiver.cs new file mode 100644 index 0000000..c5aba49 --- /dev/null +++ b/BoundingBoxes/InteractionReceiver.cs @@ -0,0 +1,70 @@ +using Godot; +using System.Collections.Generic; + +namespace SupaLidlGame.BoundingBoxes; + +public partial class InteractionReceiver : Area2D +{ + [Signal] + public delegate void TriggerEventHandler( + InteractionTrigger trigger, + InteractionTrigger closestTrigger); + + [Signal] + public delegate void ClosestTriggerEventHandler(InteractionTrigger trigger); + + private InteractionTrigger _closestTrigger; + + private HashSet _triggers; + + public InteractionReceiver() + { + _triggers = new HashSet(); + } + + private void UpdateClosestTrigger() + { + float minDist = float.MaxValue; + InteractionTrigger best = null; + + foreach (var trigger in _triggers) + { + float dist = trigger.GlobalPosition + .DistanceSquaredTo(GlobalPosition); + + if (dist <= minDist) + { + best = trigger; + minDist = dist; + } + } + + if (_closestTrigger != best) + { + EmitSignal(SignalName.ClosestTrigger, best); + _closestTrigger = best; + } + } + + public void _on_area_entered(Area2D area) + { + if (area is InteractionTrigger trigger) + { + EmitSignal(SignalName.Trigger, _closestTrigger); + } + } + + public void _on_area_exited(Area2D area) + { + // update closest trigger + if (area is InteractionTrigger trigger) + { + if (_triggers.Contains(trigger)) + { + _triggers.Remove(trigger); + } + UpdateClosestTrigger(); + } + GD.PushWarning("Area entered is not an InteractionTrigger."); + } +} diff --git a/BoundingBoxes/InteractionReceiver.tscn b/BoundingBoxes/InteractionReceiver.tscn new file mode 100644 index 0000000..a2d86bc --- /dev/null +++ b/BoundingBoxes/InteractionReceiver.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=3 format=3 uid="uid://cdxiutj5jdnvo"] + +[ext_resource type="Script" path="res://BoundingBoxes/InteractionReceiver.cs" id="1_y2pab"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_vcbnn"] +radius = 16.0 + +[node name="InteractionReceiver" type="Area2D"] +collision_layer = 32 +collision_mask = 64 +script = ExtResource("1_y2pab") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("CircleShape2D_vcbnn") +debug_color = Color(0.792157, 0.0705882, 1, 0.419608) + +[connection signal="area_entered" from="." to="." method="_on_area_entered"] +[connection signal="area_exited" from="." to="." method="_on_area_exited"] diff --git a/BoundingBoxes/InteractionTrigger.cs b/BoundingBoxes/InteractionTrigger.cs new file mode 100644 index 0000000..9c45016 --- /dev/null +++ b/BoundingBoxes/InteractionTrigger.cs @@ -0,0 +1,7 @@ +using Godot; + +namespace SupaLidlGame.BoundingBoxes; + +public partial class InteractionTrigger : Area2D +{ +} diff --git a/Characters/Character.cs b/Characters/Character.cs index 74fdbe6..da2d29d 100644 --- a/Characters/Character.cs +++ b/Characters/Character.cs @@ -25,6 +25,12 @@ public partial class Character : CharacterBody2D, IFaction } } + [Signal] + public delegate void HurtEventHandler(Events.HealthChangedArgs args); + + [Signal] + public delegate void DeathEventHandler(Events.HealthChangedArgs args); + protected float _mass = 1.0f; public Vector2 NetImpulse { get; set; } = Vector2.Zero; diff --git a/Characters/Player.tscn b/Characters/Player.tscn index cb23d86..59650ff 100644 --- a/Characters/Player.tscn +++ b/Characters/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=30 format=3 uid="uid://b2254pup8k161"] +[gd_scene load_steps=29 format=3 uid="uid://b2254pup8k161"] [ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"] [ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"] @@ -11,7 +11,6 @@ [ext_resource type="Script" path="res://Items/Inventory.cs" id="7_xyenu"] [ext_resource type="Script" path="res://State/Character/PlayerRollState.cs" id="8_fy0v5"] [ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="9_avyu4"] -[ext_resource type="PackedScene" uid="uid://g7wfcubs6bdd" path="res://Items/Weapons/Railgun.tscn" id="10_7kb8b"] [ext_resource type="AudioStream" uid="uid://njun3e6v4854" path="res://Assets/Sounds/hurt.wav" id="12_h0x0g"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_h78y7"] @@ -209,9 +208,8 @@ InventoryMap = { "equip_2": 1 } -[node name="Railgun" parent="Inventory" instance=ExtResource("10_7kb8b")] - [node name="Node2D" parent="Inventory" instance=ExtResource("7_4rxuv")] +visible = false ShouldHideIdle = false [node name="Hurtbox" parent="." instance=ExtResource("9_avyu4")] diff --git a/Events/Args.cs b/Events/Args.cs new file mode 100644 index 0000000..3deb8b1 --- /dev/null +++ b/Events/Args.cs @@ -0,0 +1,8 @@ +using Godot; + +namespace SupaLidlGame.Events; + +public abstract partial class Args : GodotObject +{ + +} diff --git a/Events/HealthChangedArgs.cs b/Events/HealthChangedArgs.cs new file mode 100644 index 0000000..ae6b957 --- /dev/null +++ b/Events/HealthChangedArgs.cs @@ -0,0 +1,14 @@ +namespace SupaLidlGame.Events; + +public partial class HealthChangedArgs : Args +{ + public Characters.Character Attacker { get; set; } + + public Items.Weapon Weapon { get; set; } + + public float OldHealth { get; set; } + + public float NewHealth { get; set; } + + public float Damage { get; set; } +} diff --git a/Extensions/AudioStreamPlayer2D.cs b/Extensions/AudioStreamPlayer2D.cs index 23339e7..20bdb4d 100644 --- a/Extensions/AudioStreamPlayer2D.cs +++ b/Extensions/AudioStreamPlayer2D.cs @@ -1,6 +1,5 @@ using Godot; using System; -using SupaLidlGame.Utils; namespace SupaLidlGame.Extensions; diff --git a/State/Character/PlayerState.cs b/State/Character/PlayerState.cs index 648d2e7..8476929 100644 --- a/State/Character/PlayerState.cs +++ b/State/Character/PlayerState.cs @@ -15,12 +15,16 @@ public abstract partial class PlayerState : CharacterState var inventory = Character.Inventory; if (this is PlayerIdleState or PlayerMoveState && - !_player.Inventory.IsUsingItem) + !_player.Inventory.IsUsingItem) { if (@event.IsActionPressed("equip_1")) { inventory.SelectedItem = inventory.GetItemByMap("equip_1"); } + else if (@event.IsActionPressed("equip_2")) + { + inventory.SelectedItem = inventory.GetItemByMap("equip_2"); + } } return base.Input(@event); diff --git a/State/Health/AliveState.cs b/State/Health/AliveState.cs new file mode 100644 index 0000000..5cc71dd --- /dev/null +++ b/State/Health/AliveState.cs @@ -0,0 +1,6 @@ +namespace SupaLidlGame.State.Health; + +public partial class AliveState : HealthState +{ + +} diff --git a/State/Health/DeadState.cs b/State/Health/DeadState.cs new file mode 100644 index 0000000..bcf71b1 --- /dev/null +++ b/State/Health/DeadState.cs @@ -0,0 +1 @@ +namespace SupaLidlGame.State.Health; diff --git a/State/Health/HealthState.cs b/State/Health/HealthState.cs new file mode 100644 index 0000000..f0f5ab1 --- /dev/null +++ b/State/Health/HealthState.cs @@ -0,0 +1,13 @@ +using Godot; + +namespace SupaLidlGame.State.Health; + +public abstract partial class HealthState : Node, IState +{ + public virtual IState Enter(IState prev) => null; + + public virtual void Exit(IState next) + { + + } +} diff --git a/Utils/World.cs b/Utils/World.cs index 4ffe2d6..aa7eb4d 100644 --- a/Utils/World.cs +++ b/Utils/World.cs @@ -1,7 +1,6 @@ using Godot; using SupaLidlGame.Characters; using SupaLidlGame.Scenes; -using SupaLidlGame.Extensions; using System.Collections.Generic; using System.Linq; @@ -24,6 +23,8 @@ public partial class World : Node2D private string _currentMapResourcePath; + private Entities.Campfire _lastCampfire = null; + private const string PLAYER_PATH = "res://Characters/Player.tscn"; private PackedScene _playerScene; @@ -43,6 +44,11 @@ public partial class World : Node2D // spawn the player in CreatePlayer(); + CurrentPlayer.Death += (Events.HealthChangedArgs args) => + { + // TODO: respawn the player at the last campfire. + }; + base._Ready(); } diff --git a/project.godot b/project.godot index c2544a1..8bdfda5 100644 --- a/project.godot +++ b/project.godot @@ -89,6 +89,8 @@ equip_3={ 2d_physics/layer_3="Player" 2d_physics/layer_4="NPC" 2d_physics/layer_5="World Clip" +2d_physics/layer_6="Interaction Receiver" +2d_physics/layer_7="Interaction Trigger" [physics]