diff --git a/Slimepire.sln.DotSettings.user b/Slimepire.sln.DotSettings.user index 2c38479..4a33232 100644 --- a/Slimepire.sln.DotSettings.user +++ b/Slimepire.sln.DotSettings.user @@ -1,5 +1,6 @@  ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded \ No newline at end of file diff --git a/assets/gradient_linear.png b/assets/gradient_linear.png new file mode 100644 index 0000000..d332608 Binary files /dev/null and b/assets/gradient_linear.png differ diff --git a/assets/gradient_linear.png.import b/assets/gradient_linear.png.import new file mode 100644 index 0000000..3198bc4 --- /dev/null +++ b/assets/gradient_linear.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b2y7oc421yoyd" +path="res://.godot/imported/gradient_linear.png-f1664a719d29c2fd7ef75dfe3ee8f4a4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/gradient_linear.png" +dest_files=["res://.godot/imported/gradient_linear.png-f1664a719d29c2fd7ef75dfe3ee8f4a4.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 diff --git a/assets/metaball.kra b/assets/metaball.kra new file mode 100644 index 0000000..cf8bf3d Binary files /dev/null and b/assets/metaball.kra differ diff --git a/assets/metaball.kra~ b/assets/metaball.kra~ new file mode 100644 index 0000000..40eda39 Binary files /dev/null and b/assets/metaball.kra~ differ diff --git a/assets/metaball.png b/assets/metaball.png new file mode 100644 index 0000000..6762a87 Binary files /dev/null and b/assets/metaball.png differ diff --git a/assets/metaball.png.import b/assets/metaball.png.import new file mode 100644 index 0000000..ef8dea6 --- /dev/null +++ b/assets/metaball.png.import @@ -0,0 +1,41 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://byk86jmfv7p64" +path.s3tc="res://.godot/imported/metaball.png-a6b8702ab5ec503295d5f109cf071bd1.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/metaball.png" +dest_files=["res://.godot/imported/metaball.png-a6b8702ab5ec503295d5f109cf071bd1.s3tc.ctex"] + +[params] + +compress/mode=2 +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=true +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=0 diff --git a/assets/metaball.png~ b/assets/metaball.png~ new file mode 100644 index 0000000..1feef2a Binary files /dev/null and b/assets/metaball.png~ differ diff --git a/assets/shaders/metaball.gdshader b/assets/shaders/metaball.gdshader new file mode 100644 index 0000000..9b19aad --- /dev/null +++ b/assets/shaders/metaball.gdshader @@ -0,0 +1,37 @@ +shader_type canvas_item; + +varying vec2 quad_uv; + +uniform vec2 ball_0; +uniform vec2 ball_1; +uniform vec2 ball_2; +uniform vec2 rect_size = vec2(1920, 1080); +uniform float ball_radius = 12.0; +uniform float cam_zoom = 1.0; +uniform vec2 cam_pos = vec2(0.0); +uniform float threshold : hint_range(0.0, 1.0) = 0.5; +uniform vec4 color : source_color = vec4(0.3, 0.5, 0.2, 1.0); +uniform sampler2D noise_tex : repeat_enable; + +void vertex() { + quad_uv = UV; +} + +float field(vec2 pos) { + return (ball_radius * cam_zoom) / max(length(quad_uv * rect_size - pos), 1.0); +} + +void fragment() { + float sum = field(ball_0) + field(ball_1) + field(ball_2); + float a = smoothstep(threshold - 0.05, threshold, sum); + + vec2 screen_px = quad_uv * rect_size; + vec2 world_px = (screen_px - rect_size * 0.5) / cam_zoom + cam_pos; + float n1 = texture(noise_tex, world_px * 0.0005).r; + float n2 = texture(noise_tex, world_px * 0.0008 + 0.33).r; + float hue_shift = (n1 - 0.5) * 0.12; + float value_shift = (n2 - 0.5) * 0.15; + vec3 shifted = color.rgb + vec3(hue_shift * 0.5, hue_shift, -hue_shift * 0.5) + value_shift; + + COLOR = vec4(shifted, a * color.a); +} diff --git a/assets/shaders/metaball.gdshader.uid b/assets/shaders/metaball.gdshader.uid new file mode 100644 index 0000000..3b5f419 --- /dev/null +++ b/assets/shaders/metaball.gdshader.uid @@ -0,0 +1 @@ +uid://8xu2s3gyxp0v diff --git a/global.json b/global.json index f4fd385..4ca0782 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "9.0.0", - "rollForward": "latestMajor", - "allowPrerelease": true + "version": "9.0.0", + "rollForward": "latestMajor", + "allowPrerelease": true } -} \ No newline at end of file +} diff --git a/project.godot b/project.godot index 45ccd53..c834f92 100644 --- a/project.godot +++ b/project.godot @@ -21,8 +21,8 @@ buses/default_bus_layout="uid://djkq0k3jsuxcg" [display] -window/size/viewport_width=480 -window/size/viewport_height=320 +window/size/viewport_width=1920 +window/size/viewport_height=1080 window/stretch/mode="canvas_items" window/stretch/aspect="expand" diff --git a/src/Gameplay/GooSubViewPort.cs b/src/Gameplay/GooSubViewPort.cs new file mode 100644 index 0000000..b335231 --- /dev/null +++ b/src/Gameplay/GooSubViewPort.cs @@ -0,0 +1,65 @@ +using Godot; +using Slimepire.Levels; + +public partial class GooSubViewPort : Node +{ + private readonly Vector2[] _worldPositions = + [ + new(400, 300), + new(430, 310), + new(380, 330), + ]; + + private ShaderMaterial _material = null!; + private ColorRect _colorRect = null!; + private DemoLevel _level = null!; + + public override void _Ready() + { + _level = GetParent(); + var canvasLayer = _level.GetNode("CanvasLayer"); + _colorRect = canvasLayer.GetNode("ColorRect"); + + _material = new ShaderMaterial + { + Shader = GD.Load("res://assets/shaders/metaball.gdshader"), + }; + _material.SetShaderParameter("threshold", 0.5f); + _material.SetShaderParameter("color", new Color(0.3f, 0.5f, 0.2f, 1f)); + _material.SetShaderParameter("ball_radius", 12f); + _material.SetShaderParameter("rect_size", GetViewport().GetVisibleRect().Size); + _material.SetShaderParameter("cam_zoom", 1f); + _material.SetShaderParameter("noise_tex", GenerateNoiseTexture(32)); + _colorRect.Material = _material; + } + + public override void _Process(double delta) + { + var cam = _level.Camera; + var viewSize = GetViewport().GetVisibleRect().Size; + + _material.SetShaderParameter("cam_zoom", cam.Zoom.X); + _material.SetShaderParameter("cam_pos", cam.GlobalPosition); + _material.SetShaderParameter("rect_size", GetViewport().GetVisibleRect().Size); + + for (var i = 0; i < _worldPositions.Length && i < 3; i++) + { + var screenPos = (_worldPositions[i] - cam.GlobalPosition) * cam.Zoom.X + viewSize / 2; + _material.SetShaderParameter($"ball_{i}", screenPos); + } + } + + private static ImageTexture GenerateNoiseTexture(int size) + { + var img = Image.CreateEmpty(size, size, false, Image.Format.Rgba8); + var rng = new Random(42); + for (var y = 0; y < size; y++) + for (var x = 0; x < size; x++) + { + var v = (float)rng.NextDouble(); + img.SetPixel(x, y, new Color(v, v, v, 1)); + } + + return ImageTexture.CreateFromImage(img); + } +} diff --git a/src/Gameplay/GooSubViewPort.cs.uid b/src/Gameplay/GooSubViewPort.cs.uid new file mode 100644 index 0000000..fe26544 --- /dev/null +++ b/src/Gameplay/GooSubViewPort.cs.uid @@ -0,0 +1 @@ +uid://bft481hoodv5d diff --git a/src/Gameplay/GooSubViewPort.tscn b/src/Gameplay/GooSubViewPort.tscn new file mode 100644 index 0000000..9589933 --- /dev/null +++ b/src/Gameplay/GooSubViewPort.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://ce2frpb21ct5l"] + +[ext_resource type="Script" uid="uid://bft481hoodv5d" path="res://src/Gameplay/GooSubViewPort.cs" id="1_xo53p"] + +[node name="GooSubViewPort" type="Node" unique_id=348721885] +script = ExtResource("1_xo53p") diff --git a/src/Gameplay/Metaball.cs b/src/Gameplay/Metaball.cs new file mode 100644 index 0000000..2384cc3 --- /dev/null +++ b/src/Gameplay/Metaball.cs @@ -0,0 +1,11 @@ +using System; +using Godot; + +public partial class Metaball : Control +{ + // 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(double delta) { } +} diff --git a/src/Gameplay/Metaball.cs.uid b/src/Gameplay/Metaball.cs.uid new file mode 100644 index 0000000..caf8364 --- /dev/null +++ b/src/Gameplay/Metaball.cs.uid @@ -0,0 +1 @@ +uid://cpj1q44qfwsps diff --git a/src/Gameplay/NoduleManager.cs b/src/Gameplay/NoduleManager.cs index bebea10..cbf1eb8 100644 --- a/src/Gameplay/NoduleManager.cs +++ b/src/Gameplay/NoduleManager.cs @@ -49,14 +49,13 @@ public partial class NoduleManager _aStar.ConnectPoints(nodule.NoduleId, neighbor.NoduleId); } - // Convert any ghost tubes connected to this nodule to real tubes. - // Tubes are not always children of this nodule (depends on hash ordering in NoduleConnection), - // so iterating children alone isn't enough. + // Convert ghost tubes where BOTH sides are now fully constructed foreach (var (conn, tube) in _tubeConnections) { if (tube.IsGhost && (ReferenceEquals(conn.A, nodule) || ReferenceEquals(conn.B, nodule))) { - tube.SetGhost(false); + if (!conn.A.IsConstructing && !conn.B.IsConstructing) + tube.SetGhost(false); } } } diff --git a/src/Gameplay/metaball.tscn b/src/Gameplay/metaball.tscn new file mode 100644 index 0000000..1116c3f --- /dev/null +++ b/src/Gameplay/metaball.tscn @@ -0,0 +1,32 @@ +[gd_scene format=3 uid="uid://ghg1o288grwq"] + +[ext_resource type="Script" uid="uid://cpj1q44qfwsps" path="res://src/Gameplay/Metaball.cs" id="1_jfklr"] +[ext_resource type="Shader" uid="uid://8xu2s3gyxp0v" path="res://assets/shaders/metaball.gdshader" id="2_vvscw"] + +[sub_resource type="ViewportTexture" id="ViewportTexture_vvscw"] +viewport_path = NodePath("SubViewport") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_vvscw"] +resource_local_to_scene = true +shader = ExtResource("2_vvscw") +shader_parameter/metaball_tex = SubResource("ViewportTexture_vvscw") +shader_parameter/threshold = 0.9250000439375 +shader_parameter/color = Color(0.3, 0.5, 0.2, 1) + +[node name="Metaball" type="Control" unique_id=1102466349] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_jfklr") + +[node name="ColorRect" type="ColorRect" parent="." unique_id=1080383949] +material = SubResource("ShaderMaterial_vvscw") +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/src/Levels/BaseLevel.cs b/src/Levels/BaseLevel.cs index d8ce27f..bc10711 100644 --- a/src/Levels/BaseLevel.cs +++ b/src/Levels/BaseLevel.cs @@ -5,5 +5,5 @@ namespace Slimepire.Levels; [GlobalClass] public abstract partial class BaseLevel : Node { - protected abstract Camera2D Camera { get; } + public abstract Camera2D Camera { get; } } diff --git a/src/Levels/DemoLevel.cs b/src/Levels/DemoLevel.cs index 756f843..e9bb800 100644 --- a/src/Levels/DemoLevel.cs +++ b/src/Levels/DemoLevel.cs @@ -5,5 +5,5 @@ namespace Slimepire.Levels; [SceneTree] public partial class DemoLevel : BaseLevel { - protected override Camera2D Camera => _.Camera; + public override Camera2D Camera => _.Camera; } diff --git a/src/Levels/DemoLevel.tscn b/src/Levels/DemoLevel.tscn index 381489b..b3da49c 100644 --- a/src/Levels/DemoLevel.tscn +++ b/src/Levels/DemoLevel.tscn @@ -3,6 +3,7 @@ [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://j15868gtem0y" path="res://src/Gameplay/Nodules/RootNodule/RootNodule.tscn" id="3_knlma"] +[ext_resource type="PackedScene" uid="uid://ce2frpb21ct5l" path="res://src/Gameplay/GooSubViewPort.tscn" id="4_goo"] [sub_resource type="LabelSettings" id="LabelSettings_l2cn0"] font_size = 107 @@ -29,3 +30,15 @@ text = "DEMO LEVEL" label_settings = SubResource("LabelSettings_l2cn0") [node name="RootNodule" parent="." unique_id=1797926942 instance=ExtResource("3_knlma")] + +[node name="CanvasLayer" type="CanvasLayer" parent="." unique_id=648836414] + +[node name="ColorRect" type="ColorRect" parent="CanvasLayer" unique_id=1287004749] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="GooSubViewPort" parent="." unique_id=348721885 instance=ExtResource("4_goo")]