From 425bf2ad272a45dff6752d6c65ea62163784ad86 Mon Sep 17 00:00:00 2001 From: Fries Date: Sat, 20 May 2023 21:42:38 -0700 Subject: [PATCH] make a settings menu and general refactoring i added more to the main menu, as it has a settings menu now, that stores its files with json. i also changed the font to atkinson hyperlegible and made a BaseMenu class that takes care of the screen scaling for menus. i also refactored the project folder structure to make it more organized. --- Fonts/AtkinsonHyperlegible-Regular.ttf | Bin 0 -> 52476 bytes Fonts/AtkinsonHyperlegible-Regular.ttf.import | 38 +++++++++ .../BouncyMaterial.tres | 0 Resources/MenuTheme.tres | 11 +++ Resources/ScoreLabelSettings.tres | 7 ++ Scenes/MainMenu.tscn | 29 ------- Scenes/{ => Objects}/Ball.tscn | 4 +- Scenes/{ => Objects}/Enemy.tscn | 4 +- Scenes/{ => Objects}/Paddle.tscn | 4 +- Scenes/{ => Objects}/Walls.tscn | 4 +- Scenes/Pong.tscn | 16 ++-- Scenes/UI/Menus/MainMenu.tscn | 32 +++++++ Scenes/UI/Menus/Settings.tscn | 63 ++++++++++++++ Scenes/{ => UI}/Score.tscn | 14 ++-- Scripts/Data/Settings.cs | 20 +++++ Scripts/Managers/MainMenuManager.cs | 28 ------- .../{SceneManager.cs => PongSceneManager.cs} | 2 +- Scripts/Managers/SettingsManager.cs | 78 ++++++++++++++++++ Scripts/Managers/UI/BaseMenu.cs | 43 ++++++++++ Scripts/Managers/UI/Menus/MainMenu.cs | 20 +++++ Scripts/Managers/UI/Menus/Settings.cs | 52 ++++++++++++ .../Managers/{ScoreManager.gd => UI/Score.gd} | 0 Scripts/Managers/{WallManager.cs => Walls.cs} | 9 +- Scripts/{Nodes => Objects}/Ball.cs | 5 +- Scripts/{Nodes => Objects}/Enemy.cs | 16 ++-- Scripts/{Nodes => Objects}/Paddle.cs | 2 +- addons/BaseMenu/BaseMenu.cs | 20 +++++ addons/BaseMenu/plugin.cfg | 7 ++ project.godot | 10 ++- 29 files changed, 440 insertions(+), 98 deletions(-) create mode 100644 Fonts/AtkinsonHyperlegible-Regular.ttf create mode 100644 Fonts/AtkinsonHyperlegible-Regular.ttf.import rename BouncyMaterial.tres => Resources/BouncyMaterial.tres (100%) create mode 100644 Resources/MenuTheme.tres create mode 100644 Resources/ScoreLabelSettings.tres delete mode 100644 Scenes/MainMenu.tscn rename Scenes/{ => Objects}/Ball.tscn (80%) rename Scenes/{ => Objects}/Enemy.tscn (84%) rename Scenes/{ => Objects}/Paddle.tscn (83%) rename Scenes/{ => Objects}/Walls.tscn (94%) create mode 100644 Scenes/UI/Menus/MainMenu.tscn create mode 100644 Scenes/UI/Menus/Settings.tscn rename Scenes/{ => UI}/Score.tscn (52%) create mode 100644 Scripts/Data/Settings.cs delete mode 100644 Scripts/Managers/MainMenuManager.cs rename Scripts/Managers/{SceneManager.cs => PongSceneManager.cs} (80%) create mode 100644 Scripts/Managers/SettingsManager.cs create mode 100644 Scripts/Managers/UI/BaseMenu.cs create mode 100644 Scripts/Managers/UI/Menus/MainMenu.cs create mode 100644 Scripts/Managers/UI/Menus/Settings.cs rename Scripts/Managers/{ScoreManager.gd => UI/Score.gd} (100%) rename Scripts/Managers/{WallManager.cs => Walls.cs} (78%) rename Scripts/{Nodes => Objects}/Ball.cs (92%) rename Scripts/{Nodes => Objects}/Enemy.cs (92%) rename Scripts/{Nodes => Objects}/Paddle.cs (96%) create mode 100644 addons/BaseMenu/BaseMenu.cs create mode 100644 addons/BaseMenu/plugin.cfg diff --git a/Fonts/AtkinsonHyperlegible-Regular.ttf b/Fonts/AtkinsonHyperlegible-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..46def7f135c24cf44f720c3a025ed1e24decfba8 GIT binary patch literal 52476 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�?A;q2u`l9gp9-G4wc$gQM4KdDM7H| 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 literal 0 HcmV?d00001 diff --git a/Fonts/AtkinsonHyperlegible-Regular.ttf.import b/Fonts/AtkinsonHyperlegible-Regular.ttf.import new file mode 100644 index 0000000..7513512 --- /dev/null +++ b/Fonts/AtkinsonHyperlegible-Regular.ttf.import @@ -0,0 +1,38 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://dq8ojwul8884x" +path="res://.godot/imported/AtkinsonHyperlegible-Regular.ttf-8428368664fa87474099ab40902da12f.fontdata" + +[deps] + +source_file="res://Fonts/AtkinsonHyperlegible-Regular.ttf" +dest_files=["res://.godot/imported/AtkinsonHyperlegible-Regular.ttf-8428368664fa87474099ab40902da12f.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +multichannel_signed_distance_field=true +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[{ +"chars": [], +"glyphs": [], +"name": "New Configuration", +"size": Vector2i(16, 0) +}] +language_support={} +script_support={} +opentype_features={} diff --git a/BouncyMaterial.tres b/Resources/BouncyMaterial.tres similarity index 100% rename from BouncyMaterial.tres rename to Resources/BouncyMaterial.tres diff --git a/Resources/MenuTheme.tres b/Resources/MenuTheme.tres new file mode 100644 index 0000000..f2f306b --- /dev/null +++ b/Resources/MenuTheme.tres @@ -0,0 +1,11 @@ +[gd_resource type="Theme" load_steps=2 format=3 uid="uid://bk0vu443pyq1g"] + +[ext_resource type="FontFile" uid="uid://dq8ojwul8884x" path="res://Fonts/AtkinsonHyperlegible-Regular.ttf" id="1_aadm8"] + +[resource] +Button/font_sizes/font_size = 32 +Button/fonts/font = ExtResource("1_aadm8") +Label/font_sizes/font_size = 32 +Label/fonts/font = ExtResource("1_aadm8") +LineEdit/font_sizes/font_size = 32 +LineEdit/fonts/font = ExtResource("1_aadm8") diff --git a/Resources/ScoreLabelSettings.tres b/Resources/ScoreLabelSettings.tres new file mode 100644 index 0000000..bbcb0b8 --- /dev/null +++ b/Resources/ScoreLabelSettings.tres @@ -0,0 +1,7 @@ +[gd_resource type="LabelSettings" load_steps=2 format=3 uid="uid://dkyqusswobqb3"] + +[ext_resource type="FontFile" uid="uid://dq8ojwul8884x" path="res://Fonts/AtkinsonHyperlegible-Regular.ttf" id="1_hcuvo"] + +[resource] +font = ExtResource("1_hcuvo") +font_size = 64 diff --git a/Scenes/MainMenu.tscn b/Scenes/MainMenu.tscn deleted file mode 100644 index 14306d5..0000000 --- a/Scenes/MainMenu.tscn +++ /dev/null @@ -1,29 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://0vkrkvlevwkj"] - -[ext_resource type="Script" path="res://Scripts/Managers/MainMenuManager.cs" id="1_tuygx"] - -[sub_resource type="LabelSettings" id="LabelSettings_vv6u3"] -font_size = 64 - -[node name="MainMenu" type="VBoxContainer"] -offset_right = 800.0 -offset_bottom = 600.0 -size_flags_horizontal = 3 -size_flags_vertical = 3 -script = ExtResource("1_tuygx") - -[node name="Label" type="Label" parent="."] -layout_mode = 2 -text = "Pong -" -label_settings = SubResource("LabelSettings_vv6u3") -horizontal_alignment = 1 -vertical_alignment = 1 - -[node name="Button" type="Button" parent="."] -layout_mode = 2 -theme_override_font_sizes/font_size = 32 -text = "Play -" - -[connection signal="pressed" from="Button" to="." method="OnButtonPressed"] diff --git a/Scenes/Ball.tscn b/Scenes/Objects/Ball.tscn similarity index 80% rename from Scenes/Ball.tscn rename to Scenes/Objects/Ball.tscn index c3f165b..05e0125 100644 --- a/Scenes/Ball.tscn +++ b/Scenes/Objects/Ball.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=4 format=3 uid="uid://67qguep14iko"] +[gd_scene load_steps=4 format=3] -[ext_resource type="Script" path="res://Scripts/Nodes/Ball.cs" id="1_474si"] +[ext_resource type="Script" path="res://Scripts/Objects/Ball.cs" id="1_474si"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_yq7ub"] size = Vector2(50, 50) diff --git a/Scenes/Enemy.tscn b/Scenes/Objects/Enemy.tscn similarity index 84% rename from Scenes/Enemy.tscn rename to Scenes/Objects/Enemy.tscn index 031f189..73c317b 100644 --- a/Scenes/Enemy.tscn +++ b/Scenes/Objects/Enemy.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=5 format=3] -[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://BouncyMaterial.tres" id="1_e3kk5"] -[ext_resource type="Script" path="res://Scripts/Nodes/Enemy.cs" id="1_fbrtv"] +[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://Resources/BouncyMaterial.tres" id="1_e3kk5"] +[ext_resource type="Script" path="res://Scripts/Objects/Enemy.cs" id="1_fbrtv"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_iw3nx"] size = Vector2(50, 75) diff --git a/Scenes/Paddle.tscn b/Scenes/Objects/Paddle.tscn similarity index 83% rename from Scenes/Paddle.tscn rename to Scenes/Objects/Paddle.tscn index 6ab4142..147a898 100644 --- a/Scenes/Paddle.tscn +++ b/Scenes/Objects/Paddle.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=5 format=3] -[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://BouncyMaterial.tres" id="1_76uik"] -[ext_resource type="Script" path="res://Scripts/Nodes/Paddle.cs" id="1_uv7s3"] +[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://Resources/BouncyMaterial.tres" id="1_76uik"] +[ext_resource type="Script" path="res://Scripts/Objects/Paddle.cs" id="1_uv7s3"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_iw3nx"] size = Vector2(50, 75) diff --git a/Scenes/Walls.tscn b/Scenes/Objects/Walls.tscn similarity index 94% rename from Scenes/Walls.tscn rename to Scenes/Objects/Walls.tscn index a4a2866..1547fcd 100644 --- a/Scenes/Walls.tscn +++ b/Scenes/Objects/Walls.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=8 format=3 uid="uid://dsvv7vqonylr1"] +[gd_scene load_steps=8 format=3] -[ext_resource type="Script" path="res://Scripts/Managers/WallManager.cs" id="1_mxer2"] +[ext_resource type="Script" path="res://Scripts/Managers/Walls.cs" id="1_mxer2"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_f7jy5"] size = Vector2(30, 1) diff --git a/Scenes/Pong.tscn b/Scenes/Pong.tscn index a0b47d6..8141f75 100644 --- a/Scenes/Pong.tscn +++ b/Scenes/Pong.tscn @@ -1,14 +1,14 @@ -[gd_scene load_steps=7 format=3 uid="uid://wn48xnd0lstq"] +[gd_scene load_steps=7 format=3 uid="uid://bh3p1hnvsviu6"] -[ext_resource type="PackedScene" path="res://Scenes/Paddle.tscn" id="1_5rs0o"] -[ext_resource type="Script" path="res://Scripts/Managers/SceneManager.cs" id="1_m8437"] -[ext_resource type="PackedScene" uid="uid://co2rv0nci8sbm" path="res://Scenes/Score.tscn" id="2_f3jwj"] -[ext_resource type="PackedScene" uid="uid://67qguep14iko" path="res://Scenes/Ball.tscn" id="2_u2ksv"] -[ext_resource type="PackedScene" uid="uid://dsvv7vqonylr1" path="res://Scenes/Walls.tscn" id="3_jfis7"] -[ext_resource type="PackedScene" path="res://Scenes/Enemy.tscn" id="4_uwvof"] +[ext_resource type="PackedScene" path="res://Scenes/Objects/Paddle.tscn" id="1_5rs0o"] +[ext_resource type="Script" path="res://Scripts/Managers/PongSceneManager.cs" id="1_ee533"] +[ext_resource type="PackedScene" uid="uid://clsmrwvyrt7av" path="res://Scenes/UI/Score.tscn" id="2_f3jwj"] +[ext_resource type="PackedScene" path="res://Scenes/Objects/Ball.tscn" id="2_u2ksv"] +[ext_resource type="PackedScene" path="res://Scenes/Objects/Walls.tscn" id="3_jfis7"] +[ext_resource type="PackedScene" path="res://Scenes/Objects/Enemy.tscn" id="4_uwvof"] [node name="Pong" type="Node2D"] -script = ExtResource("1_m8437") +script = ExtResource("1_ee533") [node name="Score" parent="." instance=ExtResource("2_f3jwj")] diff --git a/Scenes/UI/Menus/MainMenu.tscn b/Scenes/UI/Menus/MainMenu.tscn new file mode 100644 index 0000000..8c9425f --- /dev/null +++ b/Scenes/UI/Menus/MainMenu.tscn @@ -0,0 +1,32 @@ +[gd_scene load_steps=4 format=3 uid="uid://buvptlse06qej"] + +[ext_resource type="Script" path="res://Scripts/Managers/UI/Menus/MainMenu.cs" id="1_essvw"] +[ext_resource type="Theme" uid="uid://bk0vu443pyq1g" path="res://Resources/MenuTheme.tres" id="1_qt6h4"] +[ext_resource type="LabelSettings" uid="uid://dkyqusswobqb3" path="res://Resources/ScoreLabelSettings.tres" id="2_mtqkf"] + +[node name="MainMenu" type="VBoxContainer"] +offset_right = 800.0 +offset_bottom = 600.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme = ExtResource("1_qt6h4") +script = ExtResource("1_essvw") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +text = "Pong" +label_settings = ExtResource("2_mtqkf") +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="PlayButton" type="Button" parent="."] +layout_mode = 2 +text = "Play +" + +[node name="SettingsButton" type="Button" parent="."] +layout_mode = 2 +text = "Settings" + +[connection signal="pressed" from="PlayButton" to="." method="OnPlayButtonPressed"] +[connection signal="pressed" from="SettingsButton" to="." method="OnSettingsButtonPressed"] diff --git a/Scenes/UI/Menus/Settings.tscn b/Scenes/UI/Menus/Settings.tscn new file mode 100644 index 0000000..ba54748 --- /dev/null +++ b/Scenes/UI/Menus/Settings.tscn @@ -0,0 +1,63 @@ +[gd_scene load_steps=5 format=3 uid="uid://ic7535p11pds"] + +[ext_resource type="Theme" uid="uid://bk0vu443pyq1g" path="res://Resources/MenuTheme.tres" id="1_p8g8v"] +[ext_resource type="Script" path="res://Scripts/Managers/UI/Menus/Settings.cs" id="2_vlocu"] +[ext_resource type="LabelSettings" uid="uid://dkyqusswobqb3" path="res://Resources/ScoreLabelSettings.tres" id="2_wkoeb"] +[ext_resource type="FontFile" uid="uid://dq8ojwul8884x" path="res://Fonts/AtkinsonHyperlegible-Regular.ttf" id="3_ngmnl"] + +[node name="Settings" type="VBoxContainer"] +offset_right = 800.0 +offset_bottom = 600.0 +theme = ExtResource("1_p8g8v") +script = ExtResource("2_vlocu") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +text = "Settings +" +label_settings = ExtResource("2_wkoeb") +horizontal_alignment = 1 + +[node name="ScrollContainer" type="ScrollContainer" parent="."] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="InternalMainContainer" type="VBoxContainer" parent="ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ScaleContainer" type="VBoxContainer" parent="ScrollContainer/InternalMainContainer"] +layout_mode = 2 +size_flags_horizontal = 4 + +[node name="Label" type="Label" parent="ScrollContainer/InternalMainContainer/ScaleContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +text = "Scale +" + +[node name="Scale" type="SpinBox" parent="ScrollContainer/InternalMainContainer/ScaleContainer"] +layout_mode = 2 +min_value = 1.0 +max_value = 2.0 +step = 0.01 +value = 1.0 +alignment = 1 + +[node name="SaveButton" type="Button" parent="."] +layout_mode = 2 +disabled = true +text = "Save +" + +[node name="BackButton" type="Button" parent="."] +layout_mode = 2 +size_flags_vertical = 8 +theme_override_fonts/font = ExtResource("3_ngmnl") +theme_override_font_sizes/font_size = 32 +text = "Back +" + +[connection signal="pressed" from="SaveButton" to="." method="OnSaveButtonPressed"] +[connection signal="pressed" from="BackButton" to="." method="OnBackButtonPressed"] diff --git a/Scenes/Score.tscn b/Scenes/UI/Score.tscn similarity index 52% rename from Scenes/Score.tscn rename to Scenes/UI/Score.tscn index ae48c00..ac98af8 100644 --- a/Scenes/Score.tscn +++ b/Scenes/UI/Score.tscn @@ -1,9 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://co2rv0nci8sbm"] +[gd_scene load_steps=3 format=3 uid="uid://clsmrwvyrt7av"] -[ext_resource type="Script" path="res://Scripts/Managers/ScoreManager.gd" id="1_bdtqr"] - -[sub_resource type="LabelSettings" id="LabelSettings_piogj"] -font_size = 64 +[ext_resource type="Script" path="res://Scripts/Managers/UI/Score.gd" id="1_ytifn"] +[ext_resource type="LabelSettings" uid="uid://dkyqusswobqb3" path="res://Resources/ScoreLabelSettings.tres" id="2_mh7dc"] [node name="Score" type="HFlowContainer"] z_index = 1 @@ -11,20 +9,20 @@ offset_left = -378.0 offset_top = -272.0 offset_right = 378.0 offset_bottom = 268.0 -script = ExtResource("1_bdtqr") +script = ExtResource("1_ytifn") [node name="Player1" type="Label" parent="."] layout_mode = 2 size_flags_horizontal = 3 text = "0 " -label_settings = SubResource("LabelSettings_piogj") +label_settings = ExtResource("2_mh7dc") vertical_alignment = 1 [node name="Player2" type="Label" parent="."] layout_mode = 2 size_flags_horizontal = 3 text = "0" -label_settings = SubResource("LabelSettings_piogj") +label_settings = ExtResource("2_mh7dc") horizontal_alignment = 2 vertical_alignment = 1 diff --git a/Scripts/Data/Settings.cs b/Scripts/Data/Settings.cs new file mode 100644 index 0000000..e613166 --- /dev/null +++ b/Scripts/Data/Settings.cs @@ -0,0 +1,20 @@ +using System; +using System.Text.Json.Serialization; + +namespace Pong.Scripts.Data; + +/// +/// a structure containing the data of the settings. +/// +public struct Settings +{ + /// + /// the scale of the game. this can be from 1.0 to 2.0 + /// + public double Scale; + + /// + /// the default values of settings. + /// + public static Settings Default => new() { Scale = 1.0 }; +} diff --git a/Scripts/Managers/MainMenuManager.cs b/Scripts/Managers/MainMenuManager.cs deleted file mode 100644 index 684302a..0000000 --- a/Scripts/Managers/MainMenuManager.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Godot; - -namespace Pong.Scripts.Managers; - -public partial class MainMenuManager : VBoxContainer -{ - // Called when the node enters the scene tree for the first time. - public override void _Ready() - { - GetTree().Root.SizeChanged += AdaptUiToScreenResolution; - AdaptUiToScreenResolution(); - } - - /// - /// code that executes when the start button is pressed. this loads the Pong scene to the root - /// of the scene tree. - /// - private void OnButtonPressed() - { - GetTree().Root.SizeChanged -= AdaptUiToScreenResolution; - GetTree().ChangeSceneToFile("res://Scenes/Pong.tscn"); - } - - private void AdaptUiToScreenResolution() - { - Size = DisplayServer.WindowGetSize(); - } -} diff --git a/Scripts/Managers/SceneManager.cs b/Scripts/Managers/PongSceneManager.cs similarity index 80% rename from Scripts/Managers/SceneManager.cs rename to Scripts/Managers/PongSceneManager.cs index 4565617..8169bcb 100644 --- a/Scripts/Managers/SceneManager.cs +++ b/Scripts/Managers/PongSceneManager.cs @@ -2,7 +2,7 @@ using Godot; namespace Pong.Scripts.Managers; -public partial class SceneManager : Node2D +public partial class PongSceneManager : Node2D { public override void _Process(double delta) { diff --git a/Scripts/Managers/SettingsManager.cs b/Scripts/Managers/SettingsManager.cs new file mode 100644 index 0000000..d6e533f --- /dev/null +++ b/Scripts/Managers/SettingsManager.cs @@ -0,0 +1,78 @@ +using System; +using System.Text.Json; +using System.Threading.Tasks; +using Godot; +using Pong.Scripts.Data; + +namespace Pong.Scripts.Managers; + +public partial class SettingsManager : Node +{ + private const string SettingsPath = "user://settings.json"; + public Settings SettingsData = Settings.Default; + private static readonly JsonSerializerOptions SerializerOptions = new() { IncludeFields = true }; + public event Action SettingsChanged; + + public override async void _EnterTree() + { + await LoadSettings(); + } + + /// + /// load the settings data from the filesystem. + /// + private async Task LoadSettings() + { + try + { + if (!FileAccess.FileExists(SettingsPath)) + { + await SaveSettings(Settings.Default); + return; + } + + using var file = await OpenSettingsFile(FileAccess.ModeFlags.Read); + + SettingsData = + await Task.Run(() => JsonSerializer.Deserialize(file.GetAsText(), SerializerOptions)); + SettingsChanged?.Invoke(); + } + catch (Exception e) + { + PrintFileError(e); + } + } + + /// + /// open the settings file from the filesystem. + /// + /// a godot FileAccess object. + private static async Task OpenSettingsFile(FileAccess.ModeFlags flag) + { + return await Task.Run(() => FileAccess.Open(SettingsPath, flag)); + } + + internal async Task SaveSettings(Settings settings) + { + try + { + using var file = await OpenSettingsFile(FileAccess.ModeFlags.WriteRead); + var json = await Task.Run(() => JsonSerializer.Serialize(settings, SerializerOptions)); + await Task.Run(() => file.StoreBuffer(json.ToUtf8Buffer())); + SettingsData = settings; + SettingsChanged?.Invoke(); + return true; + } + catch (Exception e) + { + PrintFileError(e); + return false; + } + } + + private static void PrintFileError(Exception e) + { + GD.PrintErr($"a {e.GetType()} has occured while trying to load the settings file: {e}."); + GD.PrintErr("default settings will be used."); + } +} diff --git a/Scripts/Managers/UI/BaseMenu.cs b/Scripts/Managers/UI/BaseMenu.cs new file mode 100644 index 0000000..0639d3a --- /dev/null +++ b/Scripts/Managers/UI/BaseMenu.cs @@ -0,0 +1,43 @@ +using Godot; + +namespace Pong.Scripts.Managers.UI; + +public partial class BaseMenu : VBoxContainer +{ + private SettingsManager _settingsManager; + + public override void _EnterTree() + { + _settingsManager = GetNode("/root/SettingsManager"); + _settingsManager.SettingsChanged += AdaptUiToGameResolution; + GetTree().Root.SizeChanged += AdaptUiToGameResolution; + AdaptUiToGameResolution(); + + EnterTree(); + } + + public override void _ExitTree() + { + GetTree().Root.SizeChanged -= AdaptUiToGameResolution; + _settingsManager.SettingsChanged -= AdaptUiToGameResolution; + ExitTree(); + } + + protected virtual void EnterTree() + { + } + + protected virtual void ExitTree() + { + } + + /// + /// change the size of the UI container to the current resolution of the game. + /// + protected void AdaptUiToGameResolution() + { + var scale = _settingsManager.SettingsData.Scale; + Size = (Vector2)DisplayServer.WindowGetSize() / scale; + Scale = new Vector2(scale, scale); + } +} diff --git a/Scripts/Managers/UI/Menus/MainMenu.cs b/Scripts/Managers/UI/Menus/MainMenu.cs new file mode 100644 index 0000000..b17be61 --- /dev/null +++ b/Scripts/Managers/UI/Menus/MainMenu.cs @@ -0,0 +1,20 @@ +using Godot; + +namespace Pong.Scripts.Managers.UI.Menus; + +public partial class MainMenu : BaseMenu +{ + /// + /// code that executes when the start button is pressed. this loads the Pong scene to the root + /// of the scene tree. + /// + private void OnPlayButtonPressed() + { + GetTree().ChangeSceneToFile("res://Scenes/Pong.tscn"); + } + + private void OnSettingsButtonPressed() + { + GetTree().ChangeSceneToFile("res://Scenes/UI/Menus/Settings.tscn"); + } +} diff --git a/Scripts/Managers/UI/Menus/Settings.cs b/Scripts/Managers/UI/Menus/Settings.cs new file mode 100644 index 0000000..98cb070 --- /dev/null +++ b/Scripts/Managers/UI/Menus/Settings.cs @@ -0,0 +1,52 @@ +using Godot; + +namespace Pong.Scripts.Managers.UI.Menus; + +public partial class Settings : BaseMenu +{ + private SettingsManager _settings; + private SpinBox _scale; + private Button _saveButton; + + private bool _scaleModified; + + protected override void EnterTree() + { + GetNodes(); + + _scale.Value = _settings.SettingsData.Scale; + } + + private void OnBackButtonPressed() + { + GetTree().ChangeSceneToFile("res://Scenes/UI/Menus/MainMenu.tscn"); + } + + private void GetNodes() + { + _settings = GetNode("/root/SettingsManager"); + _scale = GetNode("ScrollContainer/InternalMainContainer/ScaleContainer/Scale"); + _saveButton = GetNode