diff --git a/assets/sfx/tube_connect.wav b/assets/sfx/tube_connect.wav new file mode 100644 index 0000000..d879b83 Binary files /dev/null and b/assets/sfx/tube_connect.wav differ diff --git a/assets/sfx/tube_connect.wav.import b/assets/sfx/tube_connect.wav.import new file mode 100644 index 0000000..808dcdc --- /dev/null +++ b/assets/sfx/tube_connect.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://bxxi7grsubvgm" +path="res://.godot/imported/tube_connect.wav-1fe9cadbb3e3c66b255ef4556d86a7af.sample" + +[deps] + +source_file="res://assets/sfx/tube_connect.wav" +dest_files=["res://.godot/imported/tube_connect.wav-1fe9cadbb3e3c66b255ef4556d86a7af.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/sfx/tube_connect_2.wav b/assets/sfx/tube_connect_2.wav new file mode 100644 index 0000000..b57ea8b Binary files /dev/null and b/assets/sfx/tube_connect_2.wav differ diff --git a/assets/sfx/tube_connect_2.wav.import b/assets/sfx/tube_connect_2.wav.import new file mode 100644 index 0000000..36654bc --- /dev/null +++ b/assets/sfx/tube_connect_2.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cimb1xertnfor" +path="res://.godot/imported/tube_connect_2.wav-2efbb2986383719e05eac50cfe243d79.sample" + +[deps] + +source_file="res://assets/sfx/tube_connect_2.wav" +dest_files=["res://.godot/imported/tube_connect_2.wav-2efbb2986383719e05eac50cfe243d79.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/sfx/tube_disconnect.wav b/assets/sfx/tube_disconnect.wav new file mode 100644 index 0000000..d6dc135 Binary files /dev/null and b/assets/sfx/tube_disconnect.wav differ diff --git a/assets/sfx/tube_disconnect.wav.import b/assets/sfx/tube_disconnect.wav.import new file mode 100644 index 0000000..a9094e5 --- /dev/null +++ b/assets/sfx/tube_disconnect.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://mj8wvuwfc6o7" +path="res://.godot/imported/tube_disconnect.wav-20a1bab1cf9ccbee7621f9a058127981.sample" + +[deps] + +source_file="res://assets/sfx/tube_disconnect.wav" +dest_files=["res://.godot/imported/tube_disconnect.wav-20a1bab1cf9ccbee7621f9a058127981.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/default_bus_layout.tres b/default_bus_layout.tres new file mode 100644 index 0000000..8e846c6 --- /dev/null +++ b/default_bus_layout.tres @@ -0,0 +1,9 @@ +[gd_resource type="AudioBusLayout" format=3 uid="uid://djkq0k3jsuxcg"] + +[resource] +bus/1/name = &"SoundFX" +bus/1/solo = false +bus/1/mute = false +bus/1/bypass_fx = false +bus/1/volume_db = -15.375541 +bus/1/send = &"Master" diff --git a/project.godot b/project.godot index 37570c2..2c5248f 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,10 @@ run/main_scene="uid://drxbsnqoi4wmw" config/features=PackedStringArray("4.6", "C#", "Forward Plus") config/icon="res://assets/icon.svg" +[audio] + +buses/default_bus_layout="uid://djkq0k3jsuxcg" + [display] window/size/viewport_width=480 @@ -59,6 +63,10 @@ cam_down={ ] } +[layer_names] + +2d_physics/layer_2="TubeConnections" + [physics] 3d/physics_engine="Jolt Physics" diff --git a/src/Gameplay/BuildGhost.cs b/src/Gameplay/BuildGhost.cs index edcfd65..d067d4b 100644 --- a/src/Gameplay/BuildGhost.cs +++ b/src/Gameplay/BuildGhost.cs @@ -1,4 +1,5 @@ using Godot; +using Slimepire.Gameplay.Nodules; namespace Slimepire.Gameplay; @@ -7,18 +8,64 @@ public partial class BuildGhost : Node2D { public event Action? OnBuild; private Tube? _tube; + private readonly Dictionary _connectedTubes = []; public override void _Ready() { - _tube = Instantiator.Instantiate(); - _tube.Position = Position / 2; // TODO WHYYY???? - GetParent()?.AddChild(_tube); + TubeConnectionArea.AreaEntered += TubeConnectionAreaOnAreaEntered; + TubeConnectionArea.AreaExited += TubeConnectionAreaOnAreaExited; + } + + private void TubeConnectionAreaOnAreaEntered(Area2D area) + { + if (area.GetParent() is Nodule nodule) + { + CreateGhostTube(nodule, area.GlobalPosition); + ConnectTubePlayer.Play(); + } + } + + private void TubeConnectionAreaOnAreaExited(Area2D area) + { + if (area.GetParent() is Nodule nodule) + { + var tube = _connectedTubes.GetValueOrDefault(nodule); + if (tube == null) + return; + + _connectedTubes.Remove(nodule); + tube.QueueFree(); + DisconnectTubePlayer.Play(); + } + } + + private void CreateGhostTube(Nodule connectedNodule, Vector2 pos) + { + var tube = Instantiator.Instantiate(); + tube.Position = pos / 2; // TODO WHYYY???? + _connectedTubes.Add(connectedNodule, tube); + GetParent()?.AddChild(tube); } public override void _Process(double delta) { GlobalPosition = GetGlobalMousePosition(); - _tube?.SetTarget(GlobalPosition); + foreach (var (_, tube) in _connectedTubes) + { + tube.SetTarget(GlobalPosition); + } + } + + public override void _UnhandledKeyInput(InputEvent @event) + { + using (@event) + { + if (@event is InputEventKey { Keycode: Key.Escape, Pressed: true }) + { + NoduleManager.Instance.Building = false; + QueueFree(); + } + } } public override void _UnhandledInput(InputEvent @event) @@ -27,9 +74,20 @@ public partial class BuildGhost : Node2D { if (@event is InputEventMouseButton { Pressed: false, ButtonIndex: MouseButton.Left }) { + NoduleManager.Instance.Building = false; OnBuild?.Invoke(GlobalPosition); - _tube?.QueueFree(); + var nodule = Instantiator.Instantiate(); + + nodule.Position = Position; + GetParent()?.AddChild(nodule); + + foreach (var (_, tube) in _connectedTubes) + { + tube.QueueFree(); + } + + _connectedTubes.Clear(); QueueFree(); GetViewport().SetInputAsHandled(); diff --git a/src/Gameplay/BuildGhost.tscn b/src/Gameplay/BuildGhost.tscn index 39ed100..788dc5e 100644 --- a/src/Gameplay/BuildGhost.tscn +++ b/src/Gameplay/BuildGhost.tscn @@ -1,12 +1,65 @@ [gd_scene format=3 uid="uid://c3n70a52kk34f"] [ext_resource type="Script" uid="uid://ck5yw760bu8sb" path="res://src/Gameplay/BuildGhost.cs" id="1_ahcoi"] -[ext_resource type="Texture2D" uid="uid://ddduid7esr36f" path="res://assets/icon.svg" id="2_uo42j"] +[ext_resource type="Texture2D" uid="uid://cecg47efx7gw8" path="res://assets/Sprite-0001.png" id="2_uo42j"] +[ext_resource type="AudioStream" uid="uid://mj8wvuwfc6o7" path="res://assets/sfx/tube_disconnect.wav" id="3_nxaxp"] +[ext_resource type="AudioStream" uid="uid://bxxi7grsubvgm" path="res://assets/sfx/tube_connect.wav" id="3_quiac"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_uo42j"] +atlas = ExtResource("2_uo42j") +region = Rect2(0, 0, 32, 32) + +[sub_resource type="AtlasTexture" id="AtlasTexture_nxaxp"] +atlas = ExtResource("2_uo42j") +region = Rect2(32, 0, 32, 32) + +[sub_resource type="AtlasTexture" id="AtlasTexture_quiac"] +atlas = ExtResource("2_uo42j") +region = Rect2(64, 0, 32, 32) + +[sub_resource type="SpriteFrames" id="SpriteFrames_vecmk"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_uo42j") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_nxaxp") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_quiac") +}], +"loop": true, +"name": &"default", +"speed": 5.0 +}] + +[sub_resource type="CircleShape2D" id="CircleShape2D_uo42j"] +radius = 96.38 [node name="BuildGhost" type="Node2D" unique_id=150653292] script = ExtResource("1_ahcoi") -[node name="Sprite2D" type="Sprite2D" parent="." unique_id=218448453] -modulate = Color(0.32941177, 0.29411766, 0.2901961, 0.5764706) -scale = Vector2(0.3, 0.3) -texture = ExtResource("2_uo42j") +[node name="Sprite2D" type="AnimatedSprite2D" parent="." unique_id=260566565] +self_modulate = Color(0.1752002, 0.36830294, 0.26058322, 0.50980395) +texture_filter = 1 +sprite_frames = SubResource("SpriteFrames_vecmk") + +[node name="TubeConnectionArea" type="Area2D" parent="." unique_id=2116427547] +unique_name_in_owner = true +collision_layer = 2 +collision_mask = 2 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="TubeConnectionArea" unique_id=1558952717] +shape = SubResource("CircleShape2D_uo42j") +debug_color = Color(0.38922516, 0.6054754, 0.25354394, 0.41960785) + +[node name="ConnectTubePlayer" type="AudioStreamPlayer" parent="." unique_id=111889028] +unique_name_in_owner = true +stream = ExtResource("3_quiac") +bus = &"SoundFX" + +[node name="DisconnectTubePlayer" type="AudioStreamPlayer" parent="." unique_id=1165411609] +unique_name_in_owner = true +stream = ExtResource("3_nxaxp") +bus = &"SoundFX" diff --git a/src/Gameplay/TubeManager.cs b/src/Gameplay/NoduleManager.cs similarity index 84% rename from src/Gameplay/TubeManager.cs rename to src/Gameplay/NoduleManager.cs index 8fdbf98..fc317fd 100644 --- a/src/Gameplay/TubeManager.cs +++ b/src/Gameplay/NoduleManager.cs @@ -4,22 +4,17 @@ using Slimepire.Gameplay.Nodules; namespace Slimepire.Gameplay; [Singleton] -public partial class TubeManager +public partial class NoduleManager { - private Nodule? _root; + public bool Building { get; set; } - private List _nodules = []; - private HashSet _connections = []; - private Dictionary _tubeConnections = new(); - private List _tubes = []; + private readonly List _nodules = []; + private readonly HashSet _connections = []; + private readonly Dictionary _tubeConnections = new(); + private readonly List _tubes = []; public void RegisterNodule(Nodule nodule) { - if (nodule.IsRoot) - { - _root = nodule; - } - _nodules.Add(nodule); UpdateNoduleConnections(); diff --git a/src/Gameplay/TubeManager.cs.uid b/src/Gameplay/NoduleManager.cs.uid similarity index 100% rename from src/Gameplay/TubeManager.cs.uid rename to src/Gameplay/NoduleManager.cs.uid diff --git a/src/Gameplay/Nodules/Nodule.cs b/src/Gameplay/Nodules/Nodule.cs index 29dc86c..c886af2 100644 --- a/src/Gameplay/Nodules/Nodule.cs +++ b/src/Gameplay/Nodules/Nodule.cs @@ -5,11 +5,6 @@ namespace Slimepire.Gameplay.Nodules; [SceneTree] public partial class Nodule : Node2D { - [Export] - public bool IsRoot; - - private BuildGhost? _ghost; - private bool _mouseInsideClickArea; private bool _clickedInside; @@ -26,7 +21,7 @@ public partial class Nodule : Node2D TubeConnectionArea.AreaEntered += TubeConnectionAreaOnAreaEntered; TubeConnectionArea.AreaExited += TubeConnectionAreaOnAreaExited; - TubeManager.Instance.RegisterNodule(this); + NoduleManager.Instance.RegisterNodule(this); } private void TubeConnectionAreaOnAreaEntered(Area2D area) @@ -34,7 +29,7 @@ public partial class Nodule : Node2D if (area.GetParent() is Nodule nodule) { Connections.Add(nodule); - TubeManager.Instance.Update(); + NoduleManager.Instance.Update(); } } @@ -68,23 +63,24 @@ public partial class Nodule : Node2D _mouseInsideClickArea = false; // ghost == null check probably unnecessary - if (_clickedInside && _ghost == null) + if (_clickedInside && !NoduleManager.Instance.Building) { + NoduleManager.Instance.Building = true; _clickedInside = false; _isExpanding = true; - _ghost = Instantiator.Instantiate(); - _ghost.Position = Position; - _ghost.OnBuild += OnBuildComplete; + var ghost = Instantiator.Instantiate(); + ghost.Position = Position; + // ghost.OnBuild += OnBuildComplete; - GetParent()?.AddChild(_ghost); + GetParent()?.AddChild(ghost); } } private void OnBuildComplete(Vector2 pos) { + NoduleManager.Instance.Building = false; _isExpanding = false; - _ghost = null; var nodule = Instantiator.Instantiate(); diff --git a/src/Gameplay/Nodules/Nodule.tscn b/src/Gameplay/Nodules/Nodule.tscn index 39b6bab..58db5d9 100644 --- a/src/Gameplay/Nodules/Nodule.tscn +++ b/src/Gameplay/Nodules/Nodule.tscn @@ -58,6 +58,8 @@ frame_progress = 0.9100785 [node name="TubeConnectionArea" type="Area2D" parent="." unique_id=339547035] unique_name_in_owner = true +collision_layer = 2 +collision_mask = 2 [node name="CollisionShape2D" type="CollisionShape2D" parent="TubeConnectionArea" unique_id=234655540] shape = SubResource("CircleShape2D_x44k2") diff --git a/src/Gameplay/Tube.cs b/src/Gameplay/Tube.cs index 06ba6fc..1dcb5b7 100644 --- a/src/Gameplay/Tube.cs +++ b/src/Gameplay/Tube.cs @@ -11,7 +11,7 @@ public partial class Tube : Node2D private void GenerateTube() { - float maxLength = 200; + float maxLength = 180; // Generate 5 points from origin to Target var diff = Target.Position - Position;