diff --git a/Assets/Sounds/main.mp3 b/Assets/Sounds/main.mp3 new file mode 100644 index 0000000..b050d05 Binary files /dev/null and b/Assets/Sounds/main.mp3 differ diff --git a/Assets/Sounds/main.mp3.import b/Assets/Sounds/main.mp3.import new file mode 100644 index 0000000..e033423 --- /dev/null +++ b/Assets/Sounds/main.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://bktx5fs75wx8g" +path="res://.godot/imported/main.mp3-3bf9bc2fc12c40a98cb36034ea76f297.mp3str" + +[deps] + +source_file="res://Assets/Sounds/main.mp3" +dest_files=["res://.godot/imported/main.mp3-3bf9bc2fc12c40a98cb36034ea76f297.mp3str"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Game/Maps/map_1.tscn b/Game/Maps/map_1.tscn index e966c23..1df5e4b 100644 --- a/Game/Maps/map_1.tscn +++ b/Game/Maps/map_1.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=141 format=4 uid="uid://bgme05i7taycc"] +[gd_scene load_steps=142 format=4 uid="uid://bgme05i7taycc"] [ext_resource type="Texture2D" uid="uid://f1npbjsw71nk" path="res://Assets/Tiles/Fields/FieldsTile_01.png" id="1_fdpq6"] [ext_resource type="Script" uid="uid://xo6vbicdva8d" path="res://Game/Maps/map_1.gd" id="1_rec5e"] @@ -67,6 +67,7 @@ [ext_resource type="Texture2D" uid="uid://bof7eh3ttmi2f" path="res://Assets/Tiles/Fields/FieldsTile_64.png" id="64_5s0ky"] [ext_resource type="Texture2D" uid="uid://do3u4pgcgn7g3" path="res://Assets/Castles/Asset 27.png" id="65_ef8wx"] [ext_resource type="PackedScene" uid="uid://ddn64i6logtw0" path="res://Game/sidepanel.tscn" id="67_rec5e"] +[ext_resource type="PackedScene" uid="uid://c5r8h61c73dwv" path="res://Game/music_player.tscn" id="68_hg5c4"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_3uxyt"] texture = ExtResource("1_fdpq6") @@ -552,4 +553,6 @@ shape = SubResource("RectangleShape2D_sglle") [node name="SidePanel" parent="CanvasLayer" instance=ExtResource("67_rec5e")] size_flags_horizontal = 6 +[node name="MusicPlayer" parent="." instance=ExtResource("68_hg5c4")] + [connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] diff --git a/Game/Menu/main.gd b/Game/Menu/main.gd index d5c6390..1ec3528 100644 --- a/Game/Menu/main.gd +++ b/Game/Menu/main.gd @@ -1,5 +1,33 @@ extends Control +func _ready() -> void: + load_settings() + +func load_settings(): + var config = ConfigFile.new() + var err = config.load("user://settings.cfg") + if err == OK: + # Load resolution + var width = config.get_value("screen", "width", -1) + var height = config.get_value("screen", "height", -1) + var res_to_set = null + if width != -1 and height != -1: + res_to_set = Vector2i(width, height) + + var mode = config.get_value("screen", "mode", 0) # Default to 0 = Windowed + + match mode: + 0: # Windowed + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) + 1: # Fullscreen + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) + 2: # Borderless / Exclusive fullscreen + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN) + + # Apply screen size only if mode is not Fullscreen, and resolution is valid + if mode != 1 and res_to_set != null: + DisplayServer.window_set_size(res_to_set) + func _on_button_pressed() -> void: diff --git a/Game/Menu/main.tscn b/Game/Menu/main.tscn index bc28642..a773752 100644 --- a/Game/Menu/main.tscn +++ b/Game/Menu/main.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=9 format=3 uid="uid://6x8vpcfwmxjd"] +[gd_scene load_steps=10 format=3 uid="uid://6x8vpcfwmxjd"] [ext_resource type="Texture2D" uid="uid://bgy114b67j3kg" path="res://Assets/Others/8-bit-graphics-pixels-scene-with-castle.jpg" id="1_3jfgb"] [ext_resource type="Script" uid="uid://cnle2j2fnno26" path="res://Game/Menu/main.gd" id="1_i0ya0"] [ext_resource type="FontFile" uid="uid://bu44ne346ymoe" path="res://Assets/Others/Canterbury.ttf" id="2_i0ya0"] +[ext_resource type="PackedScene" uid="uid://c5r8h61c73dwv" path="res://Game/music_player.tscn" id="4_14uxm"] [sub_resource type="StyleBoxTexture" id="StyleBoxTexture_14uxm"] texture = ExtResource("1_3jfgb") @@ -120,6 +121,8 @@ theme_override_fonts/font = ExtResource("2_i0ya0") theme_override_font_sizes/font_size = 32 text = "Guardians of the Last Cytadel" +[node name="MusicPlayer" parent="." instance=ExtResource("4_14uxm")] + [connection signal="pressed" from="VBoxContainer/Button" to="." method="_on_button_pressed"] [connection signal="pressed" from="VBoxContainer/Button2" to="." method="_on_button_2_pressed"] [connection signal="pressed" from="VBoxContainer/Button3" to="." method="_on_button_3_pressed"] diff --git a/Game/Menu/mapselector.tscn b/Game/Menu/mapselector.tscn index 99fc082..c2b49d4 100644 --- a/Game/Menu/mapselector.tscn +++ b/Game/Menu/mapselector.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://cxet2lvdco2ak"] +[gd_scene load_steps=14 format=3 uid="uid://cxet2lvdco2ak"] [ext_resource type="Script" uid="uid://y5h2sfhsyn7f" path="res://Game/Menu/mapselector.gd" id="1_cnef1"] [ext_resource type="Texture2D" uid="uid://bgy114b67j3kg" path="res://Assets/Others/8-bit-graphics-pixels-scene-with-castle.jpg" id="1_jteil"] @@ -20,6 +20,32 @@ texture = ExtResource("3_2uj2s") [sub_resource type="StyleBoxTexture" id="StyleBoxTexture_cg1t8"] texture = ExtResource("3_2uj2s") +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_cnef1"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mjmwi"] +bg_color = Color(0.485703, 0.485704, 0.485703, 0.447059) +corner_radius_top_left = 20 +corner_radius_top_right = 20 +corner_radius_bottom_right = 20 +corner_radius_bottom_left = 20 +shadow_size = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_udeaf"] +bg_color = Color(0.117647, 0.117647, 0.117647, 0.682353) +corner_radius_top_left = 20 +corner_radius_top_right = 20 +corner_radius_bottom_right = 20 +corner_radius_bottom_left = 20 +shadow_size = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5yqcp"] +bg_color = Color(1, 1, 1, 0.447059) +corner_radius_top_left = 20 +corner_radius_top_right = 20 +corner_radius_bottom_right = 20 +corner_radius_bottom_left = 20 +shadow_size = 5 + [node name="mapselector" type="Control"] layout_mode = 3 anchors_preset = 15 @@ -101,4 +127,33 @@ layout_mode = 2 size_flags_horizontal = 4 text = "Score: 10 / " +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -8.0 +grow_horizontal = 2 +grow_vertical = 0 +alignment = 1 + +[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 20 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 + +[node name="Button" type="Button" parent="HBoxContainer/MarginContainer"] +custom_minimum_size = Vector2(250, 0) +layout_mode = 2 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_font_sizes/font_size = 30 +theme_override_styles/focus = SubResource("StyleBoxEmpty_cnef1") +theme_override_styles/hover = SubResource("StyleBoxFlat_mjmwi") +theme_override_styles/pressed = SubResource("StyleBoxFlat_udeaf") +theme_override_styles/normal = SubResource("StyleBoxFlat_5yqcp") +text = "Main Menu" + [connection signal="pressed" from="VBoxContainer/HBoxContainer/first/Button" to="." method="_on_button_pressed"] diff --git a/Game/Menu/options.gd b/Game/Menu/options.gd index 762ded2..81b05c8 100644 --- a/Game/Menu/options.gd +++ b/Game/Menu/options.gd @@ -16,6 +16,12 @@ var resolutions = [ @onready var resolution_button: OptionButton = $"TabContainer/Screen & Video/VBoxContainer/HBoxContainer/OptionButton" @onready var display_mode: OptionButton = $"TabContainer/Screen & Video/VBoxContainer/HBoxContainer2/OptionButton" +@onready var master_volume: HSlider = $"TabContainer/Music & Sound/VBoxContainer/HBoxContainer/HSlider" +@onready var music_volume: HSlider = $"TabContainer/Music & Sound/VBoxContainer/HBoxContainer2/HSlider" +@onready var sfx_volume: HSlider = $"TabContainer/Music & Sound/VBoxContainer/HBoxContainer3/HSlider" + + + func _ready(): # Populate resolution selector for res in resolutions: @@ -35,7 +41,8 @@ func _ready(): display_mode.select(0) resolution_button.select(2) resolution_button.disabled = false - + load_settings() + func _on_display_mode_selected(index): var mode_name = display_mode.get_item_text(index) match mode_name: @@ -65,5 +72,50 @@ func _set_screen_size(size: Vector2i): DisplayServer.window_set_size(size) # Optionally center or reposition window if desired +func save_settings(): + var config = ConfigFile.new() + + # Save resolution details + var res = resolutions[resolution_button.selected] + config.set_value("screen", "width", res.x) + config.set_value("screen", "height", res.y) + + # Save display mode + config.set_value("screen", "mode", display_mode.get_selected_id()) # 0=Windowed, 1=Fullscreen, 2=Borderless + + # Save music module volumes + config.set_value("audio", "master_volume", master_volume.value) + config.set_value("audio", "music_volume", music_volume.value) + config.set_value("audio", "sfx_volume", sfx_volume.value) + + var err = config.save("user://settings.cfg") + +func load_settings(): + var config = ConfigFile.new() + var err = config.load("user://settings.cfg") + + if err == OK: + # Load resolution + var width = config.get_value("screen", "width", -1) + var height = config.get_value("screen", "height", -1) + if width != -1 and height != -1: + for i in range(resolutions.size()): + if resolutions[i].x == width and resolutions[i].y == height: + resolution_button.select(i) + break + + # Load display mode and apply it + var mode = config.get_value("screen", "mode", 0) + display_mode.select(mode) + _on_display_mode_selected(mode) # apply display mode and resolution + + # Load audio volumes + master_volume.value = config.get_value("audio", "master_volume", master_volume.value) + music_volume.value = config.get_value("audio", "music_volume", music_volume.value) + sfx_volume.value = config.get_value("audio", "sfx_volume", sfx_volume.value) + else: + print("No previous settings found or failed to load.") + func _on_button_pressed() -> void: + save_settings() get_tree().change_scene_to_file("res://Game/Menu/main.tscn") diff --git a/Game/Menu/options.tscn b/Game/Menu/options.tscn index 15670c8..1afe1de 100644 --- a/Game/Menu/options.tscn +++ b/Game/Menu/options.tscn @@ -86,11 +86,12 @@ offset_bottom = 15.5 grow_horizontal = 2 grow_vertical = 2 tab_alignment = 1 -current_tab = 0 +current_tab = 1 clip_tabs = false tab_focus_mode = 1 [node name="Screen & Video" type="TabBar" parent="TabContainer"] +visible = false layout_mode = 2 metadata/_tab_index = 0 @@ -150,10 +151,84 @@ size_flags_horizontal = 4 size_flags_vertical = 4 [node name="Music & Sound" type="TabBar" parent="TabContainer"] -visible = false layout_mode = 2 metadata/_tab_index = 1 +[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Music & Sound"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -288.5 +offset_top = -20.0 +offset_right = 288.5 +offset_bottom = 20.0 +grow_horizontal = 2 +grow_vertical = 2 +alignment = 1 + +[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Music & Sound/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 + +[node name="Label" type="Label" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Master Volume" + +[node name="VSeparator" type="VSeparator" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = 50 +theme_override_styles/separator = SubResource("StyleBoxEmpty_ed6ki") + +[node name="HSlider" type="HSlider" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer"] +custom_minimum_size = Vector2(150, 0) +layout_mode = 2 +step = 5.0 +value = 100.0 + +[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Music & Sound/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 + +[node name="Label" type="Label" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Music Volume" + +[node name="VSeparator" type="VSeparator" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +theme_override_constants/separation = 50 +theme_override_styles/separator = SubResource("StyleBoxEmpty_ed6ki") + +[node name="HSlider" type="HSlider" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer2"] +custom_minimum_size = Vector2(150, 0) +layout_mode = 2 +step = 5.0 +value = 100.0 + +[node name="HBoxContainer3" type="HBoxContainer" parent="TabContainer/Music & Sound/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 + +[node name="Label" type="Label" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer3"] +layout_mode = 2 +text = "SFX Volume" + +[node name="VSeparator" type="VSeparator" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer3"] +layout_mode = 2 +theme_override_constants/separation = 50 +theme_override_styles/separator = SubResource("StyleBoxEmpty_ed6ki") + +[node name="HSlider" type="HSlider" parent="TabContainer/Music & Sound/VBoxContainer/HBoxContainer3"] +custom_minimum_size = Vector2(150, 0) +layout_mode = 2 +step = 5.0 +value = 100.0 + [node name="HBoxContainer" type="HBoxContainer" parent="."] layout_mode = 1 anchors_preset = 12 diff --git a/Game/music_player.tscn b/Game/music_player.tscn new file mode 100644 index 0000000..5977df0 --- /dev/null +++ b/Game/music_player.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=3 format=3 uid="uid://c5r8h61c73dwv"] + +[ext_resource type="Script" uid="uid://be38xpy62ygps" path="res://music_player.gd" id="1_eumrm"] +[ext_resource type="AudioStream" uid="uid://bktx5fs75wx8g" path="res://Assets/Sounds/main.mp3" id="2_lk0hx"] + +[node name="MusicPlayer" type="Node2D"] +script = ExtResource("1_eumrm") + +[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."] +stream = ExtResource("2_lk0hx") +autoplay = true +parameters/looping = true + +[node name="AudioStreamPlayer2D2" type="AudioStreamPlayer2D" parent="."] diff --git a/music_player.gd b/music_player.gd new file mode 100644 index 0000000..8d2aabf --- /dev/null +++ b/music_player.gd @@ -0,0 +1,29 @@ +extends Node2D + +@onready var music_player: AudioStreamPlayer2D = $AudioStreamPlayer2D +@onready var sfx_player: AudioStreamPlayer2D = $AudioStreamPlayer2D2 + +func _ready() -> void: + load_audio_settings() + +func load_audio_settings() -> void: + var config = ConfigFile.new() + var err = config.load("user://settings.cfg") + if err == OK: + # Get the saved values (expected 0..100 range), default to 100 if missing + var master_volume_raw = config.get_value("audio", "master_volume", 100.0) + var music_volume_raw = config.get_value("audio", "music_volume", 100.0) + var sfx_volume_raw = config.get_value("audio", "sfx_volume", 100.0) + + # Convert from 0..100 range to 0..1 range and clamp + var master_volume = clamp(master_volume_raw / 100.0, 0.0, 1.0) + var music_volume = clamp(music_volume_raw / 100.0, 0.0, 1.0) + var sfx_volume = clamp(sfx_volume_raw / 100.0, 0.0, 1.0) + + music_player.volume_db = linear2db(master_volume * music_volume) + sfx_player.volume_db = linear2db(master_volume * sfx_volume) + +func linear2db(linear: float) -> float: + if linear <= 0.0: + return -80.0 # mute + return 20.0 * (log(linear) / log(10.0)) diff --git a/music_player.gd.uid b/music_player.gd.uid new file mode 100644 index 0000000..e184e03 --- /dev/null +++ b/music_player.gd.uid @@ -0,0 +1 @@ +uid://be38xpy62ygps diff --git a/project.godot b/project.godot index 5e99ea3..29c3d3c 100644 --- a/project.godot +++ b/project.godot @@ -19,9 +19,7 @@ config/icon="res://icon.svg" window/size/initial_position_type=3 window/size/resizable=false -window/stretch/mode="viewport" -window/stretch/aspect="expand" -window/stretch/scale_mode="integer" +window/stretch/mode="canvas_items" [editor_plugins]