From f9c4bd373ac30ead9279d5f7aa4e83931396c22b Mon Sep 17 00:00:00 2001 From: Ruslan Ignatov Date: Sat, 27 Jun 2026 17:31:24 +0300 Subject: [PATCH] Added main menu --- .gitattributes | 3 + default_bus_layout.tres | 21 ++++ fonts/Mx437_DOS-V_re_PRC16.ttf | 3 + fonts/Mx437_DOS-V_re_PRC16.ttf.import | 36 +++++++ fonts/Px437_HP_100LX_8x8.ttf | 3 + fonts/Px437_HP_100LX_8x8.ttf.import | 36 +++++++ game/managers/settings_manager.gd | 150 ++++++++++++++++++++++++++ game/managers/settings_manager.gd.uid | 1 + game/managers/settings_manager.tscn | 6 ++ game/managers/sound_manager.gd | 103 ++++++++++++++++++ game/managers/sound_manager.gd.uid | 1 + game/managers/sound_manager.tscn | 14 +++ game/menu/main_menu.gd | 45 ++++++++ game/menu/main_menu.gd.uid | 1 + game/menu/main_menu.tscn | 60 +++++++++++ game/menu/options_menu.gd | 112 +++++++++++++++++++ game/menu/options_menu.gd.uid | 1 + game/menu/options_menu.tscn | 149 +++++++++++++++++++++++++ game/themes/main_menu.tres | 11 ++ images/pallete/gorge-36-1x.png | 3 + images/pallete/gorge-36-1x.png.import | 40 +++++++ project.godot | 46 ++++++++ sound/ui/accept.wav | 3 + sound/ui/accept.wav.import | 24 +++++ sound/ui/decline.wav | 3 + sound/ui/decline.wav.import | 24 +++++ sound/ui/select.wav | 3 + sound/ui/select.wav.import | 24 +++++ 28 files changed, 926 insertions(+) create mode 100644 .gitattributes create mode 100644 default_bus_layout.tres create mode 100644 fonts/Mx437_DOS-V_re_PRC16.ttf create mode 100644 fonts/Mx437_DOS-V_re_PRC16.ttf.import create mode 100644 fonts/Px437_HP_100LX_8x8.ttf create mode 100644 fonts/Px437_HP_100LX_8x8.ttf.import create mode 100644 game/managers/settings_manager.gd create mode 100644 game/managers/settings_manager.gd.uid create mode 100644 game/managers/settings_manager.tscn create mode 100644 game/managers/sound_manager.gd create mode 100644 game/managers/sound_manager.gd.uid create mode 100644 game/managers/sound_manager.tscn create mode 100644 game/menu/main_menu.gd create mode 100644 game/menu/main_menu.gd.uid create mode 100644 game/menu/main_menu.tscn create mode 100644 game/menu/options_menu.gd create mode 100644 game/menu/options_menu.gd.uid create mode 100644 game/menu/options_menu.tscn create mode 100644 game/themes/main_menu.tres create mode 100644 images/pallete/gorge-36-1x.png create mode 100644 images/pallete/gorge-36-1x.png.import create mode 100644 sound/ui/accept.wav create mode 100644 sound/ui/accept.wav.import create mode 100644 sound/ui/decline.wav create mode 100644 sound/ui/decline.wav.import create mode 100644 sound/ui/select.wav create mode 100644 sound/ui/select.wav.import diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..58d9996 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.png filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.wav filter=lfs diff=lfs merge=lfs -text diff --git a/default_bus_layout.tres b/default_bus_layout.tres new file mode 100644 index 0000000..dd7f71a --- /dev/null +++ b/default_bus_layout.tres @@ -0,0 +1,21 @@ +[gd_resource type="AudioBusLayout" format=3 uid="uid://c2chib4gm7ni4"] + +[resource] +bus/1/name = &"UI" +bus/1/solo = false +bus/1/mute = false +bus/1/bypass_fx = false +bus/1/volume_db = 0.0 +bus/1/send = &"Master" +bus/2/name = &"SFX" +bus/2/solo = false +bus/2/mute = false +bus/2/bypass_fx = false +bus/2/volume_db = 0.0 +bus/2/send = &"Master" +bus/3/name = &"Music" +bus/3/solo = false +bus/3/mute = false +bus/3/bypass_fx = false +bus/3/volume_db = 0.0 +bus/3/send = &"Master" diff --git a/fonts/Mx437_DOS-V_re_PRC16.ttf b/fonts/Mx437_DOS-V_re_PRC16.ttf new file mode 100644 index 0000000..acc7b1f --- /dev/null +++ b/fonts/Mx437_DOS-V_re_PRC16.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a448f1e4137f0a0746f8c05260e71125e98e2ee9fcd9f03edc710964c426ec7 +size 55788 diff --git a/fonts/Mx437_DOS-V_re_PRC16.ttf.import b/fonts/Mx437_DOS-V_re_PRC16.ttf.import new file mode 100644 index 0000000..9036964 --- /dev/null +++ b/fonts/Mx437_DOS-V_re_PRC16.ttf.import @@ -0,0 +1,36 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://cqhh5hrj2rr0y" +path="res://.godot/imported/Mx437_DOS-V_re_PRC16.ttf-b77794ae3eb6d149a620e6a8e0d1ae53.fontdata" + +[deps] + +source_file="res://fonts/Mx437_DOS-V_re_PRC16.ttf" +dest_files=["res://.godot/imported/Mx437_DOS-V_re_PRC16.ttf-b77794ae3eb6d149a620e6a8e0d1ae53.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +modulate_color_glyphs=false +hinting=3 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/fonts/Px437_HP_100LX_8x8.ttf b/fonts/Px437_HP_100LX_8x8.ttf new file mode 100644 index 0000000..d930004 --- /dev/null +++ b/fonts/Px437_HP_100LX_8x8.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28763ee53f2059513e2539f23459e0153f93cd9b5bc50d4ebec9de2efee106fc +size 24808 diff --git a/fonts/Px437_HP_100LX_8x8.ttf.import b/fonts/Px437_HP_100LX_8x8.ttf.import new file mode 100644 index 0000000..29a2991 --- /dev/null +++ b/fonts/Px437_HP_100LX_8x8.ttf.import @@ -0,0 +1,36 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://bslwwl3rn7mt2" +path="res://.godot/imported/Px437_HP_100LX_8x8.ttf-bab2ed6812e5074ea39b94f160792001.fontdata" + +[deps] + +source_file="res://fonts/Px437_HP_100LX_8x8.ttf" +dest_files=["res://.godot/imported/Px437_HP_100LX_8x8.ttf-bab2ed6812e5074ea39b94f160792001.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +modulate_color_glyphs=false +hinting=3 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/game/managers/settings_manager.gd b/game/managers/settings_manager.gd new file mode 100644 index 0000000..9775317 --- /dev/null +++ b/game/managers/settings_manager.gd @@ -0,0 +1,150 @@ +class_name CSettingsManager +extends Node + + +@export var config_file_path := "user://settings.cfg" +@export var window_base_size := Vector2i(640, 360) + + +const CATEGORY_VIDEO = "video" +const SETTING_FULLSCREEN = "fullscreen" +const SETTING_WINDOW_FACTOR = "window_factor" +const CATEGORY_AUDIO = "audio" +const SETTING_MASTER_VOLUME = "master_volume" +const SETTING_UI_VOLUME = "ui_volume" +const SETTING_SFX_VOLUME = "sfx_volume" +const SETTING_MUSIC_VOLUME = "music_volume" + + +var _config: ConfigFile + +var _fullscreen := false +var fullscreen : bool: + get(): + return _fullscreen + set(value): + _fullscreen = value + _apply_video_settings() + _save_settings() + +var _window_factor := 1 +var window_factor : int: + get(): + return _window_factor + set(value): + _window_factor = clampi(value, 1, 5) + _apply_video_settings() + _save_settings() + +var _master_volume := 100 +var master_volume : int: + get(): + return _master_volume + set(value): + _master_volume = clampi(value, 0, 100) + _apply_audio_settings() + _save_settings() + +var _ui_volume := 100 +var ui_volume : int: + get(): + return _ui_volume + set(value): + _ui_volume = clampi(value, 0, 100) + _apply_audio_settings() + _save_settings() + +var _sfx_volume := 100 +var sfx_volume : int: + get(): + return _sfx_volume + set(value): + _sfx_volume = clampi(value, 0, 100) + _apply_audio_settings() + _save_settings() + +var _music_volume := 50 +var music_volume : int: + get(): + return _music_volume + set(value): + _music_volume = clampi(value, 0, 100) + _apply_audio_settings() + _save_settings() + + +func _ready() -> void: + _config = ConfigFile.new() + + _load_settings() + _apply_all_settings() + + +func _load_settings() -> void: + if _config.load(config_file_path) == OK: + _fullscreen = _config.get_value(CATEGORY_VIDEO, SETTING_FULLSCREEN, _fullscreen) + _window_factor = _config.get_value(CATEGORY_VIDEO, SETTING_WINDOW_FACTOR, _window_factor) + + _master_volume = _config.get_value(CATEGORY_AUDIO, SETTING_MASTER_VOLUME, _master_volume) + _ui_volume = _config.get_value(CATEGORY_AUDIO, SETTING_UI_VOLUME, _ui_volume) + _sfx_volume = _config.get_value(CATEGORY_AUDIO, SETTING_SFX_VOLUME, _sfx_volume) + _music_volume = _config.get_value(CATEGORY_AUDIO, SETTING_MUSIC_VOLUME, _music_volume) + + _save_settings() + + +func _save_settings() -> void: + if _config == null: + _config = ConfigFile.new() + + _config.set_value(CATEGORY_VIDEO, SETTING_FULLSCREEN, _fullscreen) + _config.set_value(CATEGORY_VIDEO, SETTING_WINDOW_FACTOR, _window_factor) + + _config.set_value(CATEGORY_AUDIO, SETTING_MASTER_VOLUME, _master_volume) + _config.set_value(CATEGORY_AUDIO, SETTING_UI_VOLUME, _ui_volume) + _config.set_value(CATEGORY_AUDIO, SETTING_SFX_VOLUME, _sfx_volume) + _config.set_value(CATEGORY_AUDIO, SETTING_MUSIC_VOLUME, _music_volume) + + _config.save(config_file_path) + + +func _apply_all_settings() -> void: + _apply_video_settings() + _apply_audio_settings() + + +func _apply_video_settings() -> void: + if OS.get_name() == "Web": return + + if _fullscreen: + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) + else: + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) + _apply_window_scale() + + +func _apply_audio_settings() -> void: + var master_bus := AudioServer.get_bus_index(CSoundManager.MASTER_BUS) + var ui_bus := AudioServer.get_bus_index(CSoundManager.UI_BUS) + var sfx_bus := AudioServer.get_bus_index(CSoundManager.SFX_BUS) + var music_bus := AudioServer.get_bus_index(CSoundManager.MUSIC_BUS) + + AudioServer.set_bus_volume_linear(master_bus, _master_volume/100.0) + AudioServer.set_bus_volume_linear(ui_bus, _ui_volume/100.0) + AudioServer.set_bus_volume_linear(sfx_bus, _sfx_volume/100.0) + AudioServer.set_bus_volume_linear(music_bus, _music_volume/100.0) + + +func _apply_window_scale() -> void: + if _fullscreen: return + + var new_size := window_base_size * _window_factor + + var current_position := DisplayServer.window_get_position() + var current_size := DisplayServer.window_get_size() + + var current_center := current_position + Vector2i(current_size / 2.0) + var new_position := current_center - Vector2i(new_size / 2.0) + + DisplayServer.window_set_size(new_size) + DisplayServer.window_set_position(new_position) diff --git a/game/managers/settings_manager.gd.uid b/game/managers/settings_manager.gd.uid new file mode 100644 index 0000000..48809a4 --- /dev/null +++ b/game/managers/settings_manager.gd.uid @@ -0,0 +1 @@ +uid://bygmkd5m8mfxn diff --git a/game/managers/settings_manager.tscn b/game/managers/settings_manager.tscn new file mode 100644 index 0000000..6b82dc8 --- /dev/null +++ b/game/managers/settings_manager.tscn @@ -0,0 +1,6 @@ +[gd_scene format=3 uid="uid://cuyv26utj07j4"] + +[ext_resource type="Script" uid="uid://bygmkd5m8mfxn" path="res://game/managers/settings_manager.gd" id="1_4nipk"] + +[node name="SettingsManager" type="Node" unique_id=261462227] +script = ExtResource("1_4nipk") diff --git a/game/managers/sound_manager.gd b/game/managers/sound_manager.gd new file mode 100644 index 0000000..e5b6912 --- /dev/null +++ b/game/managers/sound_manager.gd @@ -0,0 +1,103 @@ +class_name CSoundManager +extends Node + + +const MASTER_BUS = "Master" +const UI_BUS = "UI" +const SFX_BUS = "SFX" +const MUSIC_BUS = "Music" + + +@export_group("Pitch settings", "pitch") +@export_range(0.9, 1.1, 0.01) var putch_ui_min := 1.0 +@export_range(0.9, 1.1, 0.01) var putch_ui_max := 1.0 +@export_range(0.9, 1.1, 0.01) var putch_sfx_min := 1.0 +@export_range(0.9, 1.1, 0.01) var putch_sfx_max := 1.0 + +@export_group("Number of players", "player_count") +@export_range(1, 10) var player_count_ui := 1 +@export_range(1, 100) var player_count_sfx := 1 + +@export_group("UI Streams", "ui_stream") +@export var ui_stream_accept : AudioStream +@export var ui_stream_decline : AudioStream +@export var ui_stream_select : AudioStream + +@export_group("SFX Streams", "sfx_stream") + + +@export_group("Music Streams", "music_stream") + + + +var _ui_players : Array[AudioStreamPlayer] = [] +var _sfx_players : Array[AudioStreamPlayer2D] = [] +var _music_player : AudioStreamPlayer + + +func _ready() -> void: + _create_ui_players() + _create_sfx_players() + _create_music_player() + + +func play_ui_stream(stream: AudioStream) -> AudioStreamPlayer: + var player := _get_free_player(_ui_players) + player.stream = stream + player.pitch_scale = randf_range(putch_ui_min, putch_ui_max) + player.play() + return player + + +func play_sfx_stream(stream: AudioStream, position: Vector2) -> AudioStreamPlayer2D: + var player := _get_free_2d_player(_sfx_players) + player.stream = stream + player.pitch_scale = randf_range(putch_ui_min, putch_ui_max) + player.position = position + player.play() + return player + + +func play_music_stream(stream: AudioStream) -> AudioStreamPlayer: + if _music_player.stream == stream: return + + _music_player.stream = stream + _music_player.play() + return _music_player + + +func _create_ui_players() -> void: + for i in range(player_count_ui): + var player : AudioStreamPlayer = AudioStreamPlayer.new() + player.bus = UI_BUS + _ui_players.append(player) + add_child(player) + + +func _create_sfx_players() -> void: + for i in range(player_count_sfx): + var player : AudioStreamPlayer2D = AudioStreamPlayer2D.new() + player.bus = SFX_BUS + _sfx_players.append(player) + add_child(player) + + +func _create_music_player() -> void: + var player : AudioStreamPlayer = AudioStreamPlayer.new() + player.bus = MUSIC_BUS + _music_player = player + add_child(player) + + +func _get_free_player(players: Array[AudioStreamPlayer]) -> AudioStreamPlayer: + for player in players: + if not player.playing: + return player + return players[0] + + +func _get_free_2d_player(players: Array[AudioStreamPlayer2D]) -> AudioStreamPlayer2D: + for player in players: + if not player.playing: + return player + return players[0] diff --git a/game/managers/sound_manager.gd.uid b/game/managers/sound_manager.gd.uid new file mode 100644 index 0000000..d5a29a5 --- /dev/null +++ b/game/managers/sound_manager.gd.uid @@ -0,0 +1 @@ +uid://dh2awtco3curi diff --git a/game/managers/sound_manager.tscn b/game/managers/sound_manager.tscn new file mode 100644 index 0000000..c88521d --- /dev/null +++ b/game/managers/sound_manager.tscn @@ -0,0 +1,14 @@ +[gd_scene format=3 uid="uid://b5wqc1hgwcdm4"] + +[ext_resource type="Script" uid="uid://dh2awtco3curi" path="res://game/managers/sound_manager.gd" id="1_cg0sy"] +[ext_resource type="AudioStream" uid="uid://cwmibbhy2fpq2" path="res://sound/ui/accept.wav" id="2_ge1il"] +[ext_resource type="AudioStream" uid="uid://d2tsomsqmhf0h" path="res://sound/ui/decline.wav" id="3_agyxs"] +[ext_resource type="AudioStream" uid="uid://cfb2adf5hft7b" path="res://sound/ui/select.wav" id="4_0i6kl"] + +[node name="SoundManager" type="Node" unique_id=1576371552] +script = ExtResource("1_cg0sy") +player_count_ui = 8 +player_count_sfx = 32 +ui_stream_accept = ExtResource("2_ge1il") +ui_stream_decline = ExtResource("3_agyxs") +ui_stream_select = ExtResource("4_0i6kl") diff --git a/game/menu/main_menu.gd b/game/menu/main_menu.gd new file mode 100644 index 0000000..c3c8d39 --- /dev/null +++ b/game/menu/main_menu.gd @@ -0,0 +1,45 @@ +class_name MainMenu +extends Control + + +@onready var start_button : Button = $%StartButton +@onready var options_button : Button = $%OptionsButton +@onready var quit_button : Button = $%QuitButton + + +func _ready() -> void: + if OS.get_name() == "Web": + _setup_for_web() + + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + + #TODO Add menu music + + start_button.grab_focus() + get_viewport().gui_focus_changed.connect(_on_gui_focus_changed) + + +func _setup_for_web() -> void: + quit_button.hide() + start_button.focus_neighbor_top = options_button.get_path() + options_button.focus_neighbor_bottom = start_button.get_path() + + +func _on_gui_focus_changed(_node: Control) -> void: + SoundManager.play_ui_stream(SoundManager.ui_stream_select) + + +func _on_start_button_pressed() -> void: + SoundManager.play_ui_stream(SoundManager.ui_stream_accept) + #TODO transition to level selection + + +func _on_options_button_pressed() -> void: + SoundManager.play_ui_stream(SoundManager.ui_stream_accept) + get_tree().change_scene_to_file("res://game/menu/options_menu.tscn") + + +func _on_quit_button_pressed() -> void: + var stream_player := SoundManager.play_ui_stream(SoundManager.ui_stream_decline) + await stream_player.finished + get_tree().quit() diff --git a/game/menu/main_menu.gd.uid b/game/menu/main_menu.gd.uid new file mode 100644 index 0000000..0a19f27 --- /dev/null +++ b/game/menu/main_menu.gd.uid @@ -0,0 +1 @@ +uid://daw3vlybwcj5l diff --git a/game/menu/main_menu.tscn b/game/menu/main_menu.tscn new file mode 100644 index 0000000..4f08315 --- /dev/null +++ b/game/menu/main_menu.tscn @@ -0,0 +1,60 @@ +[gd_scene format=3 uid="uid://cl0h2acqcq5wq"] + +[ext_resource type="Theme" uid="uid://bqj884yfvhhft" path="res://game/themes/main_menu.tres" id="1_5d27k"] +[ext_resource type="Script" uid="uid://daw3vlybwcj5l" path="res://game/menu/main_menu.gd" id="2_qnvmd"] +[ext_resource type="FontFile" uid="uid://bslwwl3rn7mt2" path="res://fonts/Px437_HP_100LX_8x8.ttf" id="3_i4f54"] + +[node name="MainMenu" type="Control" unique_id=569032006] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_5d27k") +script = ExtResource("2_qnvmd") + +[node name="MarginContainer" type="MarginContainer" parent="." unique_id=1180781679] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer" unique_id=736037128] +layout_mode = 2 +size_flags_horizontal = 4 +alignment = 1 + +[node name="StartButton" type="Button" parent="MarginContainer/VBoxContainer" unique_id=1504018605] +unique_name_in_owner = true +layout_mode = 2 +focus_neighbor_top = NodePath("../QuitButton") +text = "START" + +[node name="OptionsButton" type="Button" parent="MarginContainer/VBoxContainer" unique_id=1073262524] +unique_name_in_owner = true +layout_mode = 2 +text = "OPTIONS" + +[node name="QuitButton" type="Button" parent="MarginContainer/VBoxContainer" unique_id=1029660410] +unique_name_in_owner = true +layout_mode = 2 +focus_neighbor_bottom = NodePath("../StartButton") +text = "QUIT" + +[node name="CopyrightLabel" type="Label" parent="MarginContainer" unique_id=2068603030] +layout_mode = 2 +size_flags_vertical = 1 +theme_override_fonts/font = ExtResource("3_i4f54") +theme_override_font_sizes/font_size = 8 +text = "v 1.0.0 +(c) Ruslan Ignatov 2026 +Powered by Godot Engine" +horizontal_alignment = 2 +vertical_alignment = 2 + +[connection signal="pressed" from="MarginContainer/VBoxContainer/StartButton" to="." method="_on_start_button_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/OptionsButton" to="." method="_on_options_button_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"] diff --git a/game/menu/options_menu.gd b/game/menu/options_menu.gd new file mode 100644 index 0000000..08495fc --- /dev/null +++ b/game/menu/options_menu.gd @@ -0,0 +1,112 @@ +class_name OptionsMenu +extends Control + + +const WINDOW_FACTOR = "window_factor" + + +var _play_sound := false + + +@onready var fullscreen_button : CheckButton = $%FullscreenCheckButton +@onready var window_factor_buttons : HBoxContainer = $%WindowFactorContainer +@onready var back_button : Button = $%BackButton +@onready var master_slider : Slider = $%MasterSlider +@onready var ui_slider : Slider = $%UISlider +@onready var sfx_slider : Slider = $%SFXSlider +@onready var music_slider : Slider = $%MusicSlider + + +func _ready() -> void: + _load_current_settings() + _connect_window_factor_buttons() + + fullscreen_button.grab_focus() + + if OS.get_name() == "Web": + _setup_for_web() + master_slider.grab_focus() + + _play_sound = true + get_viewport().gui_focus_changed.connect(_on_gui_focus_changed) + + +func _setup_for_web() -> void: + $%FullscreenLabel.hide() + $%WindowFactorLabel.hide() + fullscreen_button.hide() + window_factor_buttons.hide() + master_slider.focus_neighbor_top = back_button.get_path() + back_button.focus_neighbor_bottom = master_slider.get_path() + + +func _connect_window_factor_buttons() -> void: + for child in window_factor_buttons.get_children(): + if child is Button: + var button : Button = child + button.pressed.connect(_on_window_factor_button_pressed.bind(button)) + + +func _load_current_settings() -> void: + fullscreen_button.button_pressed = SettingsManager.fullscreen + for child in window_factor_buttons.get_children(): + if child is Button: + var button : Button = child + var window_factor : int = button.get_meta(WINDOW_FACTOR, 0) + if window_factor == SettingsManager.window_factor: + button.button_pressed = true + _update_window_factor_disabled() + + master_slider.value = SettingsManager.master_volume + ui_slider.value = SettingsManager.ui_volume + sfx_slider.value = SettingsManager.sfx_volume + music_slider.value = SettingsManager.music_volume + + +func _update_window_factor_disabled() -> void: + for child in window_factor_buttons.get_children(): + if not child is Button: continue + child.disabled = SettingsManager.fullscreen + child.focus_mode = Control.FOCUS_NONE if SettingsManager.fullscreen else Control.FOCUS_ALL + + +func _on_gui_focus_changed(_node: Control) -> void: + SoundManager.play_ui_stream(SoundManager.ui_stream_select) + + +func _on_fullscreen_check_button_toggled(toggled: bool) -> void: + if _play_sound: SoundManager.play_ui_stream(SoundManager.ui_stream_accept) + SettingsManager.fullscreen = toggled + _update_window_factor_disabled() + + +func _on_back_button_pressed() -> void: + if _play_sound: SoundManager.play_ui_stream(SoundManager.ui_stream_decline) + get_tree().change_scene_to_file("res://game/menu/main_menu.tscn") + + +func _on_window_factor_button_pressed(button: Button) -> void: + if _play_sound: SoundManager.play_ui_stream(SoundManager.ui_stream_accept) + var window_factor : int = button.get_meta(WINDOW_FACTOR, 0) + if window_factor > 0: + SettingsManager.window_factor = window_factor + + +func _on_master_volume_changed(value: float) -> void: + if _play_sound: SoundManager.play_ui_stream(SoundManager.ui_stream_select) + SettingsManager.master_volume = floor(value) + + +func _on_ui_volume_changed(value: float) -> void: + if _play_sound: SoundManager.play_ui_stream(SoundManager.ui_stream_select) + SettingsManager.ui_volume = floor(value) + + +func _on_sfx_volume_changed(value: float) -> void: + var screen_center := SettingsManager.window_base_size/2.0 + if _play_sound: SoundManager.play_sfx_stream(SoundManager.ui_stream_select, screen_center) + SettingsManager.sfx_volume = floor(value) + + +func _on_music_volume_changed(value: float) -> void: + SettingsManager.music_volume = floor(value) diff --git a/game/menu/options_menu.gd.uid b/game/menu/options_menu.gd.uid new file mode 100644 index 0000000..30d26a3 --- /dev/null +++ b/game/menu/options_menu.gd.uid @@ -0,0 +1 @@ +uid://c6qaxjgpf8ydx diff --git a/game/menu/options_menu.tscn b/game/menu/options_menu.tscn new file mode 100644 index 0000000..f9880c0 --- /dev/null +++ b/game/menu/options_menu.tscn @@ -0,0 +1,149 @@ +[gd_scene format=3 uid="uid://dnxfvop505syi"] + +[ext_resource type="Theme" uid="uid://bqj884yfvhhft" path="res://game/themes/main_menu.tres" id="1_e2bp2"] +[ext_resource type="Script" uid="uid://c6qaxjgpf8ydx" path="res://game/menu/options_menu.gd" id="1_lq2ks"] + +[sub_resource type="InputEventAction" id="InputEventAction_j72d6"] +action = &"ui_cancel" + +[sub_resource type="Shortcut" id="Shortcut_e2bp2"] +events = [SubResource("InputEventAction_j72d6")] + +[node name="OptionsMenu" type="Control" unique_id=1463826396] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_e2bp2") +script = ExtResource("1_lq2ks") + +[node name="MarginContainer" type="MarginContainer" parent="." unique_id=2127037660] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer" unique_id=1647231354] +layout_mode = 2 +alignment = 1 + +[node name="GridContainer" type="GridContainer" parent="MarginContainer/VBoxContainer" unique_id=1356622174] +layout_mode = 2 +size_flags_horizontal = 4 +columns = 2 + +[node name="FullscreenLabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=1820060227] +unique_name_in_owner = true +layout_mode = 2 + +[node name="FullscreenCheckButton" type="CheckButton" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=129623184] +unique_name_in_owner = true +layout_mode = 2 +text = "FULLSCREEN" + +[node name="WindowFactorLabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=1054219556] +unique_name_in_owner = true +layout_mode = 2 + +[node name="WindowFactorContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=2006592987] +unique_name_in_owner = true +layout_mode = 2 + +[node name="ButtonX1" type="Button" parent="MarginContainer/VBoxContainer/GridContainer/WindowFactorContainer" unique_id=978982542] +layout_mode = 2 +toggle_mode = true +text = "X1" +metadata/window_factor = 1 + +[node name="ButtonX2" type="Button" parent="MarginContainer/VBoxContainer/GridContainer/WindowFactorContainer" unique_id=422646167] +layout_mode = 2 +toggle_mode = true +text = "X2" +metadata/window_factor = 2 + +[node name="ButtonX3" type="Button" parent="MarginContainer/VBoxContainer/GridContainer/WindowFactorContainer" unique_id=317316950] +layout_mode = 2 +toggle_mode = true +text = "X3" +metadata/window_factor = 3 + +[node name="ButtonX4" type="Button" parent="MarginContainer/VBoxContainer/GridContainer/WindowFactorContainer" unique_id=1096197974] +layout_mode = 2 +toggle_mode = true +text = "X4" +metadata/window_factor = 4 + +[node name="ButtonX5" type="Button" parent="MarginContainer/VBoxContainer/GridContainer/WindowFactorContainer" unique_id=1598256151] +layout_mode = 2 +toggle_mode = true +text = "X5" +metadata/window_factor = 5 + +[node name="MasterLabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=1502062154] +layout_mode = 2 +text = "MASTER" + +[node name="MasterSlider" type="HSlider" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=1600615574] +unique_name_in_owner = true +layout_mode = 2 +step = 10.0 +tick_count = 11 +ticks_on_borders = true +ticks_position = 2 + +[node name="UILabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=1039303416] +layout_mode = 2 +text = "UI" + +[node name="UISlider" type="HSlider" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=2094741924] +unique_name_in_owner = true +layout_mode = 2 +step = 10.0 +tick_count = 11 +ticks_on_borders = true +ticks_position = 2 + +[node name="SFXLabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=122025284] +layout_mode = 2 +text = "SFX" + +[node name="SFXSlider" type="HSlider" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=630139889] +unique_name_in_owner = true +layout_mode = 2 +step = 10.0 +tick_count = 11 +ticks_on_borders = true +ticks_position = 2 + +[node name="MusicLabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=2133353313] +layout_mode = 2 +text = "MUSIC" + +[node name="MusicSlider" type="HSlider" parent="MarginContainer/VBoxContainer/GridContainer" unique_id=537100873] +unique_name_in_owner = true +layout_mode = 2 +step = 10.0 +tick_count = 11 +ticks_on_borders = true +ticks_position = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer" unique_id=676353768] +layout_mode = 2 +alignment = 1 + +[node name="BackButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer" unique_id=131108983] +unique_name_in_owner = true +layout_mode = 2 +shortcut = SubResource("Shortcut_e2bp2") +text = "BACK" + +[connection signal="toggled" from="MarginContainer/VBoxContainer/GridContainer/FullscreenCheckButton" to="." method="_on_fullscreen_check_button_toggled"] +[connection signal="value_changed" from="MarginContainer/VBoxContainer/GridContainer/MasterSlider" to="." method="_on_master_volume_changed"] +[connection signal="value_changed" from="MarginContainer/VBoxContainer/GridContainer/UISlider" to="." method="_on_ui_volume_changed"] +[connection signal="value_changed" from="MarginContainer/VBoxContainer/GridContainer/SFXSlider" to="." method="_on_sfx_volume_changed"] +[connection signal="value_changed" from="MarginContainer/VBoxContainer/GridContainer/MusicSlider" to="." method="_on_music_volume_changed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer/BackButton" to="." method="_on_back_button_pressed"] diff --git a/game/themes/main_menu.tres b/game/themes/main_menu.tres new file mode 100644 index 0000000..28874d2 --- /dev/null +++ b/game/themes/main_menu.tres @@ -0,0 +1,11 @@ +[gd_resource type="Theme" format=3 uid="uid://bqj884yfvhhft"] + +[ext_resource type="FontFile" uid="uid://cqhh5hrj2rr0y" path="res://fonts/Mx437_DOS-V_re_PRC16.ttf" id="1_sfg7l"] + +[resource] +default_font = ExtResource("1_sfg7l") +default_font_size = 32 +MarginContainer/constants/margin_bottom = 25 +MarginContainer/constants/margin_left = 25 +MarginContainer/constants/margin_right = 25 +MarginContainer/constants/margin_top = 25 diff --git a/images/pallete/gorge-36-1x.png b/images/pallete/gorge-36-1x.png new file mode 100644 index 0000000..eb56cdb --- /dev/null +++ b/images/pallete/gorge-36-1x.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:325708b58b2da890168d404b740140379118e03ec73e85fcbff7a4ae5c13f326 +size 207 diff --git a/images/pallete/gorge-36-1x.png.import b/images/pallete/gorge-36-1x.png.import new file mode 100644 index 0000000..f363ce5 --- /dev/null +++ b/images/pallete/gorge-36-1x.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://tr0ywkr45j7v" +path="res://.godot/imported/gorge-36-1x.png-3427ba7b879d6ced961444e5cfa104c6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/pallete/gorge-36-1x.png" +dest_files=["res://.godot/imported/gorge-36-1x.png-3427ba7b879d6ced961444e5cfa104c6.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 diff --git a/project.godot b/project.godot index 6567c7d..1138ad5 100644 --- a/project.godot +++ b/project.godot @@ -11,9 +11,19 @@ config_version=5 [application] config/name="NeonCollapse" +run/main_scene="uid://cl0h2acqcq5wq" config/features=PackedStringArray("4.7", "GL Compatibility") config/icon="res://icon.svg" +[audio] + +buses/default_bus_layout="uid://c2chib4gm7ni4" + +[autoload] + +SoundManager="*uid://b5wqc1hgwcdm4" +SettingsManager="*uid://cuyv26utj07j4" + [debug] gdscript/warnings/untyped_declaration=1 @@ -26,12 +36,48 @@ window/size/resizable=false window/stretch/mode="viewport" window/stretch/scale_mode="integer" +[input] + +ui_left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":13,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +ui_right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":14,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} +ui_up={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":11,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +ui_down={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":12,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} + [physics] 3d/physics_engine="Jolt Physics" [rendering] +textures/canvas_textures/default_texture_filter=0 rendering_device/driver.windows="d3d12" renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" diff --git a/sound/ui/accept.wav b/sound/ui/accept.wav new file mode 100644 index 0000000..0778490 --- /dev/null +++ b/sound/ui/accept.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3456e94ac78155dc7bd563abd6ed20a1332ee0a40094f3b8585c0d1a4a8b073 +size 19064 diff --git a/sound/ui/accept.wav.import b/sound/ui/accept.wav.import new file mode 100644 index 0000000..4b3066d --- /dev/null +++ b/sound/ui/accept.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cwmibbhy2fpq2" +path="res://.godot/imported/accept.wav-725025bdb42b4b7611a06b20128154fe.sample" + +[deps] + +source_file="res://sound/ui/accept.wav" +dest_files=["res://.godot/imported/accept.wav-725025bdb42b4b7611a06b20128154fe.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/sound/ui/decline.wav b/sound/ui/decline.wav new file mode 100644 index 0000000..db0e648 --- /dev/null +++ b/sound/ui/decline.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87a95aea33707cdb4b8505b721915099dee3f4b52276ae827ea2de2567accaef +size 19064 diff --git a/sound/ui/decline.wav.import b/sound/ui/decline.wav.import new file mode 100644 index 0000000..e693928 --- /dev/null +++ b/sound/ui/decline.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://d2tsomsqmhf0h" +path="res://.godot/imported/decline.wav-0c35c7fd479f3e84c9e549f385ac9a98.sample" + +[deps] + +source_file="res://sound/ui/decline.wav" +dest_files=["res://.godot/imported/decline.wav-0c35c7fd479f3e84c9e549f385ac9a98.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/sound/ui/select.wav b/sound/ui/select.wav new file mode 100644 index 0000000..9b0850c --- /dev/null +++ b/sound/ui/select.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef40b0cd81c61cc578e4bf42862cb178404415b906733ad478d328e89341ff40 +size 5882 diff --git a/sound/ui/select.wav.import b/sound/ui/select.wav.import new file mode 100644 index 0000000..4c8ca78 --- /dev/null +++ b/sound/ui/select.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cfb2adf5hft7b" +path="res://.godot/imported/select.wav-006fb2e1590ec1d0308080a407514ee4.sample" + +[deps] + +source_file="res://sound/ui/select.wav" +dest_files=["res://.godot/imported/select.wav-006fb2e1590ec1d0308080a407514ee4.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2