This commit is contained in:
2026-06-25 23:52:25 +02:00
parent b593bd64bd
commit 5714d027b7
22 changed files with 260 additions and 12 deletions

View File

@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7eeb6a6bf50d444f81dce3b50d9c468b580800_003F55_003Faaefec1f_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7eeb6a6bf50d444f81dce3b50d9c468b580800_003F55_003Faaefec1f_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARect2_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F20fdbba659cf4839ac49151c015340545a7800_003F6a_003F71fa77df_003FRect2_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASceneTreeAttribute_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe3fd2c31500d4d359fd6e9d5ca458884e0400_003F2f_003Faabb8bdb_003FSceneTreeAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASceneTreeAttribute_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe3fd2c31500d4d359fd6e9d5ca458884e0400_003F2f_003Faabb8bdb_003FSceneTreeAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASingletonAttribute_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe3fd2c31500d4d359fd6e9d5ca458884e0400_003F77_003F87840b05_003FSingletonAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASingletonAttribute_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe3fd2c31500d4d359fd6e9d5ca458884e0400_003F77_003F87840b05_003FSingletonAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASlimepire_002Ecore_002Emain_005Fgame_002EMainGame_002Eg_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FLocal_003FTemp_003FSourceGeneratedDocuments_003FC94839DE7EFB2DDB55DF1241_003FGodotSharp_002ESourceGenerators_003FGodotSharp_002ESourceGenerators_002ESceneTreeExtensions_002ESceneTreeSourceGenerator_003FSlimepire_002Ecore_002Emain_005Fgame_002EMainGame_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASlimepire_002Ecore_002Emain_005Fgame_002EMainGame_002Eg_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FLocal_003FTemp_003FSourceGeneratedDocuments_003FC94839DE7EFB2DDB55DF1241_003FGodotSharp_002ESourceGenerators_003FGodotSharp_002ESourceGenerators_002ESceneTreeExtensions_002ESceneTreeSourceGenerator_003FSlimepire_002Ecore_002Emain_005Fgame_002EMainGame_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

BIN
assets/gradient_linear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@@ -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

BIN
assets/metaball.kra Normal file

Binary file not shown.

BIN
assets/metaball.kra~ Normal file

Binary file not shown.

BIN
assets/metaball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -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

BIN
assets/metaball.png~ Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -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);
}

View File

@@ -0,0 +1 @@
uid://8xu2s3gyxp0v

View File

@@ -1,7 +1,7 @@
{ {
"sdk": { "sdk": {
"version": "9.0.0", "version": "9.0.0",
"rollForward": "latestMajor", "rollForward": "latestMajor",
"allowPrerelease": true "allowPrerelease": true
} }
} }

View File

@@ -21,8 +21,8 @@ buses/default_bus_layout="uid://djkq0k3jsuxcg"
[display] [display]
window/size/viewport_width=480 window/size/viewport_width=1920
window/size/viewport_height=320 window/size/viewport_height=1080
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"
window/stretch/aspect="expand" window/stretch/aspect="expand"

View File

@@ -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<DemoLevel>();
var canvasLayer = _level.GetNode<CanvasLayer>("CanvasLayer");
_colorRect = canvasLayer.GetNode<ColorRect>("ColorRect");
_material = new ShaderMaterial
{
Shader = GD.Load<Shader>("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);
}
}

View File

@@ -0,0 +1 @@
uid://bft481hoodv5d

View File

@@ -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")

11
src/Gameplay/Metaball.cs Normal file
View File

@@ -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) { }
}

View File

@@ -0,0 +1 @@
uid://cpj1q44qfwsps

View File

@@ -49,14 +49,13 @@ public partial class NoduleManager
_aStar.ConnectPoints(nodule.NoduleId, neighbor.NoduleId); _aStar.ConnectPoints(nodule.NoduleId, neighbor.NoduleId);
} }
// Convert any ghost tubes connected to this nodule to real tubes. // Convert ghost tubes where BOTH sides are now fully constructed
// Tubes are not always children of this nodule (depends on hash ordering in NoduleConnection),
// so iterating children alone isn't enough.
foreach (var (conn, tube) in _tubeConnections) foreach (var (conn, tube) in _tubeConnections)
{ {
if (tube.IsGhost && (ReferenceEquals(conn.A, nodule) || ReferenceEquals(conn.B, nodule))) if (tube.IsGhost && (ReferenceEquals(conn.A, nodule) || ReferenceEquals(conn.B, nodule)))
{ {
tube.SetGhost(false); if (!conn.A.IsConstructing && !conn.B.IsConstructing)
tube.SetGhost(false);
} }
} }
} }

View File

@@ -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

View File

@@ -5,5 +5,5 @@ namespace Slimepire.Levels;
[GlobalClass] [GlobalClass]
public abstract partial class BaseLevel : Node public abstract partial class BaseLevel : Node
{ {
protected abstract Camera2D Camera { get; } public abstract Camera2D Camera { get; }
} }

View File

@@ -5,5 +5,5 @@ namespace Slimepire.Levels;
[SceneTree] [SceneTree]
public partial class DemoLevel : BaseLevel public partial class DemoLevel : BaseLevel
{ {
protected override Camera2D Camera => _.Camera; public override Camera2D Camera => _.Camera;
} }

View File

@@ -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://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="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://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"] [sub_resource type="LabelSettings" id="LabelSettings_l2cn0"]
font_size = 107 font_size = 107
@@ -29,3 +30,15 @@ text = "DEMO LEVEL"
label_settings = SubResource("LabelSettings_l2cn0") label_settings = SubResource("LabelSettings_l2cn0")
[node name="RootNodule" parent="." unique_id=1797926942 instance=ExtResource("3_knlma")] [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")]