From cca539dc323248adadd72af0355c506ab3651a4b Mon Sep 17 00:00:00 2001 From: Jens Becker Date: Wed, 17 Jun 2026 09:45:25 +0200 Subject: [PATCH] init --- .editorconfig | 4 ++ .gitattributes | 2 + .gitignore | 6 ++ Slimepire.csproj | 12 ++++ Slimepire.sln | 19 ++++++ Slimepire.sln.DotSettings.user | 4 ++ assets/Sprite-0001.aseprite | Bin 0 -> 874 bytes assets/Sprite-0001.png | Bin 0 -> 603 bytes assets/Sprite-0001.png.import | 40 ++++++++++++ assets/blob.png | Bin 0 -> 1971 bytes assets/blob.png.import | 40 ++++++++++++ assets/icon.svg | 1 + assets/icon.svg.import | 43 +++++++++++++ global.json | 7 +++ project.godot | 68 ++++++++++++++++++++ src/Core/GameInputMap.cs | 6 ++ src/Core/GameInputMap.cs.uid | 1 + src/Core/MainGame.cs | 40 ++++++++++++ src/Core/MainGame.cs.uid | 1 + src/Core/MainGame.tscn | 62 ++++++++++++++++++ src/Gameplay/BuildGhost.cs | 39 ++++++++++++ src/Gameplay/BuildGhost.cs.uid | 1 + src/Gameplay/BuildGhost.tscn | 12 ++++ src/Gameplay/Camera.cs | 27 ++++++++ src/Gameplay/Camera.cs.uid | 1 + src/Gameplay/Nodules/Nodule.cs | 96 ++++++++++++++++++++++++++++ src/Gameplay/Nodules/Nodule.cs.uid | 1 + src/Gameplay/Nodules/Nodule.tscn | 64 +++++++++++++++++++ src/Gameplay/Nodules/nodule.gd | 9 +++ src/Gameplay/Nodules/nodule.gd.uid | 1 + src/Gameplay/Tube.cs | 47 ++++++++++++++ src/Gameplay/Tube.cs.uid | 1 + src/Gameplay/Tube.tscn | 25 ++++++++ src/Gameplay/TubeManager.cs | 98 +++++++++++++++++++++++++++++ src/Gameplay/TubeManager.cs.uid | 1 + src/Levels/BaseLevel.cs | 9 +++ src/Levels/BaseLevel.cs.uid | 1 + src/Levels/DemoLevel.cs | 9 +++ src/Levels/DemoLevel.cs.uid | 1 + src/Levels/DemoLevel.tscn | 32 ++++++++++ 40 files changed, 831 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 Slimepire.csproj create mode 100644 Slimepire.sln create mode 100644 Slimepire.sln.DotSettings.user create mode 100644 assets/Sprite-0001.aseprite create mode 100644 assets/Sprite-0001.png create mode 100644 assets/Sprite-0001.png.import create mode 100644 assets/blob.png create mode 100644 assets/blob.png.import create mode 100644 assets/icon.svg create mode 100644 assets/icon.svg.import create mode 100644 global.json create mode 100644 project.godot create mode 100644 src/Core/GameInputMap.cs create mode 100644 src/Core/GameInputMap.cs.uid create mode 100644 src/Core/MainGame.cs create mode 100644 src/Core/MainGame.cs.uid create mode 100644 src/Core/MainGame.tscn create mode 100644 src/Gameplay/BuildGhost.cs create mode 100644 src/Gameplay/BuildGhost.cs.uid create mode 100644 src/Gameplay/BuildGhost.tscn create mode 100644 src/Gameplay/Camera.cs create mode 100644 src/Gameplay/Camera.cs.uid create mode 100644 src/Gameplay/Nodules/Nodule.cs create mode 100644 src/Gameplay/Nodules/Nodule.cs.uid create mode 100644 src/Gameplay/Nodules/Nodule.tscn create mode 100644 src/Gameplay/Nodules/nodule.gd create mode 100644 src/Gameplay/Nodules/nodule.gd.uid create mode 100644 src/Gameplay/Tube.cs create mode 100644 src/Gameplay/Tube.cs.uid create mode 100644 src/Gameplay/Tube.tscn create mode 100644 src/Gameplay/TubeManager.cs create mode 100644 src/Gameplay/TubeManager.cs.uid create mode 100644 src/Levels/BaseLevel.cs create mode 100644 src/Levels/BaseLevel.cs.uid create mode 100644 src/Levels/DemoLevel.cs create mode 100644 src/Levels/DemoLevel.cs.uid create mode 100644 src/Levels/DemoLevel.tscn diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0adc095 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Godot 4+ specific ignores +.godot/ +/android/ + +.vscode +.idea diff --git a/Slimepire.csproj b/Slimepire.csproj new file mode 100644 index 0000000..985adbb --- /dev/null +++ b/Slimepire.csproj @@ -0,0 +1,12 @@ + + + net10.0 + net9.0 + true + enable + enable + + + + + diff --git a/Slimepire.sln b/Slimepire.sln new file mode 100644 index 0000000..fa26cc8 --- /dev/null +++ b/Slimepire.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Slimepire", "Slimepire.csproj", "{4D5460EF-2589-4714-8A0D-1A2238B0058F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + ExportDebug|Any CPU = ExportDebug|Any CPU + ExportRelease|Any CPU = ExportRelease|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4D5460EF-2589-4714-8A0D-1A2238B0058F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D5460EF-2589-4714-8A0D-1A2238B0058F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D5460EF-2589-4714-8A0D-1A2238B0058F}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {4D5460EF-2589-4714-8A0D-1A2238B0058F}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {4D5460EF-2589-4714-8A0D-1A2238B0058F}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {4D5460EF-2589-4714-8A0D-1A2238B0058F}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + EndGlobalSection +EndGlobal diff --git a/Slimepire.sln.DotSettings.user b/Slimepire.sln.DotSettings.user new file mode 100644 index 0000000..a5195fb --- /dev/null +++ b/Slimepire.sln.DotSettings.user @@ -0,0 +1,4 @@ + + ForceIncluded + ForceIncluded + ForceIncluded \ No newline at end of file diff --git a/assets/Sprite-0001.aseprite b/assets/Sprite-0001.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..2e9b0747fd22f49b343ba8cd5720b7a25dda8bd8 GIT binary patch literal 874 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 diff --git a/assets/icon.svg.import b/assets/icon.svg.import new file mode 100644 index 0000000..d462b16 --- /dev/null +++ b/assets/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ddduid7esr36f" +path="res://.godot/imported/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icon.svg" +dest_files=["res://.godot/imported/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/global.json b/global.json new file mode 100644 index 0000000..f4fd385 --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "9.0.0", + "rollForward": "latestMajor", + "allowPrerelease": true + } +} \ No newline at end of file diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..37570c2 --- /dev/null +++ b/project.godot @@ -0,0 +1,68 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Slimepire" +run/main_scene="uid://drxbsnqoi4wmw" +config/features=PackedStringArray("4.6", "C#", "Forward Plus") +config/icon="res://assets/icon.svg" + +[display] + +window/size/viewport_width=480 +window/size/viewport_height=320 +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" + +[dotnet] + +project/assembly_name="Slimepire" + +[editor] + +naming/scene_name_casing=1 + +[file_customization] + +folder_colors={ +"res://src/Debug/": "yellow" +} + +[input] + +cam_left={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +cam_right={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} +cam_up={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +cam_down={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} + +[physics] + +3d/physics_engine="Jolt Physics" + +[rendering] + +rendering_device/driver.windows="d3d12" diff --git a/src/Core/GameInputMap.cs b/src/Core/GameInputMap.cs new file mode 100644 index 0000000..3f530ba --- /dev/null +++ b/src/Core/GameInputMap.cs @@ -0,0 +1,6 @@ +using Godot; + +namespace Slimepire.Core; + +[InputMap] +public partial class GameInputMap { } diff --git a/src/Core/GameInputMap.cs.uid b/src/Core/GameInputMap.cs.uid new file mode 100644 index 0000000..890547e --- /dev/null +++ b/src/Core/GameInputMap.cs.uid @@ -0,0 +1 @@ +uid://cta7vf1tc8mrp diff --git a/src/Core/MainGame.cs b/src/Core/MainGame.cs new file mode 100644 index 0000000..99c9c6a --- /dev/null +++ b/src/Core/MainGame.cs @@ -0,0 +1,40 @@ +using Godot; +using Slimepire.Levels; + +namespace Slimepire.Core; + +[SceneTree] +public partial class MainGame : Node +{ + private BaseLevel? _currentLevel; + + public override void _Ready() + { + GD.Print("MainGame ready"); + CallDeferred(nameof(LoadLevel), "res://src/Levels/DemoLevel.tscn"); + } + + private async void LoadLevel(string level) + { + _currentLevel?.QueueFree(); + _currentLevel = null; + + await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame); + + var newLevelPacked = ResourceLoader.Load(level); + if (newLevelPacked == null) + { + GD.PushError($"Could not load packed scene {level}"); + return; + } + + _currentLevel = newLevelPacked.Instantiate(); + if (_currentLevel == null) + { + GD.PushError($"Could not load level {level}"); + return; + } + + LevelRoot.AddChild(_currentLevel); + } +} diff --git a/src/Core/MainGame.cs.uid b/src/Core/MainGame.cs.uid new file mode 100644 index 0000000..cff2265 --- /dev/null +++ b/src/Core/MainGame.cs.uid @@ -0,0 +1 @@ +uid://b0u4agvdxawp diff --git a/src/Core/MainGame.tscn b/src/Core/MainGame.tscn new file mode 100644 index 0000000..faf74cd --- /dev/null +++ b/src/Core/MainGame.tscn @@ -0,0 +1,62 @@ +[gd_scene format=3 uid="uid://drxbsnqoi4wmw"] + +[ext_resource type="Script" uid="uid://b0u4agvdxawp" path="res://src/Core/MainGame.cs" id="1_g6xmk"] + +[node name="Main Game" type="Node" unique_id=1541697061] +process_mode = 3 +script = ExtResource("1_g6xmk") + +[node name="Systems" type="Node" parent="." unique_id=71014693] + +[node name="World" type="Node2D" parent="." unique_id=436280701] +process_mode = 1 + +[node name="LevelRoot" type="Node2D" parent="World" unique_id=1066129272] +unique_name_in_owner = true + +[node name="EntityRoot" type="Node2D" parent="World" unique_id=706944944] +unique_name_in_owner = true + +[node name="HudLayer" type="CanvasLayer" parent="." unique_id=407027346] +process_mode = 1 +layer = 10 + +[node name="HudRoot" type="Control" parent="HudLayer" unique_id=428309734] +unique_name_in_owner = true +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="PauseLayer" type="CanvasLayer" parent="." unique_id=72018978] +process_mode = 2 +layer = 20 + +[node name="PauseRoot" type="Control" parent="PauseLayer" unique_id=171929713] +unique_name_in_owner = true +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="TransitionLayer" type="CanvasLayer" parent="." unique_id=1737536414] +process_mode = 3 +layer = 100 + +[node name="TransitionRoot" type="Control" parent="TransitionLayer" unique_id=78768800] +unique_name_in_owner = true +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="DebugLayer" type="CanvasLayer" parent="." unique_id=1550774256] +process_mode = 3 +layer = 128 + +[node name="DebugRoot" type="Control" parent="DebugLayer" unique_id=1697594173] +unique_name_in_owner = true +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 diff --git a/src/Gameplay/BuildGhost.cs b/src/Gameplay/BuildGhost.cs new file mode 100644 index 0000000..edcfd65 --- /dev/null +++ b/src/Gameplay/BuildGhost.cs @@ -0,0 +1,39 @@ +using Godot; + +namespace Slimepire.Gameplay; + +[SceneTree] +public partial class BuildGhost : Node2D +{ + public event Action? OnBuild; + private Tube? _tube; + + public override void _Ready() + { + _tube = Instantiator.Instantiate(); + _tube.Position = Position / 2; // TODO WHYYY???? + GetParent()?.AddChild(_tube); + } + + public override void _Process(double delta) + { + GlobalPosition = GetGlobalMousePosition(); + _tube?.SetTarget(GlobalPosition); + } + + public override void _UnhandledInput(InputEvent @event) + { + using (@event) + { + if (@event is InputEventMouseButton { Pressed: false, ButtonIndex: MouseButton.Left }) + { + OnBuild?.Invoke(GlobalPosition); + + _tube?.QueueFree(); + QueueFree(); + + GetViewport().SetInputAsHandled(); + } + } + } +} diff --git a/src/Gameplay/BuildGhost.cs.uid b/src/Gameplay/BuildGhost.cs.uid new file mode 100644 index 0000000..ed4821f --- /dev/null +++ b/src/Gameplay/BuildGhost.cs.uid @@ -0,0 +1 @@ +uid://ck5yw760bu8sb diff --git a/src/Gameplay/BuildGhost.tscn b/src/Gameplay/BuildGhost.tscn new file mode 100644 index 0000000..39ed100 --- /dev/null +++ b/src/Gameplay/BuildGhost.tscn @@ -0,0 +1,12 @@ +[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"] + +[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") diff --git a/src/Gameplay/Camera.cs b/src/Gameplay/Camera.cs new file mode 100644 index 0000000..737786b --- /dev/null +++ b/src/Gameplay/Camera.cs @@ -0,0 +1,27 @@ +using Godot; +using Slimepire.Core; + +namespace Slimepire.Gameplay; + +public partial class Camera : Camera2D +{ + [Export] + public float CameraSpeed = 500; + + private Vector2 _direction; + + public override void _UnhandledKeyInput(InputEvent @event) + { + _direction = Input.GetVector( + GameInputMap.CamLeft, + GameInputMap.CamRight, + GameInputMap.CamUp, + GameInputMap.CamDown + ); + } + + public override void _Process(double delta) + { + Position += _direction * CameraSpeed * (float)delta; + } +} diff --git a/src/Gameplay/Camera.cs.uid b/src/Gameplay/Camera.cs.uid new file mode 100644 index 0000000..c0a569a --- /dev/null +++ b/src/Gameplay/Camera.cs.uid @@ -0,0 +1 @@ +uid://cdgi3y0sm3rt1 diff --git a/src/Gameplay/Nodules/Nodule.cs b/src/Gameplay/Nodules/Nodule.cs new file mode 100644 index 0000000..29dc86c --- /dev/null +++ b/src/Gameplay/Nodules/Nodule.cs @@ -0,0 +1,96 @@ +using Godot; + +namespace Slimepire.Gameplay.Nodules; + +[SceneTree] +public partial class Nodule : Node2D +{ + [Export] + public bool IsRoot; + + private BuildGhost? _ghost; + + private bool _mouseInsideClickArea; + private bool _clickedInside; + + public readonly List Connections = []; + + // todo remove? + private bool _isExpanding; + + public override void _Ready() + { + ClickArea.MouseEntered += ClickAreaOnMouseEntered; + ClickArea.MouseExited += ClickAreaOnMouseExited; + + TubeConnectionArea.AreaEntered += TubeConnectionAreaOnAreaEntered; + TubeConnectionArea.AreaExited += TubeConnectionAreaOnAreaExited; + + TubeManager.Instance.RegisterNodule(this); + } + + private void TubeConnectionAreaOnAreaEntered(Area2D area) + { + if (area.GetParent() is Nodule nodule) + { + Connections.Add(nodule); + TubeManager.Instance.Update(); + } + } + + private void TubeConnectionAreaOnAreaExited(Area2D area) + { + if (area.GetParent() is Nodule nodule) + { + Connections.Remove(nodule); + } + } + + public override void _UnhandledInput(InputEvent @event) + { + using (@event) + { + if (@event is InputEventMouseButton && @event.IsPressed() && _mouseInsideClickArea) + { + _clickedInside = true; + GetViewport().SetInputAsHandled(); + } + } + } + + private void ClickAreaOnMouseEntered() + { + _mouseInsideClickArea = true; + } + + private void ClickAreaOnMouseExited() + { + _mouseInsideClickArea = false; + + // ghost == null check probably unnecessary + if (_clickedInside && _ghost == null) + { + _clickedInside = false; + _isExpanding = true; + + _ghost = Instantiator.Instantiate(); + _ghost.Position = Position; + _ghost.OnBuild += OnBuildComplete; + + GetParent()?.AddChild(_ghost); + } + } + + private void OnBuildComplete(Vector2 pos) + { + _isExpanding = false; + _ghost = null; + + var nodule = Instantiator.Instantiate(); + + nodule.Position = pos; + Connections.Add(nodule); + nodule.Connections.Add(this); + GetParent()?.AddChild(nodule); + } +} diff --git a/src/Gameplay/Nodules/Nodule.cs.uid b/src/Gameplay/Nodules/Nodule.cs.uid new file mode 100644 index 0000000..b047e8a --- /dev/null +++ b/src/Gameplay/Nodules/Nodule.cs.uid @@ -0,0 +1 @@ +uid://cmpl0if164dba diff --git a/src/Gameplay/Nodules/Nodule.tscn b/src/Gameplay/Nodules/Nodule.tscn new file mode 100644 index 0000000..39b6bab --- /dev/null +++ b/src/Gameplay/Nodules/Nodule.tscn @@ -0,0 +1,64 @@ +[gd_scene format=3 uid="uid://cnl6t8o4mh0j3"] + +[ext_resource type="Script" uid="uid://cmpl0if164dba" path="res://src/Gameplay/Nodules/Nodule.cs" id="1_yembh"] +[ext_resource type="Texture2D" uid="uid://cecg47efx7gw8" path="res://assets/Sprite-0001.png" id="2_7qt20"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_7qt20"] +radius = 15.0 + +[sub_resource type="AtlasTexture" id="AtlasTexture_7qt20"] +atlas = ExtResource("2_7qt20") +region = Rect2(32, 0, 32, 32) + +[sub_resource type="AtlasTexture" id="AtlasTexture_x44k2"] +atlas = ExtResource("2_7qt20") +region = Rect2(0, 0, 32, 32) + +[sub_resource type="AtlasTexture" id="AtlasTexture_inlcu"] +atlas = ExtResource("2_7qt20") +region = Rect2(64, 0, 32, 32) + +[sub_resource type="SpriteFrames" id="SpriteFrames_xyjsl"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_7qt20") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_x44k2") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_inlcu") +}], +"loop": true, +"name": &"default", +"speed": 2.0 +}] + +[sub_resource type="CircleShape2D" id="CircleShape2D_x44k2"] +radius = 96.38 + +[node name="Nodule" type="Node2D" unique_id=1637542829] +z_index = 1 +script = ExtResource("1_yembh") + +[node name="ClickArea" type="Area2D" parent="." unique_id=120357381] +unique_name_in_owner = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="ClickArea" unique_id=2005066434] +shape = SubResource("CircleShape2D_7qt20") + +[node name="Blob" type="AnimatedSprite2D" parent="." unique_id=190397869] +modulate = Color(0.34855, 0.6165254, 0.5102762, 1) +texture_filter = 1 +sprite_frames = SubResource("SpriteFrames_xyjsl") +autoplay = "default" +frame = 1 +frame_progress = 0.9100785 + +[node name="TubeConnectionArea" type="Area2D" parent="." unique_id=339547035] +unique_name_in_owner = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="TubeConnectionArea" unique_id=234655540] +shape = SubResource("CircleShape2D_x44k2") +debug_color = Color(0.38922516, 0.6054754, 0.25354394, 0.41960785) diff --git a/src/Gameplay/Nodules/nodule.gd b/src/Gameplay/Nodules/nodule.gd new file mode 100644 index 0000000..7351c6f --- /dev/null +++ b/src/Gameplay/Nodules/nodule.gd @@ -0,0 +1,9 @@ +extends Node2D + +var clicked_inside := false + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseButton: + if event.button_index == MOUSE_BUTTON_LEFT and event.pressed == true: + clicked_inside = true + get_viewport().set_input_as_handled() \ No newline at end of file diff --git a/src/Gameplay/Nodules/nodule.gd.uid b/src/Gameplay/Nodules/nodule.gd.uid new file mode 100644 index 0000000..095e892 --- /dev/null +++ b/src/Gameplay/Nodules/nodule.gd.uid @@ -0,0 +1 @@ +uid://bvl0487nflq0q diff --git a/src/Gameplay/Tube.cs b/src/Gameplay/Tube.cs new file mode 100644 index 0000000..06ba6fc --- /dev/null +++ b/src/Gameplay/Tube.cs @@ -0,0 +1,47 @@ +using Godot; + +namespace Slimepire.Gameplay; + +[SceneTree] +[Tool] +public partial class Tube : Node2D +{ + [ExportToolButton("Generate Tube")] + private Callable GenerateTubeButton => Callable.From(GenerateTube); + + private void GenerateTube() + { + float maxLength = 200; + + // Generate 5 points from origin to Target + var diff = Target.Position - Position; + + var points = new Vector2[5]; + points[0] = Position; + for (var i = 1; i < 4; i++) + { + points[i] = points[i - 1] + diff / 5; + } + points[4] = Target.Position; + + var thickness = (-1 / (maxLength / 2f)) * diff.Length() + 2f; + + Line2D.Points = points; + Line2D.WidthCurve = new Curve(); + Line2D.WidthCurve.AddPoint(new Vector2(0, 1)); + Line2D.WidthCurve.AddPoint(new Vector2(0.5f, thickness)); + Line2D.WidthCurve.AddPoint(new Vector2(1, 1)); + Line2D.WidthCurve.Bake(); + } + + public void SetTarget(Vector2 newTarget) + { + Target.GlobalPosition = newTarget; + GenerateTube(); + } + + public override void _Ready() + { + Line2D.Points = []; + } +} diff --git a/src/Gameplay/Tube.cs.uid b/src/Gameplay/Tube.cs.uid new file mode 100644 index 0000000..c972bb5 --- /dev/null +++ b/src/Gameplay/Tube.cs.uid @@ -0,0 +1 @@ +uid://dwunaa303epy6 diff --git a/src/Gameplay/Tube.tscn b/src/Gameplay/Tube.tscn new file mode 100644 index 0000000..46b1f29 --- /dev/null +++ b/src/Gameplay/Tube.tscn @@ -0,0 +1,25 @@ +[gd_scene format=3 uid="uid://b3nn42ralc31r"] + +[ext_resource type="Script" uid="uid://dwunaa303epy6" path="res://src/Gameplay/Tube.cs" id="1_76hpl"] + +[sub_resource type="Curve" id="Curve_0lkqj"] +_limits = [0.0, 2.0, 0.0, 1.0] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.5, 1.4598354), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0] +point_count = 3 + +[node name="Tube" type="Node2D" unique_id=226677696] +script = ExtResource("1_76hpl") + +[node name="Line2D" type="Line2D" parent="." unique_id=1553055261] +unique_name_in_owner = true +z_as_relative = false +width = 8.0 +width_curve = SubResource("Curve_0lkqj") +default_color = Color(0.30588236, 0.4862745, 0.23921569, 0.5568628) +joint_mode = 2 +begin_cap_mode = 2 +end_cap_mode = 2 + +[node name="Target" type="Marker2D" parent="." unique_id=630564540] +unique_name_in_owner = true +position = Vector2(47, 66) diff --git a/src/Gameplay/TubeManager.cs b/src/Gameplay/TubeManager.cs new file mode 100644 index 0000000..8fdbf98 --- /dev/null +++ b/src/Gameplay/TubeManager.cs @@ -0,0 +1,98 @@ +using Godot; +using Slimepire.Gameplay.Nodules; + +namespace Slimepire.Gameplay; + +[Singleton] +public partial class TubeManager +{ + private Nodule? _root; + + private List _nodules = []; + private HashSet _connections = []; + private Dictionary _tubeConnections = new(); + private List _tubes = []; + + public void RegisterNodule(Nodule nodule) + { + if (nodule.IsRoot) + { + _root = nodule; + } + + _nodules.Add(nodule); + + UpdateNoduleConnections(); + UpdateTubes(); + } + + public void Update() + { + GD.Print("UPDATE"); + UpdateNoduleConnections(); + UpdateTubes(); + } + + private void UpdateNoduleConnections() + { + foreach (var n in _nodules) + { + foreach (var c in n.Connections) + { + _connections.Add(new NoduleConnection(n, c)); + } + } + + GD.Print($"Connections: {_connections.Count}"); + } + + private void UpdateTubes() + { + foreach (var c in _connections) + { + if (!_tubeConnections.ContainsKey(c)) + { + GD.Print("Hello?"); + var tube = Instantiator.Instantiate(); + _tubes.Add(tube); + _tubeConnections.Add(c, tube); + // tube.GlobalPosition = c.A.GlobalPosition; + c.A.AddChild(tube); + + tube.SetTarget(c.B.Position); + } + } + } + + private record NoduleConnection + { + public Nodule A { get; init; } + public Nodule B { get; init; } + + public NoduleConnection(Nodule a, Nodule b) + { + if (a.GetHashCode() <= b.GetHashCode()) + { + A = a; + B = b; + } + else + { + A = b; + B = a; + } + } + + public virtual bool Equals(NoduleConnection? other) + { + if (other is null) + return false; + return ReferenceEquals(A, other.A) && ReferenceEquals(B, other.B); + } + + public override int GetHashCode() + { + return HashCode.Combine(A, B); + } + } +} diff --git a/src/Gameplay/TubeManager.cs.uid b/src/Gameplay/TubeManager.cs.uid new file mode 100644 index 0000000..04fc62e --- /dev/null +++ b/src/Gameplay/TubeManager.cs.uid @@ -0,0 +1 @@ +uid://bxyquhfnvob64 diff --git a/src/Levels/BaseLevel.cs b/src/Levels/BaseLevel.cs new file mode 100644 index 0000000..d8ce27f --- /dev/null +++ b/src/Levels/BaseLevel.cs @@ -0,0 +1,9 @@ +using Godot; + +namespace Slimepire.Levels; + +[GlobalClass] +public abstract partial class BaseLevel : Node +{ + protected abstract Camera2D Camera { get; } +} diff --git a/src/Levels/BaseLevel.cs.uid b/src/Levels/BaseLevel.cs.uid new file mode 100644 index 0000000..fa2974f --- /dev/null +++ b/src/Levels/BaseLevel.cs.uid @@ -0,0 +1 @@ +uid://durlongh484is diff --git a/src/Levels/DemoLevel.cs b/src/Levels/DemoLevel.cs new file mode 100644 index 0000000..756f843 --- /dev/null +++ b/src/Levels/DemoLevel.cs @@ -0,0 +1,9 @@ +using Godot; + +namespace Slimepire.Levels; + +[SceneTree] +public partial class DemoLevel : BaseLevel +{ + protected override Camera2D Camera => _.Camera; +} diff --git a/src/Levels/DemoLevel.cs.uid b/src/Levels/DemoLevel.cs.uid new file mode 100644 index 0000000..0408c66 --- /dev/null +++ b/src/Levels/DemoLevel.cs.uid @@ -0,0 +1 @@ +uid://c8l12dlpexosv diff --git a/src/Levels/DemoLevel.tscn b/src/Levels/DemoLevel.tscn new file mode 100644 index 0000000..2ae7d51 --- /dev/null +++ b/src/Levels/DemoLevel.tscn @@ -0,0 +1,32 @@ +[gd_scene format=3 uid="uid://bqv3sg03tcv71"] + +[ext_resource type="Script" uid="uid://c8l12dlpexosv" path="res://src/Levels/DemoLevel.cs" id="1_l2cn0"] +[ext_resource type="Script" uid="uid://cdgi3y0sm3rt1" path="res://src/Gameplay/Camera.cs" id="2_mxa1b"] +[ext_resource type="PackedScene" uid="uid://cnl6t8o4mh0j3" path="res://src/Gameplay/Nodules/Nodule.tscn" id="3_qhkhc"] + +[sub_resource type="LabelSettings" id="LabelSettings_l2cn0"] +font_size = 107 + +[node name="DemoLevel" type="Node2D" unique_id=1583216522] +script = ExtResource("1_l2cn0") + +[node name="Camera" type="Camera2D" parent="." unique_id=1348670701] +script = ExtResource("2_mxa1b") + +[node name="Label" type="Label" parent="." unique_id=1452841224] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -331.0 +offset_top = -221.0 +offset_right = 320.0 +offset_bottom = -74.0 +grow_horizontal = 2 +grow_vertical = 2 +text = "DEMO LEVEL" +label_settings = SubResource("LabelSettings_l2cn0") + +[node name="Nodule" parent="." unique_id=1637542829 instance=ExtResource("3_qhkhc")] +IsRoot = true