From 406036504aa421519f7ff45f122d2b47091a0f3f Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 15 Aug 2025 02:46:02 +0200 Subject: [PATCH] Implement core game functionality with AppRoot, SaveClient, PlayerRepository, and LevelRepository classes --- Mr. Brick Adventures.csproj | 138 +----------------- common/AppRoot.cs | 34 +++++ common/AppRoot.cs.uid | 1 + data/ConfigClient.cs | 6 + data/ConfigClient.cs.uid | 1 + data/SaveClient.cs | 103 +++++++++++++ data/SaveClient.cs.uid | 1 + features/ui/hud/Hud.cs | 34 +++++ features/ui/hud/Hud.cs.uid | 1 + features/ui/menus/MainMenu.cs | 58 ++++++++ features/ui/menus/MainMenu.cs.uid | 1 + features/ui/menus/PauseMenu.cs | 6 + features/ui/menus/PauseMenu.cs.uid | 1 + .../ui => features/ui/menus}/main_menu.tscn | 20 +-- features/ui/settings/AudioSettings.cs | 6 + features/ui/settings/AudioSettings.cs.uid | 1 + game/repositories/LevelRepository.cs | 34 +++++ game/repositories/LevelRepository.cs.uid | 1 + game/repositories/PlayerRepository.cs | 25 ++++ game/repositories/PlayerRepository.cs.uid | 1 + game/repositories/SessionRepository.cs | 6 + game/repositories/SessionRepository.cs.uid | 1 + game/repositories/SettingsRepository.cs | 6 + game/repositories/SettingsRepository.cs.uid | 1 + game/repositories/SkillsRepository.cs | 6 + game/repositories/SkillsRepository.cs.uid | 1 + game/services/LevelService.cs | 6 + game/services/LevelService.cs.uid | 1 + game/services/SaveService.cs | 32 ++++ game/services/SaveService.cs.uid | 1 + game/services/SkillService.cs | 6 + game/services/SkillService.cs.uid | 1 + objects/level/ui_layer.tscn | 3 +- objects/ui/pause_menu.tscn | 17 +-- scenes/level_village_1.tscn | 4 + scenes/main_menu.tscn | 26 ++-- scripts/UI/Hud.cs | 43 ------ scripts/UI/Hud.cs.uid | 1 - 38 files changed, 422 insertions(+), 213 deletions(-) create mode 100644 common/AppRoot.cs create mode 100644 common/AppRoot.cs.uid create mode 100644 data/ConfigClient.cs create mode 100644 data/ConfigClient.cs.uid create mode 100644 data/SaveClient.cs create mode 100644 data/SaveClient.cs.uid create mode 100644 features/ui/hud/Hud.cs create mode 100644 features/ui/hud/Hud.cs.uid create mode 100644 features/ui/menus/MainMenu.cs create mode 100644 features/ui/menus/MainMenu.cs.uid create mode 100644 features/ui/menus/PauseMenu.cs create mode 100644 features/ui/menus/PauseMenu.cs.uid rename {objects/ui => features/ui/menus}/main_menu.tscn (73%) create mode 100644 features/ui/settings/AudioSettings.cs create mode 100644 features/ui/settings/AudioSettings.cs.uid create mode 100644 game/repositories/LevelRepository.cs create mode 100644 game/repositories/LevelRepository.cs.uid create mode 100644 game/repositories/PlayerRepository.cs create mode 100644 game/repositories/PlayerRepository.cs.uid create mode 100644 game/repositories/SessionRepository.cs create mode 100644 game/repositories/SessionRepository.cs.uid create mode 100644 game/repositories/SettingsRepository.cs create mode 100644 game/repositories/SettingsRepository.cs.uid create mode 100644 game/repositories/SkillsRepository.cs create mode 100644 game/repositories/SkillsRepository.cs.uid create mode 100644 game/services/LevelService.cs create mode 100644 game/services/LevelService.cs.uid create mode 100644 game/services/SaveService.cs create mode 100644 game/services/SaveService.cs.uid create mode 100644 game/services/SkillService.cs create mode 100644 game/services/SkillService.cs.uid delete mode 100644 scripts/UI/Hud.cs delete mode 100644 scripts/UI/Hud.cs.uid diff --git a/Mr. Brick Adventures.csproj b/Mr. Brick Adventures.csproj index 57454f6..4c4a7f5 100644 --- a/Mr. Brick Adventures.csproj +++ b/Mr. Brick Adventures.csproj @@ -4,146 +4,10 @@ true Mr.BrickAdventures - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/common/AppRoot.cs b/common/AppRoot.cs new file mode 100644 index 0000000..8a059b3 --- /dev/null +++ b/common/AppRoot.cs @@ -0,0 +1,34 @@ +using Chickensoft.AutoInject; +using Chickensoft.Introspection; +using Godot; +using Mr.BrickAdventures.data; +using Mr.BrickAdventures.game.repositories; +using Mr.BrickAdventures.game.services; + +namespace Mr.BrickAdventures.common; + +[Meta(typeof(IAutoNode))] +public partial class AppRoot : Node2D, IProvide, IProvide, IProvide, IProvide +{ + public override void _Notification(int what) => this.Notify(what); + + private readonly SaveClient _save = new("user://savegame.save", version: 2); + private readonly PlayerRepository _players = new(); + private readonly LevelRepository _levels = new(); + private SaveService _saveService = null!; + + PlayerRepository IProvide.Value() => _players; + LevelRepository IProvide.Value() => _levels; + SaveClient IProvide.Value() => _save; + SaveService IProvide.Value() => _saveService; + + + public void OnReady() + { + _saveService = new SaveService(_players, _levels, _save); + + _saveService.TryLoad(); + + this.Provide(); + } +} \ No newline at end of file diff --git a/common/AppRoot.cs.uid b/common/AppRoot.cs.uid new file mode 100644 index 0000000..e90f264 --- /dev/null +++ b/common/AppRoot.cs.uid @@ -0,0 +1 @@ +uid://dg2l7cw6da4vb diff --git a/data/ConfigClient.cs b/data/ConfigClient.cs new file mode 100644 index 0000000..5dbd0ac --- /dev/null +++ b/data/ConfigClient.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.data; + +public class ConfigClient +{ + +} \ No newline at end of file diff --git a/data/ConfigClient.cs.uid b/data/ConfigClient.cs.uid new file mode 100644 index 0000000..4686182 --- /dev/null +++ b/data/ConfigClient.cs.uid @@ -0,0 +1 @@ +uid://d3s774lnoljcu diff --git a/data/SaveClient.cs b/data/SaveClient.cs new file mode 100644 index 0000000..ac324b5 --- /dev/null +++ b/data/SaveClient.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Godot; +using Godot.Collections; +using Mr.BrickAdventures.game.repositories; + +namespace Mr.BrickAdventures.data; + +public sealed class SaveClient +{ + private readonly string _path; + private readonly int _version; + + public SaveClient(string path, int version) { _path = path; _version = version; } + + public bool Exists() => FileAccess.FileExists(_path); + + public bool TryLoad(out PlayerState player, out LevelState level) { + player = null!; level = null!; + if (!Exists()) return false; + + using var f = FileAccess.Open(_path, FileAccess.ModeFlags.Read); + var dict = (Dictionary)f.GetVar(); + + if ((int)dict.GetValueOrDefault("version", -1) != _version) return false; + + player = ToPlayer((Dictionary)dict["player"]); + level = ToLevel((Dictionary)dict["level"]); + return true; + } + + // Strict load: requires version + player_state + level_state. + // If anything is off, delete the file and act as "no save". + public bool TryLoadStrict(out PlayerState player, out LevelState level) { + player = default!; + level = default!; + + if (!Exists()) return false; + + try { + using var f = FileAccess.Open(_path, FileAccess.ModeFlags.Read); + if (f == null) { Delete(); return false; } + + var dictionary = (Dictionary)f.GetVar(); + + + if (!dictionary.TryGetValue("version", out var v) || (int)v != _version) { Delete(); return false; } + + if (!dictionary.TryGetValue("player_state", out var pObj) || (Dictionary)pObj is not { } p) { Delete(); return false; } + if (!dictionary.TryGetValue("level_state", out var lObj) || (Dictionary)lObj is not { } l) { Delete(); return false; } + + player = ToPlayer(p); + level = ToLevel(l); + return true; + } + catch (Exception e) { + GD.PushWarning($"SaveClient: load failed — deleting bad save. {e.GetType().Name}: {e.Message}"); + Delete(); + return false; + } + } + + public void Save(PlayerState player, LevelState level) { + using var f = FileAccess.Open(_path, FileAccess.ModeFlags.Write); + var dict = new Dictionary { + { "version", _version }, + { "player", FromPlayer(player) }, + { "level", FromLevel(level) } + }; + f.StoreVar(dict); + } + + public void Delete() { + if (!Exists()) return; + var abs = ProjectSettings.GlobalizePath(_path); + var ok = DirAccess.RemoveAbsolute(abs); + if (ok != Error.Ok) GD.PushWarning($"SaveClient: failed to delete {_path}: {ok}"); + } + + private static Dictionary FromPlayer(PlayerState s) => new() { { "coins", s.Coins }, { "lives", s.Lives } }; + private static PlayerState ToPlayer(Dictionary d) => new() { + Coins = d.TryGetValue("coins", out var c) ? (int)c : 0, + Lives = d.TryGetValue("lives", out var l) ? (int)l : 3 + }; + + private static Dictionary FromLevel(LevelState s) => new() { + { "current", s.Current }, + { "unlocked", new Array(s.Unlocked) }, + { "completed", new Array(s.Completed) }, + }; + + private static LevelState ToLevel(Dictionary d) => new() { + Current = d.TryGetValue("current", out var cur) ? (int)cur : 0, + Unlocked = d.TryGetValue("unlocked", out var ul) && (Array)ul is { } a1 ? a1.ToArray() : [0], + Completed = d.TryGetValue("completed", out var cl) && (Array)cl is { } a2 ? a2.ToArray() : [], + }; +} + +public record SaveSnapshot { + public required PlayerState PlayerState { get; init; } + public required LevelState LevelState { get; init; } +} \ No newline at end of file diff --git a/data/SaveClient.cs.uid b/data/SaveClient.cs.uid new file mode 100644 index 0000000..d334625 --- /dev/null +++ b/data/SaveClient.cs.uid @@ -0,0 +1 @@ +uid://bsf45t7m2wa07 diff --git a/features/ui/hud/Hud.cs b/features/ui/hud/Hud.cs new file mode 100644 index 0000000..99a08aa --- /dev/null +++ b/features/ui/hud/Hud.cs @@ -0,0 +1,34 @@ +using Chickensoft.AutoInject; +using Chickensoft.Introspection; +using Godot; +using Mr.BrickAdventures.game.repositories; +using Mr.BrickAdventures.scripts.components; + +namespace Mr.BrickAdventures.features.ui.hud; + +[Meta(typeof(IAutoNode))] +public partial class Hud : Node +{ + public override void _Notification(int what) => this.Notify(what); + + [Export] public HealthComponent Health { get; set; } = null!; + [Export] public Label CoinsLabel { get; set; } = null!; + [Export] public ProgressBar HealthBar { get; set; } = null!; + [Export] public Label LivesLabel { get; set; } = null!; + + [Dependency] public PlayerRepository Player => this.DependOn(); + + public void OnResolved() { + CoinsLabel.Text = $"{Tr("COINS_LABEL")}: {Player.Coins}"; + LivesLabel.Text = $"{Tr("LIVES_LABEL")}: {Player.Lives}"; + + Player.CoinsChanged += c => CoinsLabel.Text = $"{Tr("COINS_LABEL")}: {c}"; + Player.LivesChanged += l => LivesLabel.Text = $"{Tr("LIVES_LABEL")}: {l}"; + + if (Health != null) { + HealthBar.MaxValue = Health.MaxHealth; + HealthBar.Value = Health.Health; + Health.HealthChanged += (_, total) => { HealthBar.Value = total; }; + } + } +} \ No newline at end of file diff --git a/features/ui/hud/Hud.cs.uid b/features/ui/hud/Hud.cs.uid new file mode 100644 index 0000000..5014c39 --- /dev/null +++ b/features/ui/hud/Hud.cs.uid @@ -0,0 +1 @@ +uid://c1uwe5e1cfdxl diff --git a/features/ui/menus/MainMenu.cs b/features/ui/menus/MainMenu.cs new file mode 100644 index 0000000..d3bff9e --- /dev/null +++ b/features/ui/menus/MainMenu.cs @@ -0,0 +1,58 @@ +using Chickensoft.AutoInject; +using Chickensoft.Introspection; +using Godot; +using Mr.BrickAdventures.game.repositories; +using Mr.BrickAdventures.game.services; + +namespace Mr.BrickAdventures.features.ui.menus; + +[Meta(typeof(IAutoNode))] +public partial class MainMenu : Control +{ + public override void _Notification(int what) => this.Notify(what); + + [Export] public Control MainMenuControl { get; set; } = null!; + [Export] public Button NewGameButton { get; set; } = null!; + [Export] public Button ContinueButton { get; set; } = null!; + [Export] public Button SettingsButton { get; set; } = null!; + [Export] public Button CreditsButton { get; set; } = null!; + [Export] public Button ExitButton { get; set; } = null!; + [Export] public Label VersionLabel { get; set; } = null!; + [Export] public Control SettingsControl { get; set; } = null!; + [Export] public Control CreditsControl { get; set; } = null!; + [Export] public PackedScene FirstLevelScene { get; set; } = null!; + + [Dependency] public SaveService Save => this.DependOn(); + [Dependency] public LevelRepository Levels => this.DependOn(); + + public void OnReady() { + VersionLabel.Text = $"v. {ProjectSettings.GetSetting("application/config/version")}"; + + NewGameButton.Pressed += OnNewGamePressed; + ContinueButton.Pressed += OnContinuePressed; + SettingsButton.Pressed += () => SettingsControl.Show(); + CreditsButton.Pressed += () => CreditsControl.Show(); + ExitButton.Pressed += () => GetTree().Quit(); + } + + public void OnResolved() + { + ContinueButton.Disabled = !Save.Exists(); + (ContinueButton.Disabled ? NewGameButton : ContinueButton).GrabFocus(); + } + + private void OnNewGamePressed() { + Save.NewGame(); + Levels.SetCurrent(0); + GetTree().ChangeSceneToPacked(FirstLevelScene); + } + + private void OnContinuePressed() { + if (!Save.TryLoad()) { + // Fallback: start new game + OnNewGamePressed(); + return; + } + GetTree().ChangeSceneToPacked(FirstLevelScene); + } +} \ No newline at end of file diff --git a/features/ui/menus/MainMenu.cs.uid b/features/ui/menus/MainMenu.cs.uid new file mode 100644 index 0000000..1f5ab15 --- /dev/null +++ b/features/ui/menus/MainMenu.cs.uid @@ -0,0 +1 @@ +uid://fcsg0e8s36in diff --git a/features/ui/menus/PauseMenu.cs b/features/ui/menus/PauseMenu.cs new file mode 100644 index 0000000..85f8e84 --- /dev/null +++ b/features/ui/menus/PauseMenu.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.features.ui.menus; + +public class PauseMenu +{ + +} \ No newline at end of file diff --git a/features/ui/menus/PauseMenu.cs.uid b/features/ui/menus/PauseMenu.cs.uid new file mode 100644 index 0000000..511293d --- /dev/null +++ b/features/ui/menus/PauseMenu.cs.uid @@ -0,0 +1 @@ +uid://bwgs02wcfnm8u diff --git a/objects/ui/main_menu.tscn b/features/ui/menus/main_menu.tscn similarity index 73% rename from objects/ui/main_menu.tscn rename to features/ui/menus/main_menu.tscn index 3bdf935..ae61493 100644 --- a/objects/ui/main_menu.tscn +++ b/features/ui/menus/main_menu.tscn @@ -1,25 +1,25 @@ [gd_scene load_steps=3 format=3 uid="uid://8b6ol5sssbgo"] -[ext_resource type="Script" uid="uid://hyfvthdbgjbc" path="res://scripts/ui/main_menu.gd" id="1_epxpl"] +[ext_resource type="Script" uid="uid://fcsg0e8s36in" path="res://features/ui/menus/MainMenu.cs" id="1_q8hru"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qv2q0"] bg_color = Color(0, 0, 0, 1) -[node name="MainMenu" type="Control" node_paths=PackedStringArray("main_menu_control", "new_game_button", "continue_button", "settings_button", "credits_button", "exit_button", "version_label")] +[node name="MainMenu" type="Control" node_paths=PackedStringArray("MainMenuControl", "NewGameButton", "ContinueButton", "SettingsButton", "CreditsButton", "ExitButton", "VersionLabel")] layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -script = ExtResource("1_epxpl") -main_menu_control = NodePath(".") -new_game_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/NewGameButton") -continue_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/ContinueButton") -settings_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/SettingsButton") -credits_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/CreditsButton") -exit_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/QuitButton") -version_label = NodePath("PanelContainer/MarginContainer/VBoxContainer/version") +script = ExtResource("1_q8hru") +MainMenuControl = NodePath(".") +NewGameButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/NewGameButton") +ContinueButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/ContinueButton") +SettingsButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/SettingsButton") +CreditsButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/CreditsButton") +ExitButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/QuitButton") +VersionLabel = NodePath("PanelContainer/MarginContainer/VBoxContainer/version") [node name="PanelContainer" type="PanelContainer" parent="."] layout_mode = 1 diff --git a/features/ui/settings/AudioSettings.cs b/features/ui/settings/AudioSettings.cs new file mode 100644 index 0000000..7d16574 --- /dev/null +++ b/features/ui/settings/AudioSettings.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.features.ui.settings; + +public class AudioSettings +{ + +} \ No newline at end of file diff --git a/features/ui/settings/AudioSettings.cs.uid b/features/ui/settings/AudioSettings.cs.uid new file mode 100644 index 0000000..96fb589 --- /dev/null +++ b/features/ui/settings/AudioSettings.cs.uid @@ -0,0 +1 @@ +uid://bnj36dhskiem diff --git a/game/repositories/LevelRepository.cs b/game/repositories/LevelRepository.cs new file mode 100644 index 0000000..35900b3 --- /dev/null +++ b/game/repositories/LevelRepository.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mr.BrickAdventures.game.repositories; + +public sealed class LevelRepository +{ + public int Current { get; private set; } = 0; + public HashSet Unlocked { get; } = new() { 0 }; + public HashSet Completed { get; } = new(); + + public event Action? CurrentChanged; + + public void SetCurrent(int idx) { Current = idx; CurrentChanged?.Invoke(Current); } + public void Unlock(int idx) => Unlocked.Add(idx); + public void Complete(int idx) { Completed.Add(idx); Unlock(idx + 1); } + + public LevelState Export() => new() { + Current = Current, Unlocked = [..Unlocked], Completed = [..Completed] + }; + public void Load(LevelState s) { + Current = s.Current; + Unlocked.Clear(); foreach (var i in s.Unlocked) Unlocked.Add(i); + Completed.Clear(); foreach (var i in s.Completed) Completed.Add(i); + CurrentChanged?.Invoke(Current); + } +} + +public record LevelState { + public int Current; + public int[] Unlocked = []; + public int[] Completed = []; +} \ No newline at end of file diff --git a/game/repositories/LevelRepository.cs.uid b/game/repositories/LevelRepository.cs.uid new file mode 100644 index 0000000..51ccdf5 --- /dev/null +++ b/game/repositories/LevelRepository.cs.uid @@ -0,0 +1 @@ +uid://d0604lmwpadt5 diff --git a/game/repositories/PlayerRepository.cs b/game/repositories/PlayerRepository.cs new file mode 100644 index 0000000..14eb6c5 --- /dev/null +++ b/game/repositories/PlayerRepository.cs @@ -0,0 +1,25 @@ +using System; + +namespace Mr.BrickAdventures.game.repositories; + +public sealed class PlayerRepository +{ + public int Coins { get; private set; } = 0; + public int Lives { get; private set; } = 3; + + public event Action? CoinsChanged; + public event Action? LivesChanged; + + public void SetCoins(int value) { Coins = Math.Max(0, value); CoinsChanged?.Invoke(Coins); } + public void AddCoins(int amount) { SetCoins(Coins + amount); } + public void RemoveCoins(int amount){ SetCoins(Coins - amount); } + + public void SetLives(int value) { Lives = value; LivesChanged?.Invoke(Lives); } + public void AddLives(int amount) { SetLives(Lives + amount); } + public void RemoveLives(int amount){ SetLives(Lives - amount); } + + public PlayerState Export() => new() { Coins = Coins, Lives = Lives }; + public void Load(PlayerState s) { SetCoins(s.Coins); SetLives(s.Lives); } +} + +public record PlayerState { public int Coins; public int Lives; } \ No newline at end of file diff --git a/game/repositories/PlayerRepository.cs.uid b/game/repositories/PlayerRepository.cs.uid new file mode 100644 index 0000000..0aa5531 --- /dev/null +++ b/game/repositories/PlayerRepository.cs.uid @@ -0,0 +1 @@ +uid://d1dijkt574x4b diff --git a/game/repositories/SessionRepository.cs b/game/repositories/SessionRepository.cs new file mode 100644 index 0000000..93781b6 --- /dev/null +++ b/game/repositories/SessionRepository.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.game.repositories; + +public sealed class SessionRepository +{ + +} \ No newline at end of file diff --git a/game/repositories/SessionRepository.cs.uid b/game/repositories/SessionRepository.cs.uid new file mode 100644 index 0000000..32a435b --- /dev/null +++ b/game/repositories/SessionRepository.cs.uid @@ -0,0 +1 @@ +uid://b550hcqugygv0 diff --git a/game/repositories/SettingsRepository.cs b/game/repositories/SettingsRepository.cs new file mode 100644 index 0000000..289a6b9 --- /dev/null +++ b/game/repositories/SettingsRepository.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.game.repositories; + +public class SettingsRepository +{ + +} \ No newline at end of file diff --git a/game/repositories/SettingsRepository.cs.uid b/game/repositories/SettingsRepository.cs.uid new file mode 100644 index 0000000..f6b01ee --- /dev/null +++ b/game/repositories/SettingsRepository.cs.uid @@ -0,0 +1 @@ +uid://bk11iduo7bg2h diff --git a/game/repositories/SkillsRepository.cs b/game/repositories/SkillsRepository.cs new file mode 100644 index 0000000..dbe64be --- /dev/null +++ b/game/repositories/SkillsRepository.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.game.repositories; + +public class SkillsRepository +{ + +} \ No newline at end of file diff --git a/game/repositories/SkillsRepository.cs.uid b/game/repositories/SkillsRepository.cs.uid new file mode 100644 index 0000000..bdb96d4 --- /dev/null +++ b/game/repositories/SkillsRepository.cs.uid @@ -0,0 +1 @@ +uid://cymx7mtmdblun diff --git a/game/services/LevelService.cs b/game/services/LevelService.cs new file mode 100644 index 0000000..4b14d2d --- /dev/null +++ b/game/services/LevelService.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.game.services; + +public sealed class LevelService +{ + +} \ No newline at end of file diff --git a/game/services/LevelService.cs.uid b/game/services/LevelService.cs.uid new file mode 100644 index 0000000..0eced1f --- /dev/null +++ b/game/services/LevelService.cs.uid @@ -0,0 +1 @@ +uid://b2tsi3cjnh5xq diff --git a/game/services/SaveService.cs b/game/services/SaveService.cs new file mode 100644 index 0000000..b7b2722 --- /dev/null +++ b/game/services/SaveService.cs @@ -0,0 +1,32 @@ +using Mr.BrickAdventures.data; +using Mr.BrickAdventures.game.repositories; + +namespace Mr.BrickAdventures.game.services; + +public sealed class SaveService +{ + private readonly PlayerRepository _players; + private readonly LevelRepository _levels; + private readonly SaveClient _save; + + public SaveService(PlayerRepository players, LevelRepository levels, SaveClient save) { + _players = players; _levels = levels; _save = save; + } + + + public bool TryLoad() { + if (!_save.TryLoad(out var p, out var l)) return false; + _players.Load(p); + _levels.Load(l); + return true; + } + + public void Save() => _save.Save(_players.Export(), _levels.Export()); + public bool Exists() => _save.Exists(); + + public void NewGame() { + _players.Load(new PlayerState { Coins = 0, Lives = 3 }); + _levels.Load(new LevelState { Current = 0, Unlocked = [0], Completed = [] }); + Save(); + } +} \ No newline at end of file diff --git a/game/services/SaveService.cs.uid b/game/services/SaveService.cs.uid new file mode 100644 index 0000000..aa8532c --- /dev/null +++ b/game/services/SaveService.cs.uid @@ -0,0 +1 @@ +uid://dxqkxlkkivxog diff --git a/game/services/SkillService.cs b/game/services/SkillService.cs new file mode 100644 index 0000000..213a765 --- /dev/null +++ b/game/services/SkillService.cs @@ -0,0 +1,6 @@ +namespace Mr.BrickAdventures.game.services; + +public sealed class SkillService +{ + +} \ No newline at end of file diff --git a/game/services/SkillService.cs.uid b/game/services/SkillService.cs.uid new file mode 100644 index 0000000..59bce5a --- /dev/null +++ b/game/services/SkillService.cs.uid @@ -0,0 +1 @@ +uid://dim21hs12wdi5 diff --git a/objects/level/ui_layer.tscn b/objects/level/ui_layer.tscn index 64549a3..219e5a3 100644 --- a/objects/level/ui_layer.tscn +++ b/objects/level/ui_layer.tscn @@ -34,9 +34,8 @@ visible = false offset_top = 32.0 components_to_disable = [null] -[node name="Pause menu" parent="." node_paths=PackedStringArray("settings_menu") instance=ExtResource("6_1q4vn")] +[node name="Pause menu" parent="." instance=ExtResource("6_1q4vn")] visible = false -settings_menu = NodePath("../Settings menu") [node name="Settings menu" parent="." node_paths=PackedStringArray("input_settings", "audio_settings") instance=ExtResource("7_hkjav")] visible = false diff --git a/objects/ui/pause_menu.tscn b/objects/ui/pause_menu.tscn index d995ee9..14d62bf 100644 --- a/objects/ui/pause_menu.tscn +++ b/objects/ui/pause_menu.tscn @@ -1,12 +1,11 @@ -[gd_scene load_steps=4 format=3 uid="uid://i6mnjbjcoqe5"] +[gd_scene load_steps=3 format=3 uid="uid://i6mnjbjcoqe5"] -[ext_resource type="Script" uid="uid://cugifchx6jhuk" path="res://scripts/ui/pause_menu.gd" id="1_aktha"] -[ext_resource type="PackedScene" uid="uid://cl00e2ocomk3m" path="res://scenes/main_menu.tscn" id="2_h4pd5"] +[ext_resource type="Script" uid="uid://cakgxndurgfa3" path="res://scripts/UI/PauseMenu.cs" id="1_aktha"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_g4ivv"] bg_color = Color(0, 0, 0, 1) -[node name="Pause menu" type="Control" node_paths=PackedStringArray("pause_menu_control", "resume_button", "quit_button", "settings_button", "exit_to_menu_button")] +[node name="Pause menu" type="Control" node_paths=PackedStringArray("ResumeButton", "MainMenuButton", "QuitButton", "SettingsButton")] layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 @@ -16,12 +15,10 @@ grow_vertical = 2 size_flags_horizontal = 6 size_flags_vertical = 6 script = ExtResource("1_aktha") -pause_menu_control = NodePath(".") -resume_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Resume Button") -quit_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Quit game Button") -settings_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Settings Button") -exit_to_menu_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Exit to menu Button") -exit_to_menu_scene = ExtResource("2_h4pd5") +ResumeButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Resume Button") +MainMenuButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Exit to menu Button") +QuitButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Quit game Button") +SettingsButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Settings Button") [node name="PanelContainer" type="PanelContainer" parent="."] layout_mode = 1 diff --git a/scenes/level_village_1.tscn b/scenes/level_village_1.tscn index 73e8824..960c277 100644 --- a/scenes/level_village_1.tscn +++ b/scenes/level_village_1.tscn @@ -77,6 +77,10 @@ nodes_to_disable = [NodePath("../../Brick Player")] skill_unlocker = NodePath("../../Brick Player/SkillUnlockerComponent") components_to_disable = [NodePath("../../Brick Player")] +[node name="Pause menu" parent="UI Layer" index="4" node_paths=PackedStringArray("PauseMenuControl", "SettingsControl")] +PauseMenuControl = NodePath(".") +SettingsControl = NodePath("../Settings menu") + [node name="Global Light" parent="." instance=ExtResource("4_mc58c")] [node name="Camera2D" parent="." instance=ExtResource("5_sskgn")] diff --git a/scenes/main_menu.tscn b/scenes/main_menu.tscn index b1dac87..5f20dd9 100644 --- a/scenes/main_menu.tscn +++ b/scenes/main_menu.tscn @@ -1,27 +1,33 @@ -[gd_scene load_steps=6 format=3 uid="uid://cl00e2ocomk3m"] +[gd_scene load_steps=8 format=3 uid="uid://cl00e2ocomk3m"] -[ext_resource type="PackedScene" uid="uid://8b6ol5sssbgo" path="res://objects/ui/main_menu.tscn" id="1_ekxnf"] +[ext_resource type="PackedScene" uid="uid://8b6ol5sssbgo" path="res://features/ui/menus/main_menu.tscn" id="1_ekxnf"] +[ext_resource type="Script" uid="uid://dg2l7cw6da4vb" path="res://common/AppRoot.cs" id="1_rtw2f"] [ext_resource type="PackedScene" uid="uid://y0ae6e7t70fj" path="res://objects/ui/settings_menu.tscn" id="2_bqqt6"] [ext_resource type="PackedScene" uid="uid://bwgmrcyj4mvu" path="res://objects/ui/credits.tscn" id="3_bqqt6"] +[ext_resource type="PackedScene" uid="uid://bol7g83v2accs" path="res://scenes/level_village_1.tscn" id="3_oa1go"] [ext_resource type="PackedScene" uid="uid://b5fx1vdfky307" path="res://objects/ui/audio_settings.tscn" id="4_8ln24"] [ext_resource type="PackedScene" uid="uid://cvfsbiy5ggrpg" path="res://objects/ui/input_settings.tscn" id="5_rtw2f"] -[node name="Main menu" type="CanvasLayer"] +[node name="AppRoot" type="Node2D"] +script = ExtResource("1_rtw2f") -[node name="MainMenu" parent="." node_paths=PackedStringArray("settings_control", "credits_control") instance=ExtResource("1_ekxnf")] -settings_control = NodePath("../Settings menu") -credits_control = NodePath("../Credits") +[node name="Main menu" type="CanvasLayer" parent="."] -[node name="Settings menu" parent="." node_paths=PackedStringArray("input_settings", "audio_settings") instance=ExtResource("2_bqqt6")] +[node name="MainMenu" parent="Main menu" node_paths=PackedStringArray("SettingsControl", "CreditsControl") instance=ExtResource("1_ekxnf")] +SettingsControl = NodePath("../Settings menu") +CreditsControl = NodePath("../Credits") +FirstLevelScene = ExtResource("3_oa1go") + +[node name="Settings menu" parent="Main menu" node_paths=PackedStringArray("input_settings", "audio_settings") instance=ExtResource("2_bqqt6")] visible = false input_settings = NodePath("../Input Settings") audio_settings = NodePath("../Audio settings") -[node name="Credits" parent="." instance=ExtResource("3_bqqt6")] +[node name="Credits" parent="Main menu" instance=ExtResource("3_bqqt6")] visible = false -[node name="Audio settings" parent="." instance=ExtResource("4_8ln24")] +[node name="Audio settings" parent="Main menu" instance=ExtResource("4_8ln24")] visible = false -[node name="Input Settings" parent="." instance=ExtResource("5_rtw2f")] +[node name="Input Settings" parent="Main menu" instance=ExtResource("5_rtw2f")] visible = false diff --git a/scripts/UI/Hud.cs b/scripts/UI/Hud.cs deleted file mode 100644 index 5939a8e..0000000 --- a/scripts/UI/Hud.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Godot; -using Mr.BrickAdventures.Autoloads; -using Mr.BrickAdventures.scripts.components; - -namespace Mr.BrickAdventures.scripts.UI; - -public partial class Hud : Node -{ - [Export] public HealthComponent Health { get; set; } - [Export] public Label CoinsLabel { get; set; } - [Export] public ProgressBar HealthBar { get; set; } - [Export] public Label LivesLabel { get; set; } - - private GameManager _gameManager; - - public override void _Ready() - { - _gameManager = GetNode("/root/GameManager"); - } - - public override void _Process(double delta) - { - SetHealthBar(); - SetLivesLabel(); - SetCoinsLabel(); - } - - private void SetCoinsLabel() - { - CoinsLabel.Text = Tr("COINS_LABEL") + ": " + _gameManager.GetCoins(); - } - - private void SetLivesLabel() - { - LivesLabel.Text = Tr("LIVES_LABEL") + ": " + _gameManager.GetLives(); - } - - private void SetHealthBar() - { - HealthBar.Value = Health.Health; - HealthBar.MaxValue = Health.MaxHealth; - } -} \ No newline at end of file diff --git a/scripts/UI/Hud.cs.uid b/scripts/UI/Hud.cs.uid deleted file mode 100644 index 15ddc0b..0000000 --- a/scripts/UI/Hud.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://wfj674u4486f