Compare commits
8 Commits
eefbff0fd9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 5714d027b7 | |||
| b593bd64bd | |||
| 390ac95638 | |||
| bfee5f4025 | |||
| ecea198766 | |||
| 8f2912a174 | |||
| 9a6566a178 | |||
| f2fd147c19 |
17
AGENTS.md
Normal file
17
AGENTS.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Slimepire Project — Agent Rules
|
||||
|
||||
## Before editing ANY file: ALWAYS re-read it first
|
||||
|
||||
I often edit code manually while the agent is running. If you edit a file based on
|
||||
stale content from a previous read, you will overwrite my manual changes.
|
||||
|
||||
**Rule:** Before calling `edit` or `write` on any existing file, read it again with
|
||||
`read` to get the current state. Never rely on file contents from earlier turns or
|
||||
from a previous compaction/context window.
|
||||
|
||||
## Code style
|
||||
|
||||
- Godot 4.7 C# project targeting .NET 10.0
|
||||
- Uses `GodotSharp.SourceGenerators` — provides `[Singleton]`, `[SceneTree]`,
|
||||
`[ResourceTree]`, and `Instantiator.Instantiate<T>()`
|
||||
- Keep things simple, avoid over-engineering
|
||||
@@ -9,4 +9,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.7.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="src\Gameplay\Nodules\BasicNodule\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
2
Slimepire.csproj.DotSettings
Normal file
2
Slimepire.csproj.DotSettings
Normal file
@@ -0,0 +1,2 @@
|
||||
<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:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cgameplay_005Ccomponents_005Cenergy/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -1,4 +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">
|
||||
<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_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>
|
||||
BIN
assets/gradient_linear.png
Normal file
BIN
assets/gradient_linear.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
40
assets/gradient_linear.png.import
Normal file
40
assets/gradient_linear.png.import
Normal 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
BIN
assets/metaball.kra
Normal file
Binary file not shown.
BIN
assets/metaball.kra~
Normal file
BIN
assets/metaball.kra~
Normal file
Binary file not shown.
BIN
assets/metaball.png
Normal file
BIN
assets/metaball.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
41
assets/metaball.png.import
Normal file
41
assets/metaball.png.import
Normal 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
BIN
assets/metaball.png~
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/root_nodule.aseprite
Normal file
BIN
assets/root_nodule.aseprite
Normal file
Binary file not shown.
BIN
assets/root_nodule.png
Normal file
BIN
assets/root_nodule.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 B |
40
assets/root_nodule.png.import
Normal file
40
assets/root_nodule.png.import
Normal file
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://tomd3kojw0qy"
|
||||
path="res://.godot/imported/root_nodule.png-981ed6f2ff13b8d32aab753225ea9d2d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/root_nodule.png"
|
||||
dest_files=["res://.godot/imported/root_nodule.png-981ed6f2ff13b8d32aab753225ea9d2d.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
|
||||
37
assets/shaders/metaball.gdshader
Normal file
37
assets/shaders/metaball.gdshader
Normal 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);
|
||||
}
|
||||
1
assets/shaders/metaball.gdshader.uid
Normal file
1
assets/shaders/metaball.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://8xu2s3gyxp0v
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "9.0.0",
|
||||
"rollForward": "latestMajor",
|
||||
"allowPrerelease": true
|
||||
"version": "9.0.0",
|
||||
"rollForward": "latestMajor",
|
||||
"allowPrerelease": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
{
|
||||
"uuid": "e8652da7-7445-495d-8b60-2d303de6224a",
|
||||
"title": "Doing",
|
||||
"tasks": []
|
||||
"tasks": [
|
||||
"e2e29c87-042f-49e3-9c98-7ca6b258bcb7"
|
||||
]
|
||||
},
|
||||
{
|
||||
"uuid": "7362331b-07bd-4057-830f-780196f510be",
|
||||
@@ -42,7 +44,7 @@
|
||||
{
|
||||
"uuid": "36c8edc5-2708-440d-9bce-eaac534c3d84",
|
||||
"title": "EnergyManager",
|
||||
"description": "",
|
||||
"description": "soll es so ein Equilibrium geben, bei dem sich die Energie im System immer gleichmäßig verteilt?\n\nODER\n\n\"Saugen\" Depots Energie ein und Baustellen und Consumer requesten Energie von der nähsten Quelle/Depot?",
|
||||
"category": "4bec2406-dc3d-416b-b6c4-d8fd7425b2b5",
|
||||
"steps": [
|
||||
{
|
||||
@@ -78,6 +80,13 @@
|
||||
"description": "",
|
||||
"category": "4bec2406-dc3d-416b-b6c4-d8fd7425b2b5",
|
||||
"steps": []
|
||||
},
|
||||
{
|
||||
"uuid": "e2e29c87-042f-49e3-9c98-7ca6b258bcb7",
|
||||
"title": "Refactor Nodules",
|
||||
"description": "",
|
||||
"category": "4bec2406-dc3d-416b-b6c4-d8fd7425b2b5",
|
||||
"steps": []
|
||||
}
|
||||
],
|
||||
"layout": {
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@ using Godot;
|
||||
|
||||
namespace Slimepire.Core;
|
||||
|
||||
[ResourceTree("/src/Data")]
|
||||
[ResourceTree("/src")]
|
||||
public static partial class GameResources;
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
[gd_resource type="Resource" script_class="NoduleResource" format=3 uid="uid://0d8vif4ejtp1"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://ds1idectpqbnh" path="res://assets/energy_storage_nodule.png" id="1_237jx"]
|
||||
[ext_resource type="Script" uid="uid://bnf6qmk64i2wj" path="res://src/Data/NoduleResource.cs" id="2_dusyu"]
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_dusyu"]
|
||||
atlas = ExtResource("1_237jx")
|
||||
region = Rect2(0, 0, 32, 32)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_rmsh8"]
|
||||
atlas = ExtResource("1_237jx")
|
||||
region = Rect2(32, 0, 32, 32)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_lmxtc"]
|
||||
atlas = ExtResource("1_237jx")
|
||||
region = Rect2(64, 0, 32, 32)
|
||||
|
||||
[sub_resource type="SpriteFrames" id="SpriteFrames_j6wbi"]
|
||||
animations = [{
|
||||
"frames": [{
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_dusyu")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_rmsh8")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_lmxtc")
|
||||
}],
|
||||
"loop": 1,
|
||||
"name": &"default",
|
||||
"speed": 5.0
|
||||
}]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_dusyu")
|
||||
SpriteFrames = SubResource("SpriteFrames_j6wbi")
|
||||
Color = Color(0.60033447, 0.5019659, 0.0981792, 1)
|
||||
NoduleName = "Energy Nodule"
|
||||
MaxEnergy = 100.0
|
||||
metadata/_custom_type_script = "uid://bnf6qmk64i2wj"
|
||||
@@ -1,22 +0,0 @@
|
||||
using Godot;
|
||||
|
||||
namespace Slimepire.Data;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class NoduleResource : Resource
|
||||
{
|
||||
[Export]
|
||||
public SpriteFrames SpriteFrames;
|
||||
|
||||
[Export]
|
||||
public Color Color;
|
||||
|
||||
[Export]
|
||||
public string NoduleName = "Nodule";
|
||||
|
||||
[Export]
|
||||
public float MaxEnergy;
|
||||
|
||||
[Export]
|
||||
public float EnergyRegenRate;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
uid://bnf6qmk64i2wj
|
||||
@@ -1,42 +0,0 @@
|
||||
[gd_resource type="Resource" script_class="NoduleResource" format=3 uid="uid://5gk0giodp6g"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://cecg47efx7gw8" path="res://assets/simple_nodule.png" id="1_j6wbi"]
|
||||
[ext_resource type="Script" uid="uid://bnf6qmk64i2wj" path="res://src/Data/NoduleResource.cs" id="1_otepm"]
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_j6wbi"]
|
||||
atlas = ExtResource("1_j6wbi")
|
||||
region = Rect2(0, 0, 32, 32)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_q8pab"]
|
||||
atlas = ExtResource("1_j6wbi")
|
||||
region = Rect2(64, 0, 32, 32)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_dh8qd"]
|
||||
atlas = ExtResource("1_j6wbi")
|
||||
region = Rect2(32, 0, 32, 32)
|
||||
|
||||
[sub_resource type="SpriteFrames" id="SpriteFrames_x44k2"]
|
||||
animations = [{
|
||||
"frames": [{
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_j6wbi")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_q8pab")
|
||||
}, {
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_dh8qd")
|
||||
}],
|
||||
"loop": 1,
|
||||
"name": &"default",
|
||||
"speed": 3.0
|
||||
}]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_otepm")
|
||||
SpriteFrames = SubResource("SpriteFrames_x44k2")
|
||||
Color = Color(0.2642648, 0.46582836, 0.36528692, 1)
|
||||
NoduleName = "Simple Nodule"
|
||||
MaxEnergy = 2.0
|
||||
EnergyRegenRate = 0.1
|
||||
metadata/_custom_type_script = "uid://bnf6qmk64i2wj"
|
||||
@@ -1,6 +1,5 @@
|
||||
using Godot;
|
||||
using Slimepire.Core;
|
||||
using Slimepire.Data;
|
||||
using Slimepire.Gameplay.Components;
|
||||
using Slimepire.Gameplay.Nodules;
|
||||
|
||||
namespace Slimepire.Gameplay;
|
||||
@@ -8,25 +7,31 @@ namespace Slimepire.Gameplay;
|
||||
[SceneTree]
|
||||
public partial class BuildGhost : Node2D
|
||||
{
|
||||
private Tube? _tube;
|
||||
private static readonly PackedScene NoduleScene = GD.Load<PackedScene>(
|
||||
"res://src/Gameplay/Nodules/BasicNodule/BasicNodule.tscn"
|
||||
);
|
||||
|
||||
private readonly Dictionary<Nodule, Tube> _connectedTubes = [];
|
||||
|
||||
[Export]
|
||||
private TubeConnectionArea _tubeConnectionArea = null!;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
TubeConnectionArea.AreaEntered += TubeConnectionAreaOnAreaEntered;
|
||||
TubeConnectionArea.AreaExited += TubeConnectionAreaOnAreaExited;
|
||||
_tubeConnectionArea.AreaEntered += OnAreaEntered;
|
||||
_tubeConnectionArea.AreaExited += OnAreaExited;
|
||||
}
|
||||
|
||||
private void TubeConnectionAreaOnAreaEntered(Area2D area)
|
||||
private void OnAreaEntered(Area2D area)
|
||||
{
|
||||
if (area.GetParent() is Nodule nodule)
|
||||
{
|
||||
CreateGhostTube(nodule, area.GlobalPosition);
|
||||
CreateGhostTube(nodule, nodule.GlobalPosition);
|
||||
ConnectTubePlayer.Play();
|
||||
}
|
||||
}
|
||||
|
||||
private void TubeConnectionAreaOnAreaExited(Area2D area)
|
||||
private void OnAreaExited(Area2D area)
|
||||
{
|
||||
if (area.GetParent() is Nodule nodule)
|
||||
{
|
||||
@@ -43,7 +48,7 @@ public partial class BuildGhost : Node2D
|
||||
private void CreateGhostTube(Nodule connectedNodule, Vector2 pos)
|
||||
{
|
||||
var tube = Instantiator.Instantiate<Tube>();
|
||||
tube.Position = pos / 2; // TODO WHYYY????
|
||||
tube.Position = pos;
|
||||
_connectedTubes.Add(connectedNodule, tube);
|
||||
GetParent()?.AddChild(tube);
|
||||
}
|
||||
@@ -80,15 +85,12 @@ public partial class BuildGhost : Node2D
|
||||
|
||||
if (@event is InputEventMouseButton { Pressed: false, ButtonIndex: MouseButton.Left })
|
||||
{
|
||||
var nodule = Instantiator.Instantiate<Nodule>();
|
||||
|
||||
var nodule = NoduleScene.Instantiate<Nodule>();
|
||||
nodule.Position = Position;
|
||||
nodule.NoduleResource = GD.Load<NoduleResource>(
|
||||
GameResources.SimpleNoduleTres.ResourcePath
|
||||
);
|
||||
|
||||
nodule.EnergyBuildCost = 5f; // TODO: make configurable per nodule type
|
||||
nodule.ConstructionProgress = 0;
|
||||
GetParent()?.AddChild(nodule);
|
||||
|
||||
NoduleManager.Instance.RequestConstruction(nodule);
|
||||
CleanupBuildMode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
[ext_resource type="Script" uid="uid://ck5yw760bu8sb" path="res://src/Gameplay/BuildGhost.cs" id="1_ahcoi"]
|
||||
[ext_resource type="Texture2D" uid="uid://cecg47efx7gw8" path="res://assets/simple_nodule.png" id="2_uo42j"]
|
||||
[ext_resource type="PackedScene" uid="uid://bjesfu1mfx8l5" path="res://src/Gameplay/Components/TubeConnectionArea.tscn" id="2_vecmk"]
|
||||
[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"]
|
||||
|
||||
@@ -29,31 +30,22 @@ animations = [{
|
||||
"duration": 1.0,
|
||||
"texture": SubResource("AtlasTexture_quiac")
|
||||
}],
|
||||
"loop": true,
|
||||
"loop": 1,
|
||||
"name": &"default",
|
||||
"speed": 5.0
|
||||
}]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_uo42j"]
|
||||
radius = 96.38
|
||||
|
||||
[node name="BuildGhost" type="Node2D" unique_id=150653292]
|
||||
[node name="BuildGhost" type="Node2D" unique_id=150653292 node_paths=PackedStringArray("_tubeConnectionArea")]
|
||||
script = ExtResource("1_ahcoi")
|
||||
_tubeConnectionArea = NodePath("TubeConnectionArea")
|
||||
|
||||
[node name="TubeConnectionArea" parent="." unique_id=1821668398 instance=ExtResource("2_vecmk")]
|
||||
|
||||
[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")
|
||||
|
||||
49
src/Gameplay/Components/Energy/EnergyPackage.cs
Normal file
49
src/Gameplay/Components/Energy/EnergyPackage.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Godot;
|
||||
|
||||
namespace Slimepire.Gameplay.Components;
|
||||
|
||||
[SceneTree]
|
||||
public partial class EnergyPackage : Node2D
|
||||
{
|
||||
[Export]
|
||||
public float TravelSpeed { get; set; } = 200f;
|
||||
|
||||
private Vector2[] _waypoints = [];
|
||||
private int _currentWaypointIndex;
|
||||
|
||||
public event Action? Arrived;
|
||||
|
||||
public void SetWaypoints(Vector2[] waypoints)
|
||||
{
|
||||
_waypoints = waypoints;
|
||||
if (_waypoints.Length > 0)
|
||||
{
|
||||
GlobalPosition = _waypoints[0];
|
||||
}
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (_waypoints.Length == 0 || _currentWaypointIndex >= _waypoints.Length - 1)
|
||||
{
|
||||
Arrived?.Invoke();
|
||||
QueueFree();
|
||||
return;
|
||||
}
|
||||
|
||||
var target = _waypoints[_currentWaypointIndex + 1];
|
||||
var direction = target - GlobalPosition;
|
||||
var distance = direction.Length();
|
||||
var step = TravelSpeed * (float)delta;
|
||||
|
||||
if (step >= distance)
|
||||
{
|
||||
GlobalPosition = target;
|
||||
_currentWaypointIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
GlobalPosition += direction.Normalized() * step;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/Gameplay/Components/Energy/EnergyPackage.cs.uid
Normal file
1
src/Gameplay/Components/Energy/EnergyPackage.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://nk5tjlmcrpn2
|
||||
29
src/Gameplay/Components/Energy/EnergyPackage.tscn
Normal file
29
src/Gameplay/Components/Energy/EnergyPackage.tscn
Normal file
@@ -0,0 +1,29 @@
|
||||
[gd_scene format=3 uid="uid://dwdbqktsl34sm"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://nk5tjlmcrpn2" path="res://src/Gameplay/Components/Energy/EnergyPackage.cs" id="1_kmtmh"]
|
||||
[ext_resource type="Texture2D" uid="uid://bjl6gqj0bvhhp" path="res://assets/energy_package.png" id="2_psum7"]
|
||||
|
||||
[sub_resource type="Curve" id="Curve_psum7"]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1e-05, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 3
|
||||
|
||||
[sub_resource type="CurveTexture" id="CurveTexture_psum7"]
|
||||
curve = SubResource("Curve_psum7")
|
||||
|
||||
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_psum7"]
|
||||
particle_flag_disable_z = true
|
||||
inherit_velocity_ratio = 0.625
|
||||
gravity = Vector3(0, 10, 0)
|
||||
scale_curve = SubResource("CurveTexture_psum7")
|
||||
|
||||
[node name="EnergyPackage" type="Node2D" unique_id=869544034]
|
||||
z_index = 2
|
||||
script = ExtResource("1_kmtmh")
|
||||
|
||||
[node name="GPUParticles2D" type="GPUParticles2D" parent="." unique_id=388560926]
|
||||
modulate = Color(1, 0.7764706, 0, 1)
|
||||
texture = ExtResource("2_psum7")
|
||||
lifetime = 0.3
|
||||
use_fixed_seed = true
|
||||
seed = 874795105
|
||||
process_material = SubResource("ParticleProcessMaterial_psum7")
|
||||
17
src/Gameplay/Components/Energy/EnergyProducer.cs
Normal file
17
src/Gameplay/Components/Energy/EnergyProducer.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Godot;
|
||||
|
||||
namespace Slimepire.Gameplay.Components;
|
||||
|
||||
public partial class EnergyProducer : Node
|
||||
{
|
||||
[Export]
|
||||
public EnergyStorage EnergyStorage = null!;
|
||||
|
||||
[Export]
|
||||
public float ProductionRate = 1;
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
EnergyStorage.Energy += ProductionRate * (float)delta;
|
||||
}
|
||||
}
|
||||
1
src/Gameplay/Components/Energy/EnergyProducer.cs.uid
Normal file
1
src/Gameplay/Components/Energy/EnergyProducer.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bku1vey63ew65
|
||||
6
src/Gameplay/Components/Energy/EnergyProducer.tscn
Normal file
6
src/Gameplay/Components/Energy/EnergyProducer.tscn
Normal file
@@ -0,0 +1,6 @@
|
||||
[gd_scene format=3 uid="uid://t0gdf172f65v"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bku1vey63ew65" path="res://src/Gameplay/Components/Energy/EnergyProducer.cs" id="1_4q7h4"]
|
||||
|
||||
[node name="EnergyProducer" type="Node" unique_id=1184182162]
|
||||
script = ExtResource("1_4q7h4")
|
||||
49
src/Gameplay/Components/Energy/EnergyStorage.cs
Normal file
49
src/Gameplay/Components/Energy/EnergyStorage.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Godot;
|
||||
|
||||
namespace Slimepire.Gameplay.Components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class EnergyStorage : Node
|
||||
{
|
||||
[Export]
|
||||
public Label EnergyLabel = null!;
|
||||
|
||||
[Export]
|
||||
public float MaxEnergy = 100;
|
||||
|
||||
public float Energy
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
field = Mathf.Clamp(field + value, 0, MaxEnergy);
|
||||
UpdateLabel();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryConsume(float amount)
|
||||
{
|
||||
if (Energy >= amount)
|
||||
{
|
||||
Energy = -amount;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
UpdateLabel();
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
// EnergyManager.Instance.RemoveEnergyStorage(this);
|
||||
}
|
||||
|
||||
private void UpdateLabel()
|
||||
{
|
||||
EnergyLabel.Text = $"{Energy:0}/{MaxEnergy}";
|
||||
}
|
||||
}
|
||||
1
src/Gameplay/Components/Energy/EnergyStorage.cs.uid
Normal file
1
src/Gameplay/Components/Energy/EnergyStorage.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dgkeo1wsicv13
|
||||
6
src/Gameplay/Components/Energy/EnergyStorage.tscn
Normal file
6
src/Gameplay/Components/Energy/EnergyStorage.tscn
Normal file
@@ -0,0 +1,6 @@
|
||||
[gd_scene format=3 uid="uid://by6iw05ovnhq8"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dgkeo1wsicv13" path="res://src/Gameplay/Components/Energy/EnergyStorage.cs" id="1_vetx7"]
|
||||
|
||||
[node name="EnergyStorage" type="Node" unique_id=1765924301]
|
||||
script = ExtResource("1_vetx7")
|
||||
56
src/Gameplay/Components/GrowArea.cs
Normal file
56
src/Gameplay/Components/GrowArea.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Godot;
|
||||
|
||||
namespace Slimepire.Gameplay.Components;
|
||||
|
||||
[SceneTree]
|
||||
public partial class GrowArea : Area2D
|
||||
{
|
||||
private bool _mouseInsideClickArea;
|
||||
private bool _clickedInside;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
MouseEntered += ClickAreaOnMouseEntered;
|
||||
MouseExited += ClickAreaOnMouseExited;
|
||||
}
|
||||
|
||||
private void ClickAreaOnMouseEntered()
|
||||
{
|
||||
_mouseInsideClickArea = true;
|
||||
}
|
||||
|
||||
private void ClickAreaOnMouseExited()
|
||||
{
|
||||
_mouseInsideClickArea = false;
|
||||
|
||||
// ghost == null check probably unnecessary
|
||||
if (_clickedInside && !NoduleManager.Instance.Building)
|
||||
{
|
||||
NoduleManager.Instance.Building = true;
|
||||
_clickedInside = false;
|
||||
|
||||
var ghost = Instantiator.Instantiate<BuildGhost>();
|
||||
ghost.Position = Position;
|
||||
|
||||
// TODO: Make it better... EntityRoot oder vllt. NoduleRoot
|
||||
// Oder einfach den Baum auch als Baum in der Scene darstellen?
|
||||
GetTree().Root.AddChild(ghost);
|
||||
}
|
||||
}
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
using (@event)
|
||||
{
|
||||
if (
|
||||
@event is InputEventMouseButton { ButtonIndex: MouseButton.Left }
|
||||
&& @event.IsPressed()
|
||||
&& _mouseInsideClickArea
|
||||
)
|
||||
{
|
||||
_clickedInside = true;
|
||||
GetViewport().SetInputAsHandled();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/Gameplay/Components/GrowArea.cs.uid
Normal file
1
src/Gameplay/Components/GrowArea.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cfxb8wmnt7ej7
|
||||
7
src/Gameplay/Components/GrowArea.tscn
Normal file
7
src/Gameplay/Components/GrowArea.tscn
Normal file
@@ -0,0 +1,7 @@
|
||||
[gd_scene format=3 uid="uid://3x5pqm4t5cbl"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cfxb8wmnt7ej7" path="res://src/Gameplay/Components/GrowArea.cs" id="1_a3tcn"]
|
||||
|
||||
[node name="GrowArea" type="Area2D" unique_id=979341496]
|
||||
monitorable = false
|
||||
script = ExtResource("1_a3tcn")
|
||||
8
src/Gameplay/Components/TubeConnectionArea.cs
Normal file
8
src/Gameplay/Components/TubeConnectionArea.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using Godot;
|
||||
|
||||
namespace Slimepire.Gameplay.Components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class TubeConnectionArea : Area2D
|
||||
{
|
||||
}
|
||||
1
src/Gameplay/Components/TubeConnectionArea.cs.uid
Normal file
1
src/Gameplay/Components/TubeConnectionArea.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bcw8vylpb533h
|
||||
15
src/Gameplay/Components/TubeConnectionArea.tscn
Normal file
15
src/Gameplay/Components/TubeConnectionArea.tscn
Normal file
@@ -0,0 +1,15 @@
|
||||
[gd_scene format=3 uid="uid://bjesfu1mfx8l5"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bcw8vylpb533h" path="res://src/Gameplay/Components/TubeConnectionArea.cs" id="1_uhdst"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_x44k2"]
|
||||
radius = 96.38
|
||||
|
||||
[node name="TubeConnectionArea" type="Area2D" unique_id=1821668398]
|
||||
collision_layer = 2
|
||||
collision_mask = 2
|
||||
script = ExtResource("1_uhdst")
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=301201606]
|
||||
shape = SubResource("CircleShape2D_x44k2")
|
||||
debug_color = Color(0.38922516, 0.6054754, 0.25354394, 0.41960785)
|
||||
65
src/Gameplay/GooSubViewPort.cs
Normal file
65
src/Gameplay/GooSubViewPort.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
1
src/Gameplay/GooSubViewPort.cs.uid
Normal file
1
src/Gameplay/GooSubViewPort.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bft481hoodv5d
|
||||
6
src/Gameplay/GooSubViewPort.tscn
Normal file
6
src/Gameplay/GooSubViewPort.tscn
Normal 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
11
src/Gameplay/Metaball.cs
Normal 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) { }
|
||||
}
|
||||
1
src/Gameplay/Metaball.cs.uid
Normal file
1
src/Gameplay/Metaball.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cpj1q44qfwsps
|
||||
@@ -1,4 +1,5 @@
|
||||
using Godot;
|
||||
using Godot;
|
||||
using Slimepire.Gameplay.Components;
|
||||
using Slimepire.Gameplay.Nodules;
|
||||
|
||||
namespace Slimepire.Gameplay;
|
||||
@@ -6,19 +7,29 @@ namespace Slimepire.Gameplay;
|
||||
[Singleton]
|
||||
public partial class NoduleManager
|
||||
{
|
||||
private const float PackageSendInterval = 0.3f;
|
||||
private const float ConstructionRetryInterval = 2f;
|
||||
|
||||
public bool Building { get; set; }
|
||||
|
||||
private AStar2D _aStar = new();
|
||||
private readonly List<Nodule> _nodules = [];
|
||||
private readonly Dictionary<long, Nodule> _nodules = [];
|
||||
private readonly HashSet<NoduleConnection> _connections = [];
|
||||
private readonly List<RootNodule> _rootNodules = [];
|
||||
private readonly Dictionary<long, ConstructionRequest> _activeConstructions = [];
|
||||
|
||||
// GFX
|
||||
private readonly Dictionary<NoduleConnection, Tube> _tubeConnections = new();
|
||||
|
||||
public void RegisterNodule(Nodule nodule)
|
||||
{
|
||||
_nodules.Add(nodule);
|
||||
_aStar.AddPoint(nodule.Id, nodule.Position);
|
||||
_nodules.Add(nodule.NoduleId, nodule);
|
||||
_aStar.AddPoint(nodule.NoduleId, nodule.Position);
|
||||
|
||||
if (nodule is RootNodule root && !_rootNodules.Contains(root))
|
||||
{
|
||||
_rootNodules.Add(root);
|
||||
}
|
||||
|
||||
UpdateNoduleConnections();
|
||||
UpdateTubesAndAstar();
|
||||
@@ -30,31 +41,208 @@ public partial class NoduleManager
|
||||
UpdateTubesAndAstar();
|
||||
}
|
||||
|
||||
public void OnNoduleConstructed(Nodule nodule)
|
||||
{
|
||||
// Add all AStar connections that were skipped during construction
|
||||
foreach (var neighbor in nodule.Connections)
|
||||
{
|
||||
_aStar.ConnectPoints(nodule.NoduleId, neighbor.NoduleId);
|
||||
}
|
||||
|
||||
// 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)))
|
||||
{
|
||||
if (!conn.A.IsConstructing && !conn.B.IsConstructing)
|
||||
tube.SetGhost(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestConstruction(Nodule target)
|
||||
{
|
||||
if (!target.IsConstructing)
|
||||
return;
|
||||
|
||||
// Defer to allow connections to be established (physics frame overlap detection)
|
||||
var tree = target.GetTree();
|
||||
tree.CreateTimer(0.1f).Timeout += () => TryStartConstruction(target);
|
||||
}
|
||||
|
||||
private void TryStartConstruction(Nodule target)
|
||||
{
|
||||
// Constructing nodule has no AStar connections yet — route via neighbors
|
||||
var (sourceRoot, waypoints) = FindPathViaNeighbors(target);
|
||||
if (sourceRoot == null || waypoints.Length == 0)
|
||||
{
|
||||
// No path yet — retry periodically until a RootNodule becomes reachable
|
||||
// TODO: ist das hier richtig?
|
||||
var tree = target.GetTree();
|
||||
tree.CreateTimer(ConstructionRetryInterval).Timeout += () =>
|
||||
{
|
||||
if (target.IsConstructing && !_activeConstructions.ContainsKey(target.NoduleId))
|
||||
TryStartConstruction(target);
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
var request = new ConstructionRequest
|
||||
{
|
||||
Target = target,
|
||||
SourceRoot = sourceRoot,
|
||||
Waypoints = waypoints,
|
||||
};
|
||||
|
||||
_activeConstructions[target.NoduleId] = request;
|
||||
SendNextPackage(request);
|
||||
}
|
||||
|
||||
private void SendNextPackage(ConstructionRequest request)
|
||||
{
|
||||
var target = request.Target;
|
||||
|
||||
if (!target.IsConstructing)
|
||||
{
|
||||
_activeConstructions.Remove(target.NoduleId);
|
||||
return;
|
||||
}
|
||||
|
||||
var energyStorage = request.SourceRoot.GetNode<EnergyStorage>("EnergyStorage");
|
||||
if (energyStorage == null || !energyStorage.TryConsume(1))
|
||||
{
|
||||
// Source empty — retry after a delay
|
||||
var tree = request.SourceRoot.GetTree();
|
||||
tree.CreateTimer(PackageSendInterval).Timeout += () =>
|
||||
{
|
||||
if (_activeConstructions.ContainsKey(target.NoduleId))
|
||||
SendNextPackage(request);
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
var package = Instantiator.Instantiate<EnergyPackage>();
|
||||
package.SetWaypoints(request.Waypoints);
|
||||
|
||||
// Add to tree as sibling of source root so it's visible
|
||||
var parent = request.SourceRoot.GetParent();
|
||||
parent?.AddChild(package);
|
||||
package.GlobalPosition = request.Waypoints[0];
|
||||
|
||||
package.Arrived += () =>
|
||||
{
|
||||
target.ReceiveConstructionEnergy(1);
|
||||
|
||||
if (!target.IsConstructing)
|
||||
{
|
||||
_activeConstructions.Remove(target.NoduleId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send next package after a short interval
|
||||
var tree = target.GetTree();
|
||||
tree.CreateTimer(PackageSendInterval).Timeout += () =>
|
||||
{
|
||||
if (_activeConstructions.TryGetValue(target.NoduleId, out var req))
|
||||
SendNextPackage(req);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
private (RootNodule? source, Vector2[] waypoints) FindPathViaNeighbors(Nodule target)
|
||||
{
|
||||
RootNodule? bestRoot = null;
|
||||
Vector2[] bestWaypoints = [];
|
||||
float bestDist = float.MaxValue;
|
||||
|
||||
foreach (var neighbor in target.Connections)
|
||||
{
|
||||
foreach (var root in _rootNodules)
|
||||
{
|
||||
var pointPath = _aStar.GetPointPath(root.NoduleId, neighbor.NoduleId);
|
||||
if (pointPath.Length == 0)
|
||||
continue;
|
||||
|
||||
var dist = 0f;
|
||||
for (var i = 0; i < pointPath.Length - 1; i++)
|
||||
dist += pointPath[i].DistanceTo(pointPath[i + 1]);
|
||||
dist += pointPath[^1].DistanceTo(target.GlobalPosition);
|
||||
|
||||
if (dist < bestDist)
|
||||
{
|
||||
bestDist = dist;
|
||||
bestRoot = root;
|
||||
bestWaypoints = [.. pointPath, target.GlobalPosition];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (bestRoot, bestWaypoints);
|
||||
}
|
||||
|
||||
private (RootNodule? source, long[] path) FindNearestRootNodule(Nodule target)
|
||||
{
|
||||
RootNodule? nearest = null;
|
||||
float shortestDist = float.MaxValue;
|
||||
long[] shortestIds = [];
|
||||
|
||||
foreach (var root in _rootNodules)
|
||||
{
|
||||
var ids = _aStar.GetIdPath(root.NoduleId, target.NoduleId);
|
||||
if (ids.Length == 0)
|
||||
continue;
|
||||
|
||||
var path = _aStar.GetPointPath(root.NoduleId, target.NoduleId);
|
||||
var dist = 0f;
|
||||
for (var i = 0; i < path.Length - 1; i++)
|
||||
{
|
||||
dist += path[i].DistanceTo(path[i + 1]);
|
||||
}
|
||||
|
||||
if (dist < shortestDist)
|
||||
{
|
||||
shortestDist = dist;
|
||||
nearest = root;
|
||||
shortestIds = [.. ids];
|
||||
}
|
||||
}
|
||||
|
||||
return (nearest, shortestIds);
|
||||
}
|
||||
|
||||
private void UpdateNoduleConnections()
|
||||
{
|
||||
foreach (var n in _nodules)
|
||||
foreach (var nodule in _nodules.Values)
|
||||
{
|
||||
foreach (var c in n.Connections)
|
||||
foreach (var connected in nodule.Connections)
|
||||
{
|
||||
_connections.Add(new NoduleConnection(n, c));
|
||||
_connections.Add(new NoduleConnection(nodule, connected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTubesAndAstar()
|
||||
{
|
||||
foreach (var c in _connections)
|
||||
foreach (var conn in _connections)
|
||||
{
|
||||
if (!_tubeConnections.ContainsKey(c))
|
||||
if (!_tubeConnections.ContainsKey(conn))
|
||||
{
|
||||
var tube = Instantiator.Instantiate<Tube>();
|
||||
_tubeConnections.Add(c, tube);
|
||||
c.A.AddChild(tube);
|
||||
_tubeConnections.Add(conn, tube);
|
||||
|
||||
tube.SetTarget(c.B.Position);
|
||||
conn.A.AddChild(tube);
|
||||
tube.SetTarget(conn.B.GlobalPosition);
|
||||
|
||||
// TODO: refactor this out of gfx stuff
|
||||
_aStar.ConnectPoints(c.A.Id, c.B.Id);
|
||||
// Ghost tubes for constructing nodules — visual only, no AStar
|
||||
var eitherConstructing = conn.A.IsConstructing || conn.B.IsConstructing;
|
||||
if (eitherConstructing)
|
||||
{
|
||||
tube.SetGhost(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_aStar.ConnectPoints(conn.A.NoduleId, conn.B.NoduleId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,4 +278,11 @@ public partial class NoduleManager
|
||||
return HashCode.Combine(A, B);
|
||||
}
|
||||
}
|
||||
|
||||
private class ConstructionRequest
|
||||
{
|
||||
public required Nodule Target { get; init; }
|
||||
public required RootNodule SourceRoot { get; init; }
|
||||
public required Vector2[] Waypoints { get; init; }
|
||||
}
|
||||
}
|
||||
|
||||
3
src/Gameplay/Nodules/BasicNodule/BasicNodule.cs
Normal file
3
src/Gameplay/Nodules/BasicNodule/BasicNodule.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
using Slimepire.Gameplay.Nodules;
|
||||
|
||||
public partial class BasicNodule : Nodule { }
|
||||
1
src/Gameplay/Nodules/BasicNodule/BasicNodule.cs.uid
Normal file
1
src/Gameplay/Nodules/BasicNodule/BasicNodule.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b2b2irskqp5au
|
||||
58
src/Gameplay/Nodules/BasicNodule/BasicNodule.tscn
Normal file
58
src/Gameplay/Nodules/BasicNodule/BasicNodule.tscn
Normal file
@@ -0,0 +1,58 @@
|
||||
[gd_scene format=3 uid="uid://cnl6t8o4mh0j3"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b2b2irskqp5au" path="res://src/Gameplay/Nodules/BasicNodule/BasicNodule.cs" id="1_wbqr8"]
|
||||
[ext_resource type="PackedScene" uid="uid://bjesfu1mfx8l5" path="res://src/Gameplay/Components/TubeConnectionArea.tscn" id="2_dehe6"]
|
||||
[ext_resource type="PackedScene" uid="uid://3x5pqm4t5cbl" path="res://src/Gameplay/Components/GrowArea.tscn" id="3_pcav2"]
|
||||
[ext_resource type="Texture2D" uid="uid://cecg47efx7gw8" path="res://assets/simple_nodule.png" id="4_w4wqd"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_t72h2"]
|
||||
radius = 17.029387
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_7qt20"]
|
||||
atlas = ExtResource("4_w4wqd")
|
||||
region = Rect2(32, 0, 32, 32)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_x44k2"]
|
||||
atlas = ExtResource("4_w4wqd")
|
||||
region = Rect2(0, 0, 32, 32)
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_inlcu"]
|
||||
atlas = ExtResource("4_w4wqd")
|
||||
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": 1,
|
||||
"name": &"default",
|
||||
"speed": 2.0
|
||||
}]
|
||||
|
||||
[node name="BasicNodule" type="Node2D" unique_id=1637542829 node_paths=PackedStringArray("_tubeConnectionArea", "_gfx")]
|
||||
z_index = 1
|
||||
script = ExtResource("1_wbqr8")
|
||||
_tubeConnectionArea = NodePath("TubeConnectionArea")
|
||||
_gfx = NodePath("Gfx")
|
||||
|
||||
[node name="TubeConnectionArea" parent="." unique_id=1821668398 instance=ExtResource("2_dehe6")]
|
||||
|
||||
[node name="GrowArea" parent="." unique_id=979341496 instance=ExtResource("3_pcav2")]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="GrowArea" unique_id=282097141]
|
||||
shape = SubResource("CircleShape2D_t72h2")
|
||||
|
||||
[node name="Gfx" type="AnimatedSprite2D" parent="." unique_id=190397869]
|
||||
unique_name_in_owner = true
|
||||
texture_filter = 1
|
||||
sprite_frames = SubResource("SpriteFrames_xyjsl")
|
||||
autoplay = "default"
|
||||
frame_progress = 0.120879106
|
||||
@@ -1,20 +0,0 @@
|
||||
using Godot;
|
||||
|
||||
namespace Slimepire.Gameplay.Nodules;
|
||||
|
||||
[SceneTree]
|
||||
public partial class Mitochondria : Node2D
|
||||
{
|
||||
public float Energy { get; set; } = 0;
|
||||
public float MaxEnergy { get; set; } = 100;
|
||||
public float EnergyRegenRate { get; set; } = 1;
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (Energy < MaxEnergy)
|
||||
{
|
||||
Energy += EnergyRegenRate * (float)delta;
|
||||
}
|
||||
GPUParticles2D.Amount = (int)Energy;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
uid://h50qndjmmq4d
|
||||
File diff suppressed because one or more lines are too long
@@ -1,51 +1,51 @@
|
||||
using Godot;
|
||||
using Slimepire.Data;
|
||||
using Slimepire.Gameplay.Components;
|
||||
|
||||
namespace Slimepire.Gameplay.Nodules;
|
||||
|
||||
[SceneTree]
|
||||
public partial class Nodule : Node2D
|
||||
{
|
||||
public long Id { get; set; } = BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0);
|
||||
|
||||
private bool _mouseInsideClickArea;
|
||||
private bool _clickedInside;
|
||||
|
||||
public readonly List<Nodule> Connections = [];
|
||||
[Export]
|
||||
private TubeConnectionArea _tubeConnectionArea = null!;
|
||||
|
||||
[Export]
|
||||
public required NoduleResource NoduleResource;
|
||||
private AnimatedSprite2D _gfx = null!;
|
||||
|
||||
private float energy = 0;
|
||||
[Export]
|
||||
public float EnergyBuildCost { get; set; } = 0f;
|
||||
|
||||
// todo remove?
|
||||
private bool _isExpanding;
|
||||
public float ConstructionProgress { get; set; }
|
||||
|
||||
public bool IsConstructing => EnergyBuildCost > 0 && ConstructionProgress < EnergyBuildCost;
|
||||
|
||||
public List<Nodule> Connections { get; } = [];
|
||||
|
||||
protected AnimatedSprite2D Gfx => _gfx;
|
||||
|
||||
public long NoduleId => (long)GetInstanceId();
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Gfx.SpriteFrames = NoduleResource.SpriteFrames;
|
||||
Gfx.SelfModulate = NoduleResource.Color;
|
||||
|
||||
ClickArea.MouseEntered += ClickAreaOnMouseEntered;
|
||||
ClickArea.MouseExited += ClickAreaOnMouseExited;
|
||||
|
||||
TubeConnectionArea.AreaEntered += TubeConnectionAreaOnAreaEntered;
|
||||
TubeConnectionArea.AreaExited += TubeConnectionAreaOnAreaExited;
|
||||
_tubeConnectionArea.AreaEntered += OnAreaEntered;
|
||||
_tubeConnectionArea.AreaExited += OnAreaExited;
|
||||
|
||||
ApplyCustomizations();
|
||||
NoduleManager.Instance.RegisterNodule(this);
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (energy < NoduleResource.MaxEnergy)
|
||||
// render above tubes
|
||||
ZIndex = 1;
|
||||
|
||||
if (IsConstructing)
|
||||
{
|
||||
energy += NoduleResource.EnergyRegenRate * (float)delta;
|
||||
_gfx.Modulate = new Color(1, 1, 1, 0.4f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gfx.Play();
|
||||
}
|
||||
|
||||
EnergyLabel.Text = energy.ToString("F2");
|
||||
}
|
||||
|
||||
private void TubeConnectionAreaOnAreaEntered(Area2D area)
|
||||
private void OnAreaEntered(Area2D area)
|
||||
{
|
||||
if (area.GetParent() is Nodule nodule)
|
||||
{
|
||||
@@ -54,63 +54,38 @@ public partial class Nodule : Node2D
|
||||
}
|
||||
}
|
||||
|
||||
private void TubeConnectionAreaOnAreaExited(Area2D area)
|
||||
private void OnAreaExited(Area2D area)
|
||||
{
|
||||
if (area.GetParent() is Nodule nodule)
|
||||
{
|
||||
Connections.Remove(nodule);
|
||||
NoduleManager.Instance.Update();
|
||||
}
|
||||
}
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
protected virtual void ApplyCustomizations()
|
||||
{
|
||||
using (@event)
|
||||
_gfx.SelfModulate = Colors.DarkOliveGreen;
|
||||
}
|
||||
|
||||
public void ReceiveConstructionEnergy(float amount)
|
||||
{
|
||||
if (!IsConstructing)
|
||||
return;
|
||||
|
||||
ConstructionProgress = Mathf.Min(ConstructionProgress + amount, EnergyBuildCost);
|
||||
|
||||
if (ConstructionProgress >= EnergyBuildCost)
|
||||
{
|
||||
if (
|
||||
@event is InputEventMouseButton { ButtonIndex: MouseButton.Left }
|
||||
&& @event.IsPressed()
|
||||
&& _mouseInsideClickArea
|
||||
)
|
||||
{
|
||||
_clickedInside = true;
|
||||
GetViewport().SetInputAsHandled();
|
||||
}
|
||||
OnConstructionComplete();
|
||||
}
|
||||
}
|
||||
|
||||
private void ClickAreaOnMouseEntered()
|
||||
protected virtual void OnConstructionComplete()
|
||||
{
|
||||
_mouseInsideClickArea = true;
|
||||
}
|
||||
_gfx.Modulate = Colors.White;
|
||||
_gfx.Play();
|
||||
|
||||
private void ClickAreaOnMouseExited()
|
||||
{
|
||||
_mouseInsideClickArea = false;
|
||||
|
||||
// ghost == null check probably unnecessary
|
||||
if (_clickedInside && !NoduleManager.Instance.Building)
|
||||
{
|
||||
NoduleManager.Instance.Building = true;
|
||||
_clickedInside = false;
|
||||
_isExpanding = true;
|
||||
|
||||
var ghost = Instantiator.Instantiate<BuildGhost>();
|
||||
ghost.Position = Position;
|
||||
|
||||
GetParent()?.AddChild(ghost);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBuildComplete(Vector2 pos)
|
||||
{
|
||||
NoduleManager.Instance.Building = false;
|
||||
_isExpanding = false;
|
||||
|
||||
var nodule = Instantiator.Instantiate<Nodule>();
|
||||
|
||||
nodule.Position = pos;
|
||||
Connections.Add(nodule);
|
||||
nodule.Connections.Add(this);
|
||||
GetParent()?.AddChild(nodule);
|
||||
NoduleManager.Instance.OnNoduleConstructed(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cmpl0if164dba
|
||||
uid://ycm0pzamtclm
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
[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/simple_nodule.png" id="2_7qt20"]
|
||||
[ext_resource type="PackedScene" uid="uid://c11xdoiv2ch3w" path="res://src/Gameplay/Nodules/Mitochondria.tscn" id="3_x44k2"]
|
||||
|
||||
[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": 1,
|
||||
"name": &"default",
|
||||
"speed": 2.0
|
||||
}]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_x44k2"]
|
||||
radius = 96.38
|
||||
|
||||
[sub_resource type="LabelSettings" id="LabelSettings_x44k2"]
|
||||
font_size = 12
|
||||
outline_size = 3
|
||||
outline_color = Color(0, 0, 0, 1)
|
||||
shadow_size = 3
|
||||
shadow_color = Color(0, 0, 0, 1)
|
||||
|
||||
[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="Gfx" type="AnimatedSprite2D" parent="." unique_id=190397869]
|
||||
unique_name_in_owner = true
|
||||
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
|
||||
collision_layer = 2
|
||||
collision_mask = 2
|
||||
|
||||
[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)
|
||||
|
||||
[node name="Mitochondria" parent="." unique_id=954228490 instance=ExtResource("3_x44k2")]
|
||||
process_mode = 4
|
||||
visible = false
|
||||
|
||||
[node name="EnergyLabel" type="Label" parent="." unique_id=466024399]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -20.0
|
||||
offset_top = 14.0
|
||||
offset_right = 20.0
|
||||
offset_bottom = 31.0
|
||||
grow_horizontal = 2
|
||||
text = "5"
|
||||
label_settings = SubResource("LabelSettings_x44k2")
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
11
src/Gameplay/Nodules/RootNodule/RootNodule.cs
Normal file
11
src/Gameplay/Nodules/RootNodule/RootNodule.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Godot;
|
||||
using Slimepire.Gameplay.Nodules;
|
||||
|
||||
[SceneTree]
|
||||
public partial class RootNodule : Nodule
|
||||
{
|
||||
protected override void ApplyCustomizations()
|
||||
{
|
||||
Gfx.Modulate = Colors.Coral;
|
||||
}
|
||||
}
|
||||
1
src/Gameplay/Nodules/RootNodule/RootNodule.cs.uid
Normal file
1
src/Gameplay/Nodules/RootNodule/RootNodule.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://y4cpi50hsaj4
|
||||
69
src/Gameplay/Nodules/RootNodule/RootNodule.tscn
Normal file
69
src/Gameplay/Nodules/RootNodule/RootNodule.tscn
Normal file
@@ -0,0 +1,69 @@
|
||||
[gd_scene format=3 uid="uid://j15868gtem0y"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bjesfu1mfx8l5" path="res://src/Gameplay/Components/TubeConnectionArea.tscn" id="1_b03xe"]
|
||||
[ext_resource type="Script" uid="uid://y4cpi50hsaj4" path="res://src/Gameplay/Nodules/RootNodule/RootNodule.cs" id="1_root"]
|
||||
[ext_resource type="PackedScene" uid="uid://t0gdf172f65v" path="res://src/Gameplay/Components/Energy/EnergyProducer.tscn" id="2_cy5pc"]
|
||||
[ext_resource type="PackedScene" uid="uid://by6iw05ovnhq8" path="res://src/Gameplay/Components/Energy/EnergyStorage.tscn" id="2_gke5o"]
|
||||
[ext_resource type="PackedScene" uid="uid://3x5pqm4t5cbl" path="res://src/Gameplay/Components/GrowArea.tscn" id="2_tg6hi"]
|
||||
[ext_resource type="Texture2D" uid="uid://tomd3kojw0qy" path="res://assets/root_nodule.png" id="3_b03xe"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_t72h2"]
|
||||
radius = 27.018513
|
||||
|
||||
[sub_resource type="SpriteFrames" id="SpriteFrames_cy5pc"]
|
||||
animations = [{
|
||||
"frames": [{
|
||||
"duration": 1.0,
|
||||
"texture": ExtResource("3_b03xe")
|
||||
}],
|
||||
"loop": 1,
|
||||
"name": &"default",
|
||||
"speed": 2.0
|
||||
}]
|
||||
|
||||
[sub_resource type="LabelSettings" id="LabelSettings_cdcnu"]
|
||||
font_size = 12
|
||||
outline_size = 3
|
||||
outline_color = Color(0, 0, 0, 1)
|
||||
shadow_size = 3
|
||||
shadow_color = Color(0, 0, 0, 1)
|
||||
|
||||
[node name="RootNodule" type="Node2D" unique_id=1797926942 node_paths=PackedStringArray("_tubeConnectionArea", "_gfx")]
|
||||
z_index = 1
|
||||
script = ExtResource("1_root")
|
||||
_tubeConnectionArea = NodePath("TubeConnectionArea")
|
||||
_gfx = NodePath("Gfx")
|
||||
|
||||
[node name="EnergyProducer" parent="." unique_id=1184182162 node_paths=PackedStringArray("EnergyStorage") instance=ExtResource("2_cy5pc")]
|
||||
EnergyStorage = NodePath("../EnergyStorage")
|
||||
|
||||
[node name="EnergyStorage" parent="." unique_id=1765924301 node_paths=PackedStringArray("EnergyLabel") instance=ExtResource("2_gke5o")]
|
||||
EnergyLabel = NodePath("../EnergyLabel")
|
||||
|
||||
[node name="TubeConnectionArea" parent="." unique_id=1821668398 instance=ExtResource("1_b03xe")]
|
||||
|
||||
[node name="GrowArea" parent="." unique_id=979341496 instance=ExtResource("2_tg6hi")]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="GrowArea" unique_id=1962902431]
|
||||
shape = SubResource("CircleShape2D_t72h2")
|
||||
|
||||
[node name="Gfx" type="AnimatedSprite2D" parent="." unique_id=705500036]
|
||||
unique_name_in_owner = true
|
||||
texture_filter = 1
|
||||
sprite_frames = SubResource("SpriteFrames_cy5pc")
|
||||
autoplay = "default"
|
||||
|
||||
[node name="EnergyLabel" type="Label" parent="." unique_id=1654733583]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -20.0
|
||||
offset_top = 14.0
|
||||
offset_right = 20.0
|
||||
offset_bottom = 31.0
|
||||
grow_horizontal = 2
|
||||
text = "5"
|
||||
label_settings = SubResource("LabelSettings_cdcnu")
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
@@ -1,9 +0,0 @@
|
||||
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()
|
||||
@@ -1 +0,0 @@
|
||||
uid://bvl0487nflq0q
|
||||
@@ -14,13 +14,13 @@ public partial class Tube : Node2D
|
||||
float maxLength = 180;
|
||||
|
||||
// Generate 5 points from origin to Target
|
||||
var diff = Target.Position - Position;
|
||||
var diff = Target.Position;
|
||||
|
||||
var points = new Vector2[5];
|
||||
points[0] = Position;
|
||||
points[0] = Vector2.Zero;
|
||||
for (var i = 1; i < 4; i++)
|
||||
{
|
||||
points[i] = points[i - 1] + diff / 5;
|
||||
points[i] = diff * i / 5;
|
||||
}
|
||||
points[4] = Target.Position;
|
||||
|
||||
@@ -40,6 +40,17 @@ public partial class Tube : Node2D
|
||||
GenerateTube();
|
||||
}
|
||||
|
||||
private bool _isGhost;
|
||||
public bool IsGhost => _isGhost;
|
||||
|
||||
public void SetGhost(bool ghost)
|
||||
{
|
||||
_isGhost = ghost;
|
||||
Line2D.DefaultColor = ghost
|
||||
? new Color(0.3f, 0.49f, 0.24f, 0.3f)
|
||||
: new Color(0.30588236f, 0.4862745f, 0.23921569f, 1f);
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Line2D.Points = [];
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
[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]
|
||||
[sub_resource type="Curve" id="Curve_kvwlm"]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.5, 0.9453219), 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]
|
||||
@@ -13,13 +12,14 @@ script = ExtResource("1_76hpl")
|
||||
[node name="Line2D" type="Line2D" parent="." unique_id=1553055261]
|
||||
unique_name_in_owner = true
|
||||
z_as_relative = false
|
||||
points = PackedVector2Array(0, 0, 5.4, 18.2, 10.8, 36.4, 16.2, 54.6, 27, 91)
|
||||
width = 8.0
|
||||
width_curve = SubResource("Curve_0lkqj")
|
||||
default_color = Color(0.30588236, 0.4862745, 0.23921569, 0.5568628)
|
||||
width_curve = SubResource("Curve_kvwlm")
|
||||
default_color = Color(0.30588236, 0.4862745, 0.23921569, 1)
|
||||
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)
|
||||
position = Vector2(27, 91)
|
||||
|
||||
32
src/Gameplay/metaball.tscn
Normal file
32
src/Gameplay/metaball.tscn
Normal 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
|
||||
@@ -5,5 +5,5 @@ namespace Slimepire.Levels;
|
||||
[GlobalClass]
|
||||
public abstract partial class BaseLevel : Node
|
||||
{
|
||||
protected abstract Camera2D Camera { get; }
|
||||
public abstract Camera2D Camera { get; }
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace Slimepire.Levels;
|
||||
[SceneTree]
|
||||
public partial class DemoLevel : BaseLevel
|
||||
{
|
||||
protected override Camera2D Camera => _.Camera;
|
||||
public override Camera2D Camera => _.Camera;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
[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"]
|
||||
[ext_resource type="Resource" uid="uid://0d8vif4ejtp1" path="res://src/Data/EnergyStorageNodule.tres" id="4_yyao7"]
|
||||
[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,5 +29,16 @@ grow_vertical = 2
|
||||
text = "DEMO LEVEL"
|
||||
label_settings = SubResource("LabelSettings_l2cn0")
|
||||
|
||||
[node name="Nodule" parent="." unique_id=1637542829 instance=ExtResource("3_qhkhc")]
|
||||
NoduleResource = ExtResource("4_yyao7")
|
||||
[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")]
|
||||
|
||||
Reference in New Issue
Block a user