Persist title audio settings

This commit is contained in:
2026-06-19 23:14:24 +09:00
parent ab3f0a1124
commit 3615b64196
4 changed files with 209 additions and 6 deletions

View File

@@ -26,6 +26,8 @@ const THREAT_OVERLAY_COLOR := Color(0.76, 0.060, 0.035, 0.20)
const THREAT_BORDER_COLOR := Color(0.86, 0.18, 0.10, 0.48)
const BGM_MENU_PATH := "res://audio/bgm/menu_theme_placeholder.wav"
const BGM_BATTLE_PATH := "res://audio/bgm/battle_loop_placeholder.wav"
const SETTINGS_PATH := "user://heros_settings.json"
const SETTINGS_SAVE_VERSION := 1
const SFX_BOW_RELEASE_PATH := "res://audio/sfx/bow_release_01.wav"
const SFX_DEFEAT_STING_PATH := "res://audio/sfx/defeat_sting_01.wav"
const SFX_FIRE_SKILL_PATH := "res://audio/sfx/fire_skill_01.wav"
@@ -44,6 +46,7 @@ const UI_FONT_BOLD_PATH := "res://art/ui/fonts/GowunBatang-Bold.ttf"
const BGM_VOLUME_DB := -14.0
const SFX_VOLUME_DB := -4.0
const UI_SFX_VOLUME_DB := -8.0
const AUDIO_MUTED_DB := -80.0
const FLOATING_TEXT_LIFETIME := 1.0
const FLOATING_TEXT_RISE := 42.0
const OBJECTIVE_NOTICE_DURATION := 2.6
@@ -471,11 +474,17 @@ var title_settings_panel: PanelContainer
var title_bgm_toggle: CheckButton
var title_sfx_toggle: CheckButton
var title_edge_scroll_toggle: CheckButton
var title_bgm_volume_slider: HSlider
var title_sfx_volume_slider: HSlider
var title_bgm_volume_value_label: Label
var title_sfx_volume_value_label: Label
var title_settings_back_button: Button
var title_screen_visible := false
var title_bgm_enabled := true
var title_sfx_enabled := true
var title_edge_scroll_enabled := true
var title_bgm_volume_percent := 100
var title_sfx_volume_percent := 100
var log_box: RichTextLabel
var dialogue_queue: Array = []
var active_dialogue_lines: Array = []
@@ -504,6 +513,7 @@ var unit_idle_time := 0.0
func _ready() -> void:
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
_load_title_settings()
_create_hud()
_create_audio()
state.changed.connect(_on_state_changed)
@@ -3069,7 +3079,7 @@ func _create_hud() -> void:
title_settings_panel = PanelContainer.new()
title_settings_panel.visible = false
title_settings_panel.custom_minimum_size = Vector2(432, 134)
title_settings_panel.custom_minimum_size = Vector2(432, 236)
_apply_panel_style(title_settings_panel, "hud_info")
title_menu_column.add_child(title_settings_panel)
@@ -3077,22 +3087,93 @@ func _create_hud() -> void:
title_settings_column.add_theme_constant_override("separation", 6)
title_settings_panel.add_child(title_settings_column)
var title_settings_caption := Label.new()
title_settings_caption.text = "환경 설정"
title_settings_caption.custom_minimum_size = Vector2(392, 24)
title_settings_caption.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
title_settings_caption.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_apply_label_style(title_settings_caption, UI_OLD_BRONZE, 15)
title_settings_column.add_child(title_settings_caption)
title_bgm_toggle = CheckButton.new()
title_bgm_toggle.text = "배경음"
title_bgm_toggle.custom_minimum_size = Vector2(392, 30)
title_bgm_toggle.button_pressed = title_bgm_enabled
title_bgm_toggle.tooltip_text = "배경 음악을 켜거나 끕니다."
title_bgm_toggle.toggled.connect(_on_title_bgm_toggled)
title_settings_column.add_child(title_bgm_toggle)
var title_bgm_volume_row := HBoxContainer.new()
title_bgm_volume_row.custom_minimum_size = Vector2(392, 34)
title_bgm_volume_row.add_theme_constant_override("separation", 8)
title_settings_column.add_child(title_bgm_volume_row)
var title_bgm_volume_caption := Label.new()
title_bgm_volume_caption.text = "배경음 크기"
title_bgm_volume_caption.custom_minimum_size = Vector2(94, 30)
title_bgm_volume_caption.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_apply_label_style(title_bgm_volume_caption, UI_PARCHMENT_TEXT, 13)
title_bgm_volume_row.add_child(title_bgm_volume_caption)
title_bgm_volume_slider = HSlider.new()
title_bgm_volume_slider.min_value = 0.0
title_bgm_volume_slider.max_value = 100.0
title_bgm_volume_slider.step = 5.0
title_bgm_volume_slider.value = float(title_bgm_volume_percent)
title_bgm_volume_slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL
title_bgm_volume_slider.custom_minimum_size = Vector2(216, 30)
title_bgm_volume_slider.tooltip_text = "배경 음악의 크기를 조절합니다."
title_bgm_volume_slider.value_changed.connect(_on_title_bgm_volume_changed)
title_bgm_volume_row.add_child(title_bgm_volume_slider)
title_bgm_volume_value_label = Label.new()
title_bgm_volume_value_label.custom_minimum_size = Vector2(48, 30)
title_bgm_volume_value_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
title_bgm_volume_value_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_apply_label_style(title_bgm_volume_value_label, UI_PARCHMENT_TEXT, 13)
title_bgm_volume_row.add_child(title_bgm_volume_value_label)
title_sfx_toggle = CheckButton.new()
title_sfx_toggle.text = "효과음"
title_sfx_toggle.custom_minimum_size = Vector2(392, 30)
title_sfx_toggle.button_pressed = title_sfx_enabled
title_sfx_toggle.tooltip_text = "버튼과 전투 효과음을 켜거나 끕니다."
title_sfx_toggle.toggled.connect(_on_title_sfx_toggled)
title_settings_column.add_child(title_sfx_toggle)
var title_sfx_volume_row := HBoxContainer.new()
title_sfx_volume_row.custom_minimum_size = Vector2(392, 34)
title_sfx_volume_row.add_theme_constant_override("separation", 8)
title_settings_column.add_child(title_sfx_volume_row)
var title_sfx_volume_caption := Label.new()
title_sfx_volume_caption.text = "효과음 크기"
title_sfx_volume_caption.custom_minimum_size = Vector2(94, 30)
title_sfx_volume_caption.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_apply_label_style(title_sfx_volume_caption, UI_PARCHMENT_TEXT, 13)
title_sfx_volume_row.add_child(title_sfx_volume_caption)
title_sfx_volume_slider = HSlider.new()
title_sfx_volume_slider.min_value = 0.0
title_sfx_volume_slider.max_value = 100.0
title_sfx_volume_slider.step = 5.0
title_sfx_volume_slider.value = float(title_sfx_volume_percent)
title_sfx_volume_slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL
title_sfx_volume_slider.custom_minimum_size = Vector2(216, 30)
title_sfx_volume_slider.tooltip_text = "버튼과 전투 효과음의 크기를 조절합니다."
title_sfx_volume_slider.value_changed.connect(_on_title_sfx_volume_changed)
title_sfx_volume_row.add_child(title_sfx_volume_slider)
title_sfx_volume_value_label = Label.new()
title_sfx_volume_value_label.custom_minimum_size = Vector2(48, 30)
title_sfx_volume_value_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
title_sfx_volume_value_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_apply_label_style(title_sfx_volume_value_label, UI_PARCHMENT_TEXT, 13)
title_sfx_volume_row.add_child(title_sfx_volume_value_label)
title_edge_scroll_toggle = CheckButton.new()
title_edge_scroll_toggle.text = "가장자리 스크롤"
title_edge_scroll_toggle.custom_minimum_size = Vector2(392, 30)
title_edge_scroll_toggle.button_pressed = title_edge_scroll_enabled
title_edge_scroll_toggle.tooltip_text = "마우스를 전장 가장자리에 두면 화면을 움직입니다."
title_edge_scroll_toggle.toggled.connect(_on_title_edge_scroll_toggled)
@@ -3161,9 +3242,79 @@ func _create_hud() -> void:
func _create_audio() -> void:
bgm_player = AudioStreamPlayer.new()
bgm_player.name = "BgmPlayer"
bgm_player.volume_db = BGM_VOLUME_DB
bgm_player.volume_db = _bgm_volume_db()
bgm_player.finished.connect(_on_bgm_finished)
add_child(bgm_player)
_apply_audio_settings()
func _load_title_settings() -> void:
if not FileAccess.file_exists(SETTINGS_PATH):
return
var parsed = JSON.parse_string(FileAccess.get_file_as_string(SETTINGS_PATH))
if not parsed is Dictionary:
return
title_bgm_enabled = bool(parsed.get("bgm_enabled", title_bgm_enabled))
title_sfx_enabled = bool(parsed.get("sfx_enabled", title_sfx_enabled))
title_edge_scroll_enabled = bool(parsed.get("edge_scroll_enabled", title_edge_scroll_enabled))
title_bgm_volume_percent = _clamp_volume_percent(parsed.get("bgm_volume_percent", title_bgm_volume_percent))
title_sfx_volume_percent = _clamp_volume_percent(parsed.get("sfx_volume_percent", title_sfx_volume_percent))
func _save_title_settings() -> bool:
var file := FileAccess.open(SETTINGS_PATH, FileAccess.WRITE)
if file == null:
push_warning("Unable to save title settings: %s" % SETTINGS_PATH)
return false
var payload := {
"save_version": SETTINGS_SAVE_VERSION,
"bgm_enabled": title_bgm_enabled,
"bgm_volume_percent": title_bgm_volume_percent,
"sfx_enabled": title_sfx_enabled,
"sfx_volume_percent": title_sfx_volume_percent,
"edge_scroll_enabled": title_edge_scroll_enabled
}
file.store_string(JSON.stringify(payload, "\t"))
return true
func _apply_audio_settings() -> void:
if bgm_player != null:
bgm_player.volume_db = _bgm_volume_db()
if not title_bgm_enabled:
bgm_player.stop()
func _clamp_volume_percent(value) -> int:
return mini(maxi(int(value), 0), 100)
func _bgm_volume_db() -> float:
return _volume_percent_to_db(BGM_VOLUME_DB, title_bgm_volume_percent)
func _effective_sfx_volume_db(base_volume_db: float) -> float:
return _volume_percent_to_db(base_volume_db, title_sfx_volume_percent)
func _volume_percent_to_db(base_volume_db: float, percent: int) -> float:
var clamped := _clamp_volume_percent(percent)
if clamped <= 0:
return AUDIO_MUTED_DB
return base_volume_db + linear_to_db(float(clamped) / 100.0)
func _refresh_title_volume_controls() -> void:
if title_bgm_volume_slider != null:
title_bgm_volume_slider.set_value_no_signal(float(title_bgm_volume_percent))
title_bgm_volume_slider.editable = title_bgm_enabled
if title_sfx_volume_slider != null:
title_sfx_volume_slider.set_value_no_signal(float(title_sfx_volume_percent))
title_sfx_volume_slider.editable = title_sfx_enabled
if title_bgm_volume_value_label != null:
title_bgm_volume_value_label.text = "%d%%" % title_bgm_volume_percent
if title_sfx_volume_value_label != null:
title_sfx_volume_value_label.text = "%d%%" % title_sfx_volume_percent
func _on_bgm_finished() -> void:
@@ -3181,6 +3332,7 @@ func _play_bgm(key: String) -> void:
current_bgm_key = key
bgm_player.stop()
return
bgm_player.volume_db = _bgm_volume_db()
if current_bgm_key == key and bgm_player.playing:
return
var stream := _bgm_stream_for(key)
@@ -3209,7 +3361,7 @@ func _play_sfx(key: String, volume_db := SFX_VOLUME_DB) -> void:
var player := AudioStreamPlayer.new()
player.name = "Sfx_%s" % key
player.stream = stream
player.volume_db = volume_db
player.volume_db = _effective_sfx_volume_db(volume_db)
player.finished.connect(player.queue_free)
add_child(player)
player.play()
@@ -9880,11 +10032,12 @@ func _update_title_menu_state() -> void:
if title_settings_back_button != null:
title_settings_back_button.visible = title_settings_panel != null and title_settings_panel.visible
if title_bgm_toggle != null:
title_bgm_toggle.button_pressed = title_bgm_enabled
title_bgm_toggle.set_pressed_no_signal(title_bgm_enabled)
if title_sfx_toggle != null:
title_sfx_toggle.button_pressed = title_sfx_enabled
title_sfx_toggle.set_pressed_no_signal(title_sfx_enabled)
if title_edge_scroll_toggle != null:
title_edge_scroll_toggle.button_pressed = title_edge_scroll_enabled
title_edge_scroll_toggle.set_pressed_no_signal(title_edge_scroll_enabled)
_refresh_title_volume_controls()
func _format_title_status_text(has_load: bool) -> String:
@@ -9967,6 +10120,14 @@ func _on_title_settings_back_pressed() -> void:
func _set_title_settings_visible(visible: bool) -> void:
if title_status_label != null:
title_status_label.visible = not visible
if title_start_button != null:
title_start_button.visible = not visible
if title_load_button != null:
title_load_button.visible = not visible
if title_settings_button != null:
title_settings_button.visible = not visible
if title_settings_panel != null:
title_settings_panel.visible = visible
if title_settings_back_button != null:
@@ -9979,6 +10140,8 @@ func _on_title_bgm_toggled(enabled: bool) -> void:
_play_bgm(current_bgm_key if not current_bgm_key.is_empty() else "menu")
elif bgm_player != null:
bgm_player.stop()
_apply_audio_settings()
_save_title_settings()
_update_title_menu_state()
@@ -9986,15 +10149,32 @@ func _on_title_sfx_toggled(enabled: bool) -> void:
title_sfx_enabled = enabled
if title_sfx_enabled:
_play_sfx("ui_click", UI_SFX_VOLUME_DB)
_save_title_settings()
_update_title_menu_state()
func _on_title_edge_scroll_toggled(enabled: bool) -> void:
title_edge_scroll_enabled = enabled
_save_title_settings()
_update_title_menu_state()
queue_redraw()
func _on_title_bgm_volume_changed(value: float) -> void:
title_bgm_volume_percent = _clamp_volume_percent(value)
_apply_audio_settings()
_save_title_settings()
_refresh_title_volume_controls()
func _on_title_sfx_volume_changed(value: float) -> void:
title_sfx_volume_percent = _clamp_volume_percent(value)
_save_title_settings()
_refresh_title_volume_controls()
if title_sfx_enabled:
_play_sfx("ui_click", UI_SFX_VOLUME_DB)
func _update_top_archive_buttons() -> void:
var prep_available := (
not battle_started