difficulty: mogut desde options a un fitxer propi

This commit is contained in:
2025-07-23 19:52:57 +02:00
parent e21839e478
commit d33c1f5dc5
10 changed files with 319 additions and 146 deletions

View File

@@ -4,19 +4,18 @@
#include <algorithm> // Para clamp, max
#include <fstream> // Para basic_ostream, operator<<, basic_ostream::operator<<, basic_ofstream, basic_istream, basic_ifstream, ifstream, ofstream
#include <utility> // Para swap
#include <vector> // Para vector
#include <functional>
#include <map>
#include <stdexcept> // Para excepciones de std::stoi
#include <string>
#include <utility> // Para swap
#include <vector> // Para vector
#include "asset.h" // Para Asset
#include "difficulty.h" // Para Difficulty
#include "input.h" // Para InputDevice
#include "lang.h" // Para Code
#include "utils.h" // Para boolToString, stringToBool, getFileName
#include <string>
#include <functional>
#include <map>
#include <stdexcept> // Para excepciones de std::stoi
namespace Options {
// --- Variables globales ---
WindowOptions window; // Opciones de la ventana
@@ -26,19 +25,16 @@ AudioOptions audio; // Opciones de audio
std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
PendingChanges pending_changes; // Opciones que se aplican al cerrar
// Vector con las dificultades
std::vector<Difficulty> difficulties = {
{DifficultyCode::EASY, "Easy"},
{DifficultyCode::NORMAL, "Normal"},
{DifficultyCode::HARD, "Hard"}};
// Declaraciones
auto set(const std::string &var, const std::string &value) -> bool;
auto set(const std::string& var, const std::string& value) -> bool;
// Establece el fichero de configuración
void setFile(const std::string& file_path) { settings.config_file = file_path; };
// Inicializa las opciones del programa
void init() {
// Settings
settings.config_file = Asset::get()->get("config.txt");
// Dificultades
Difficulty::init();
// Opciones de control
controllers.clear();
@@ -143,7 +139,7 @@ auto saveToFile() -> bool {
// Opciones del juego
file << "\n\n## GAME\n";
file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
file << "## game.difficulty [" << static_cast<int>(DifficultyCode::EASY) << ": easy, " << static_cast<int>(DifficultyCode::NORMAL) << ": normal, " << static_cast<int>(DifficultyCode::HARD) << ": hard]\n";
file << "## game.difficulty [" << static_cast<int>(Difficulty::Code::EASY) << ": easy, " << static_cast<int>(Difficulty::Code::NORMAL) << ": normal, " << static_cast<int>(Difficulty::Code::HARD) << ": hard]\n";
file << "\n";
file << "game.language=" << static_cast<int>(settings.language) << "\n";
@@ -155,7 +151,7 @@ auto saveToFile() -> bool {
file << "\n\n## CONTROLLERS\n";
int controller_index = 0;
for (const auto &controller : controllers) {
for (const auto& controller : controllers) {
file << "\n";
file << "controller." << controller_index << ".name=" << controller.name << "\n";
file << "controller." << controller_index << ".player=" << controller.player_id << "\n";
@@ -177,7 +173,7 @@ auto saveToFile() -> bool {
}
// Función auxiliar para analizar la configuración del mando y reducir duplicación
void parseAndSetController(const std::string &var, const std::string &value) {
void parseAndSetController(const std::string& var, const std::string& value) {
// Lógica básica de análisis (puede hacerse más robusta)
size_t first_dot = var.find('.');
size_t second_dot = var.find('.', first_dot + 1);
@@ -206,7 +202,7 @@ void parseAndSetController(const std::string &var, const std::string &value) {
}
}
auto set(const std::string &var, const std::string &value) -> bool {
auto set(const std::string& var, const std::string& value) -> bool {
// Clausula de protección: ignora líneas vacías o comentarios
if (var.empty() || var.starts_with("#")) {
return false;
@@ -215,32 +211,31 @@ auto set(const std::string &var, const std::string &value) -> bool {
// Un mapa estático asegura que se inicializa solo una vez
static const std::map<std::string, std::function<void(const std::string&)>> settings_map = {
// Ventana
{"window.zoom", [](const auto& val){ window.zoom = std::stoi(val); }},
{"window.zoom", [](const auto& val) { window.zoom = std::stoi(val); }},
// Vídeo
{"video.fullscreen", [](const auto& val){ video.fullscreen = stringToBool(val); }},
{"video.scale_mode", [](const auto& val){ video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(val)); }},
{"video.shaders", [](const auto& val){ video.shaders = stringToBool(val); }},
{"video.integer_scale", [](const auto& val){ video.integer_scale = stringToBool(val); }},
{"video.vsync", [](const auto& val){ video.vsync = stringToBool(val); }},
{"video.fullscreen", [](const auto& val) { video.fullscreen = stringToBool(val); }},
{"video.scale_mode", [](const auto& val) { video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(val)); }},
{"video.shaders", [](const auto& val) { video.shaders = stringToBool(val); }},
{"video.integer_scale", [](const auto& val) { video.integer_scale = stringToBool(val); }},
{"video.vsync", [](const auto& val) { video.vsync = stringToBool(val); }},
// Audio
{"audio.enabled", [](const auto& val){ audio.enabled = stringToBool(val); }},
{"audio.volume", [](const auto& val){ audio.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.music.enabled", [](const auto& val){ audio.music.enabled = stringToBool(val); }},
{"audio.music.volume", [](const auto& val){ audio.music.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.sound.enabled", [](const auto& val){ audio.sound.enabled = stringToBool(val); }},
{"audio.sound.volume", [](const auto& val){ audio.sound.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.enabled", [](const auto& val) { audio.enabled = stringToBool(val); }},
{"audio.volume", [](const auto& val) { audio.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.music.enabled", [](const auto& val) { audio.music.enabled = stringToBool(val); }},
{"audio.music.volume", [](const auto& val) { audio.music.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.sound.enabled", [](const auto& val) { audio.sound.enabled = stringToBool(val); }},
{"audio.sound.volume", [](const auto& val) { audio.sound.volume = std::clamp(std::stoi(val), 0, 100); }},
// Juego
{"game.language", [](const auto& val){
settings.language = static_cast<Lang::Code>(std::stoi(val));
pending_changes.new_language = settings.language;
}},
{"game.difficulty", [](const auto& val){
settings.difficulty = static_cast<DifficultyCode>(std::stoi(val));
pending_changes.new_difficulty = settings.difficulty;
}},
{"game.autofire", [](const auto& val){ settings.autofire = stringToBool(val); }},
{"game.shutdown_enabled", [](const auto& val){ settings.shutdown_enabled = stringToBool(val); }}
};
{"game.language", [](const auto& val) {
settings.language = static_cast<Lang::Code>(std::stoi(val));
pending_changes.new_language = settings.language;
}},
{"game.difficulty", [](const auto& val) {
settings.difficulty = static_cast<Difficulty::Code>(std::stoi(val));
pending_changes.new_difficulty = settings.difficulty;
}},
{"game.autofire", [](const auto& val) { settings.autofire = stringToBool(val); }},
{"game.shutdown_enabled", [](const auto& val) { settings.shutdown_enabled = stringToBool(val); }}};
// Maneja por separado la configuración general de los mandos
if (var.starts_with("controller.")) {
@@ -249,7 +244,7 @@ auto set(const std::string &var, const std::string &value) -> bool {
return true;
} catch (const std::out_of_range& e) {
// Error: por ejemplo, índice de mando fuera de rango
return false;
return false;
} catch (const std::invalid_argument& e) {
// Error: por ejemplo, fallo en std::stoi
return false;
@@ -267,15 +262,14 @@ auto set(const std::string &var, const std::string &value) -> bool {
return false;
}
}
// Si la clave no se encontró en el mapa ni en la lógica de mandos
return false;
}
// Asigna el teclado al jugador
void setKeyboardToPlayer(int player_id) {
for (auto &controller : controllers) {
for (auto& controller : controllers) {
if (controller.player_id == player_id) {
controller.type = InputDevice::ANY;
} else {
@@ -297,7 +291,7 @@ void swapControllers() {
// Averigua quien está usando el teclado
auto getPlayerWhoUsesKeyboard() -> int {
for (const auto &controller : controllers) {
for (const auto& controller : controllers) {
if (controller.type == InputDevice::ANY) {
return controller.player_id;
}
@@ -318,24 +312,4 @@ void checkPendingChanges() {
pending_changes.has_pending_changes = settings.language != pending_changes.new_language ||
settings.difficulty != pending_changes.new_difficulty;
}
auto getDifficultyCodeFromName(const std::string &name) -> DifficultyCode {
for (const auto &difficulty : difficulties) {
if (difficulty.name == name) {
return difficulty.code;
}
}
// Si no se encuentra, devuelve el primero por defecto
return difficulties[0].code;
}
auto getDifficultyNameFromCode(DifficultyCode code) -> std::string {
for (const auto &difficulty : difficulties) {
if (difficulty.code == code) {
return difficulty.name;
}
}
// Si no se encuentra, devuelve el nombre del primero por defecto
return difficulties[0].name;
}
} // namespace Options