Add Godot project shell

This commit is contained in:
2026-04-21 18:54:38 +02:00
parent 0d9957fa62
commit 12a2868c9c
17 changed files with 424 additions and 6 deletions

View File

@@ -0,0 +1,59 @@
#nullable enable
using Godot;
using SideScrollerGame.Debug;
namespace SideScrollerGame.Bootstrap;
public partial class GameRoot : Node
{
public override void _Ready()
{
m_Settings = DebugSettings.Load();
GD.Seed((ulong)m_Settings.Seed);
GD.Print($"Debug boot: {m_Settings.BootMode}");
GD.Print($"Seed: {m_Settings.Seed}");
LoadBootScene(m_Settings.BootMode);
}
public void LoadBootScene(DebugBootMode bootMode)
{
PackedScene? scene = bootMode switch
{
DebugBootMode.Smoke => SmokeScene,
_ => MenuScene
};
string loadedSceneId = bootMode.ToString();
if (scene is null)
{
GD.PushError($"No scene configured for debug boot mode '{bootMode}'.");
return;
}
if (m_LoadedScene is not null)
{
m_LoadedScene.QueueFree();
}
m_LoadedScene = scene.Instantiate();
AddChild(m_LoadedScene);
DebugOverlay? overlay = GetNodeOrNull<DebugOverlay>("DebugOverlay");
if (overlay is not null && m_Settings is not null)
{
overlay.SetStatus(m_Settings, loadedSceneId);
}
}
[Export]
public PackedScene? MenuScene { get; set; }
[Export]
public PackedScene? SmokeScene { get; set; }
private Node? m_LoadedScene;
private DebugSettings? m_Settings;
}

View File

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

View File

@@ -0,0 +1,7 @@
namespace SideScrollerGame.Debug;
public enum DebugBootMode
{
Menu,
Smoke
}

View File

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

View File

@@ -0,0 +1,43 @@
#nullable enable
using Godot;
namespace SideScrollerGame.Debug;
public partial class DebugOverlay : CanvasLayer
{
public override void _Ready()
{
Layer = 100;
ProcessMode = ProcessModeEnum.Always;
EnsureLabel();
}
public void SetStatus(DebugSettings settings, string loadedSceneId)
{
Label label = EnsureLabel();
label.Text = $"Debug boot: {settings.BootMode}\nSeed: {settings.Seed}\nScene: {loadedSceneId}\nDebug: {OS.IsDebugBuild()}";
}
private Label EnsureLabel()
{
if (m_StatusLabel is not null)
{
return m_StatusLabel;
}
m_StatusLabel = GetNodeOrNull<Label>("StatusLabel");
if (m_StatusLabel is null)
{
m_StatusLabel = new Label { Name = "StatusLabel" };
AddChild(m_StatusLabel);
}
m_StatusLabel.MouseFilter = Control.MouseFilterEnum.Ignore;
m_StatusLabel.Position = new Vector2(8.0f, 8.0f);
m_StatusLabel.AutowrapMode = TextServer.AutowrapMode.Off;
return m_StatusLabel;
}
private Label? m_StatusLabel;
}

View File

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

View File

@@ -0,0 +1,91 @@
using System;
using Godot;
namespace SideScrollerGame.Debug;
public sealed class DebugSettings
{
public DebugSettings(DebugBootMode bootMode, int seed)
{
BootMode = bootMode;
Seed = seed;
}
public static DebugSettings Load()
{
DebugBootMode bootMode = LoadBootModeFromProjectSettings();
int seed = LoadSeedFromProjectSettings();
foreach (string argument in OS.GetCmdlineUserArgs())
{
if (argument.StartsWith(DebugBootModePrefix, StringComparison.OrdinalIgnoreCase))
{
string value = argument[DebugBootModePrefix.Length..];
if (TryParseBootMode(value, out DebugBootMode parsedBootMode))
{
bootMode = parsedBootMode;
}
else
{
GD.PushWarning($"Unknown debug boot mode '{value}'. Falling back to Menu.");
bootMode = DebugBootMode.Menu;
}
}
else if (argument.StartsWith(SeedPrefix, StringComparison.OrdinalIgnoreCase))
{
string value = argument[SeedPrefix.Length..];
if (int.TryParse(value, out int parsedSeed))
{
seed = parsedSeed;
}
else
{
GD.PushWarning($"Unknown debug seed '{value}'. Keeping seed {seed}.");
}
}
}
return new DebugSettings(bootMode, seed);
}
public DebugBootMode BootMode { get; }
public int Seed { get; }
private static DebugBootMode LoadBootModeFromProjectSettings()
{
if (!ProjectSettings.HasSetting(DebugBootModeSetting))
{
return DebugBootMode.Menu;
}
string configuredBootMode = ProjectSettings.GetSetting(DebugBootModeSetting).AsString();
if (TryParseBootMode(configuredBootMode, out DebugBootMode bootMode))
{
return bootMode;
}
GD.PushWarning($"Unknown configured debug boot mode '{configuredBootMode}'. Falling back to Menu.");
return DebugBootMode.Menu;
}
private static int LoadSeedFromProjectSettings()
{
if (!ProjectSettings.HasSetting(DebugSeedSetting))
{
return 1;
}
return ProjectSettings.GetSetting(DebugSeedSetting).AsInt32();
}
private static bool TryParseBootMode(string value, out DebugBootMode bootMode)
{
return Enum.TryParse(value, true, out bootMode);
}
private const string DebugBootModePrefix = "--debug-boot=";
private const string DebugBootModeSetting = "application/run/debug_boot_mode";
private const string DebugSeedSetting = "application/run/debug_seed";
private const string SeedPrefix = "--seed=";
}

View File

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

View File

@@ -0,0 +1,24 @@
using Godot;
namespace SideScrollerGame.Debug;
public partial class SmokeSceneController : Node2D
{
public override async void _Ready()
{
GD.Print("Smoke scene loaded");
if (!IsHeadless())
{
return;
}
await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);
GetTree().Quit(0);
}
private static bool IsHeadless()
{
return DisplayServer.GetName().Equals("headless", System.StringComparison.OrdinalIgnoreCase);
}
}

View File

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

View File

@@ -0,0 +1,23 @@
#nullable enable
using Godot;
namespace SideScrollerGame.Menu;
public partial class MenuPlaceholder : Control
{
public override void _Ready()
{
Label? title = GetNodeOrNull<Label>("Title");
if (title is not null)
{
title.Text = "SideScrollerGame - Menu Placeholder";
}
Label? hint = GetNodeOrNull<Label>("Hint");
if (hint is not null)
{
hint.Text = "Run with -- --debug-boot=smoke for smoke scene";
}
}
}

View File

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