diff --git a/source/core/audio/audio.cpp b/source/core/audio/audio.cpp index 300feb3..6b88731 100644 --- a/source/core/audio/audio.cpp +++ b/source/core/audio/audio.cpp @@ -177,6 +177,18 @@ void Audio::initSDLAudio() { JA_Init(FREQUENCY, SDL_AUDIO_S16LE, 2); enable(Options::audio.enabled); + // Aplicar estado de música y sonido guardado en las opciones. + // enable() ya aplica los volúmenes, pero no toca music_enabled_/sound_enabled_. + // Si alguno está desactivado, hay que forzar el volumen a 0 en el backend. + if (!Options::audio.music.enabled) { + setMusicVolume(0.0F); // music_enabled_=true aún → llega a JA + enableMusic(false); + } + if (!Options::audio.sound.enabled) { + setSoundVolume(0.0F); // sound_enabled_=true aún → llega a JA + enableSound(false); + } + std::cout << "\n** AUDIO SYSTEM **\n"; std::cout << "Audio system initialized successfully\n"; } diff --git a/source/game/options.cpp b/source/game/options.cpp index a059d0e..a69ddb6 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -527,6 +527,43 @@ namespace Options { } } + // Carga configuración de audio desde YAML + void loadAudioConfigFromYaml(const fkyaml::node& yaml) { + if (!yaml.contains("audio")) { return; } + const auto& a = yaml["audio"]; + + if (a.contains("enabled")) { + try { audio.enabled = a["enabled"].get_value(); } catch (...) {} + } + if (a.contains("volume")) { + try { + audio.volume = std::clamp(a["volume"].get_value(), 0.0F, 1.0F); + } catch (...) {} + } + if (a.contains("music")) { + const auto& m = a["music"]; + if (m.contains("enabled")) { + try { audio.music.enabled = m["enabled"].get_value(); } catch (...) {} + } + if (m.contains("volume")) { + try { + audio.music.volume = std::clamp(m["volume"].get_value(), 0.0F, 1.0F); + } catch (...) {} + } + } + if (a.contains("sound")) { + const auto& s = a["sound"]; + if (s.contains("enabled")) { + try { audio.sound.enabled = s["enabled"].get_value(); } catch (...) {} + } + if (s.contains("volume")) { + try { + audio.sound.volume = std::clamp(s["volume"].get_value(), 0.0F, 1.0F); + } catch (...) {} + } + } + } + // Carga configuración de idioma desde YAML void loadLocalizationFromYaml(const fkyaml::node& yaml) { if (yaml.contains("localization")) { @@ -602,6 +639,7 @@ namespace Options { // Carga las diferentes secciones de configuración usando funciones helper loadWindowConfigFromYaml(yaml); loadVideoConfigFromYaml(yaml); + loadAudioConfigFromYaml(yaml); loadKeyboardControlsFromYaml(yaml); loadGamepadControlsFromYaml(yaml); loadKioskConfigFromYaml(yaml); @@ -657,6 +695,19 @@ namespace Options { file << " zoom: " << window.zoom << "\n"; file << "\n"; + // AUDIO + file << "# AUDIO\n"; + file << "audio:\n"; + file << " enabled: " << (audio.enabled ? "true" : "false") << "\n"; + file << " volume: " << audio.volume << " # 0.0-1.0 (volumen maestro)\n"; + file << " music:\n"; + file << " enabled: " << (audio.music.enabled ? "true" : "false") << "\n"; + file << " volume: " << audio.music.volume << "\n"; + file << " sound:\n"; + file << " enabled: " << (audio.sound.enabled ? "true" : "false") << "\n"; + file << " volume: " << audio.sound.volume << "\n"; + file << "\n"; + // VIDEO file << "# VIDEO \n"; file << "video:\n"; diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index 48c525a..55a9a14 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -7,6 +7,7 @@ #include // Para string #include // Para vector +#include "core/audio/audio.hpp" // Para Audio #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/sprite/sprite.hpp" // Para Sprite #include "core/rendering/surface.hpp" // Para Surface @@ -77,6 +78,9 @@ static void printHelp() { #ifdef _DEBUG SDL_Log(" DEBUG Toggle debug overlay (F12)"); #endif + SDL_Log(" AUDIO [ON|OFF|VOL <0-100>] Audio master"); + SDL_Log(" MUSIC [ON|OFF|VOL <0-100>] Music volume"); + SDL_Log(" SOUND [ON|OFF|VOL <0-100>] Sound volume"); SDL_Log(" SCENE [LOGO|LOADING|TITLE|CREDITS|GAME|ENDING|ENDING2|RESTART]"); SDL_Log(" KIOSK [ON] Enable kiosk mode"); SDL_Log(" EXIT / QUIT Quit application"); @@ -364,6 +368,107 @@ static const std::vector COMMANDS = { return "Usage: KIOSK [ON]"; }}, + // AUDIO [ON|OFF|VOL <0-100>] — Audio maestro (estado + volumen) + {.keyword = "AUDIO", .execute = [](const std::vector& args) -> std::string { + if (args.empty()) { + const int VOL = static_cast(Options::audio.volume * 100.0F); + return std::string("Audio ") + (Options::audio.enabled ? "ON" : "OFF") + + " vol:" + std::to_string(VOL); + } + if (args[0] == "ON") { + if (Options::audio.enabled) { return "Audio already ON"; } + Options::audio.enabled = true; + Audio::get()->enable(true); + return "Audio ON"; + } + if (args[0] == "OFF") { + if (!Options::audio.enabled) { return "Audio already OFF"; } + Options::audio.enabled = false; + Audio::get()->enable(false); + return "Audio OFF"; + } + if (args[0] == "VOL" && args.size() >= 2) { + try { + const int VAL = std::stoi(args[1]); + if (VAL < 0 || VAL > 100) { return "Vol must be 0-100"; } + Options::audio.volume = static_cast(VAL) / 100.0F; + Audio::get()->enable(Options::audio.enabled); + return "Audio vol:" + std::to_string(VAL); + } catch (...) { return "Usage: AUDIO VOL <0-100>"; } + } + return "Usage: AUDIO [ON|OFF|VOL N]"; + }}, + + // MUSIC [ON|OFF|VOL <0-100>] — Volumen e interruptor de música + {.keyword = "MUSIC", .execute = [](const std::vector& args) -> std::string { + if (args.empty()) { + const int VOL = static_cast(Options::audio.music.volume * 100.0F); + return std::string("Music ") + (Options::audio.music.enabled ? "ON" : "OFF") + + " vol:" + std::to_string(VOL); + } + if (args[0] == "ON") { + if (Options::audio.music.enabled) { return "Music already ON"; } + Options::audio.music.enabled = true; + Audio::get()->enableMusic(true); + Audio::get()->setMusicVolume(Options::audio.music.volume); + return "Music ON"; + } + if (args[0] == "OFF") { + if (!Options::audio.music.enabled) { return "Music already OFF"; } + Audio::get()->setMusicVolume(0.0F); + Audio::get()->enableMusic(false); + Options::audio.music.enabled = false; + return "Music OFF"; + } + if (args[0] == "VOL" && args.size() >= 2) { + try { + const int VAL = std::stoi(args[1]); + if (VAL < 0 || VAL > 100) { return "Vol must be 0-100"; } + Options::audio.music.volume = static_cast(VAL) / 100.0F; + if (Options::audio.music.enabled) { + Audio::get()->setMusicVolume(Options::audio.music.volume); + } + return "Music vol:" + std::to_string(VAL); + } catch (...) { return "Usage: MUSIC VOL <0-100>"; } + } + return "Usage: MUSIC [ON|OFF|VOL N]"; + }}, + + // SOUND [ON|OFF|VOL <0-100>] — Volumen e interruptor de efectos de sonido + {.keyword = "SOUND", .execute = [](const std::vector& args) -> std::string { + if (args.empty()) { + const int VOL = static_cast(Options::audio.sound.volume * 100.0F); + return std::string("Sound ") + (Options::audio.sound.enabled ? "ON" : "OFF") + + " vol:" + std::to_string(VOL); + } + if (args[0] == "ON") { + if (Options::audio.sound.enabled) { return "Sound already ON"; } + Options::audio.sound.enabled = true; + Audio::get()->enableSound(true); + Audio::get()->setSoundVolume(Options::audio.sound.volume); + return "Sound ON"; + } + if (args[0] == "OFF") { + if (!Options::audio.sound.enabled) { return "Sound already OFF"; } + Audio::get()->setSoundVolume(0.0F); + Audio::get()->enableSound(false); + Options::audio.sound.enabled = false; + return "Sound OFF"; + } + if (args[0] == "VOL" && args.size() >= 2) { + try { + const int VAL = std::stoi(args[1]); + if (VAL < 0 || VAL > 100) { return "Vol must be 0-100"; } + Options::audio.sound.volume = static_cast(VAL) / 100.0F; + if (Options::audio.sound.enabled) { + Audio::get()->setSoundVolume(Options::audio.sound.volume); + } + return "Sound vol:" + std::to_string(VAL); + } catch (...) { return "Usage: SOUND VOL <0-100>"; } + } + return "Usage: SOUND [ON|OFF|VOL N]"; + }}, + // EXIT / QUIT — Cerrar la aplicacion (bloqueado en kiosk) {.keyword = "EXIT", .execute = [](const std::vector& args) -> std::string { if (Options::kiosk.enabled && (args.empty() || args[0] != "PLEASE")) {