migrada la configuracio de txt a yaml
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,5 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
*data/config/config.txt
|
*data/config/config.yaml
|
||||||
*stats.txt
|
*stats.txt
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
thumbs.db
|
thumbs.db
|
||||||
|
|||||||
@@ -587,7 +587,7 @@ namespace Options {
|
|||||||
inline Stats stats{}; // Game statistics
|
inline Stats stats{}; // Game statistics
|
||||||
}
|
}
|
||||||
|
|
||||||
Options::loadFromFile(path); // Load from config.txt
|
Options::loadFromFile(path); // Load from config.yaml
|
||||||
Options::saveToFile(path); // Save on exit
|
Options::saveToFile(path); // Save on exit
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -820,7 +820,7 @@ assets:
|
|||||||
# SYSTEM FILES (optional, absolute paths)
|
# SYSTEM FILES (optional, absolute paths)
|
||||||
system:
|
system:
|
||||||
- type: DATA
|
- type: DATA
|
||||||
path: ${SYSTEM_FOLDER}/config.txt
|
path: ${SYSTEM_FOLDER}/config.yaml
|
||||||
required: false
|
required: false
|
||||||
absolute: true
|
absolute: true
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ El programa guarda automàticament la configuració del mode de vídeo i les est
|
|||||||
|
|
||||||
- **Windows**: `C:\Users\<nom_d'usuari>\AppData\Roaming\jailgames\jaildoctors_dilemma`
|
- **Windows**: `C:\Users\<nom_d'usuari>\AppData\Roaming\jailgames\jaildoctors_dilemma`
|
||||||
- **MacOS**: `~/Library/Application Support/jailgames/jaildoctors_dilemma`
|
- **MacOS**: `~/Library/Application Support/jailgames/jaildoctors_dilemma`
|
||||||
- **Linux**: `~/.jailgames/jaildoctors_dilemma`
|
- **Linux**: `~/.config/jailgames/jaildoctors_dilemma`
|
||||||
|
|
||||||
Dins de la carpeta es troba el fitxer de configuració `config.txt`, on es pot modificar la configuració per connectar-se al servei en línia, i els fitxers `stats.csv` i `stats_buffer.csv`, que contenen informació sobre les estadístiques del joc.
|
Dins de la carpeta es troba el fitxer de configuració `config.yaml`, on es pot modificar la configuració per connectar-se al servei en línia, i els fitxers `stats.csv` i `stats_buffer.csv`, que contenen informació sobre les estadístiques del joc.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ assets:
|
|||||||
# SYSTEM
|
# SYSTEM
|
||||||
system:
|
system:
|
||||||
- type: DATA
|
- type: DATA
|
||||||
path: ${SYSTEM_FOLDER}/config.txt
|
path: ${SYSTEM_FOLDER}/config.yaml
|
||||||
required: false
|
required: false
|
||||||
absolute: true
|
absolute: true
|
||||||
- type: DATA
|
- type: DATA
|
||||||
|
|||||||
@@ -118,8 +118,9 @@ Director::Director(std::vector<std::string> const& args) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Carga las opciones desde un fichero
|
// Configura la ruta y carga las opciones desde un fichero
|
||||||
Options::loadFromFile(Resource::List::get()->get("config.txt"));
|
Options::setConfigFile(Resource::List::get()->get("config.yaml"));
|
||||||
|
Options::loadFromFile();
|
||||||
|
|
||||||
// Inicializa JailAudio
|
// Inicializa JailAudio
|
||||||
Audio::init();
|
Audio::init();
|
||||||
@@ -160,7 +161,7 @@ Director::Director(std::vector<std::string> const& args) {
|
|||||||
|
|
||||||
Director::~Director() {
|
Director::~Director() {
|
||||||
// Guarda las opciones a un fichero
|
// Guarda las opciones a un fichero
|
||||||
Options::saveToFile(Resource::List::get()->get("config.txt"));
|
Options::saveToFile();
|
||||||
|
|
||||||
// Destruye los singletones
|
// Destruye los singletones
|
||||||
Cheevos::destroy();
|
Cheevos::destroy();
|
||||||
|
|||||||
@@ -2,27 +2,14 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <algorithm> // Para find_if
|
#include <fstream> // Para ifstream, ofstream
|
||||||
#include <cctype> // Para isspace
|
#include <iostream> // Para cout, cerr
|
||||||
#include <fstream> // Para basic_ostream, operator<<, basic_ofstream
|
#include <string> // Para string
|
||||||
#include <functional> // Para function
|
|
||||||
#include <iostream> // Para cout, cerr
|
|
||||||
#include <ranges>
|
|
||||||
#include <sstream> // Para basic_istringstream
|
|
||||||
#include <string> // Para char_traits, string, operator<<, hash
|
|
||||||
#include <unordered_map> // Para unordered_map, operator==, _Node_const_i...
|
|
||||||
#include <utility> // Para pair
|
|
||||||
|
|
||||||
#include "game/defaults.hpp" // Para GameDefaults::VERSION
|
#include "external/fkyaml_node.hpp" // Para fkyaml::node
|
||||||
#include "utils/utils.hpp" // Para stringToBool, boolToString, safeStoi
|
#include "game/defaults.hpp" // Para GameDefaults::VERSION
|
||||||
|
|
||||||
namespace Options {
|
namespace Options {
|
||||||
// Declaración de funciones internas
|
|
||||||
auto setOptions(const std::string& var, const std::string& value) -> bool;
|
|
||||||
auto trimLine(const std::string& line) -> std::string;
|
|
||||||
auto isCommentOrEmpty(const std::string& line) -> bool;
|
|
||||||
auto processConfigLine(const std::string& line) -> bool;
|
|
||||||
auto readConfigFile(const std::string& file_path) -> bool;
|
|
||||||
|
|
||||||
// Crea e inicializa las opciones del programa
|
// Crea e inicializa las opciones del programa
|
||||||
void init() {
|
void init() {
|
||||||
@@ -33,245 +20,253 @@ void init() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elimina espacios en blanco al inicio y final de una línea
|
// Establece la ruta del fichero de configuración
|
||||||
auto trimLine(const std::string& line) -> std::string {
|
void setConfigFile(const std::string& path) {
|
||||||
auto start = std::ranges::find_if(line, [](int ch) { return !std::isspace(ch); });
|
config_file_path_ = path;
|
||||||
auto end = std::ranges::find_if(std::ranges::reverse_view(line), [](int ch) { return !std::isspace(ch); }).base();
|
|
||||||
return {start, end};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifica si una línea es comentario o está vacía
|
// Carga las opciones desde el fichero configurado
|
||||||
auto isCommentOrEmpty(const std::string& line) -> bool {
|
auto loadFromFile() -> bool {
|
||||||
return line.empty() || line[0] == '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Procesa una línea de configuración individual
|
|
||||||
auto processConfigLine(const std::string& line) -> bool {
|
|
||||||
std::istringstream iss(line);
|
|
||||||
std::string key;
|
|
||||||
std::string value;
|
|
||||||
|
|
||||||
if (iss >> key >> value) {
|
|
||||||
if (!setOptions(key, value)) {
|
|
||||||
if (console) {
|
|
||||||
std::cout << "Warning: file config.txt\n";
|
|
||||||
std::cout << "unknown parameter " << key << '\n';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lee y procesa el fichero de configuración
|
|
||||||
auto readConfigFile(const std::string& file_path) -> bool {
|
|
||||||
std::ifstream file(file_path);
|
|
||||||
if (!file.good()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool success = true;
|
|
||||||
if (console) {
|
|
||||||
std::cout << "Reading file config.txt\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(file, line)) {
|
|
||||||
line = trimLine(line);
|
|
||||||
|
|
||||||
if (isCommentOrEmpty(line)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!processConfigLine(line)) {
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (console) {
|
|
||||||
std::cout << "Closing file config.txt\n\n";
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carga las opciones desde un fichero
|
|
||||||
auto loadFromFile(const std::string& file_path) -> bool {
|
|
||||||
// Versión esperada del fichero
|
// Versión esperada del fichero
|
||||||
const std::string CONFIG_VERSION = GameDefaults::VERSION;
|
const std::string CONFIG_VERSION = GameDefaults::VERSION;
|
||||||
version = "";
|
version = "";
|
||||||
|
|
||||||
// Intenta leer el fichero
|
// Intenta abrir y leer el fichero
|
||||||
bool success = readConfigFile(file_path);
|
std::ifstream file(config_file_path_);
|
||||||
|
if (!file.good()) {
|
||||||
// Si no se pudo leer, crea el fichero con valores por defecto
|
|
||||||
if (!success) {
|
|
||||||
saveToFile(file_path);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si la versión de fichero no coincide, crea un fichero nuevo con los valores por defecto
|
|
||||||
if (CONFIG_VERSION != version) {
|
|
||||||
init();
|
|
||||||
saveToFile(file_path);
|
|
||||||
if (console) {
|
if (console) {
|
||||||
std::cout << "Wrong config file: initializing \n\n";
|
std::cout << "Config file not found, creating default: " << config_file_path_ << '\n';
|
||||||
}
|
}
|
||||||
|
saveToFile();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
// Lee todo el contenido del fichero
|
||||||
|
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (console) {
|
||||||
|
std::cout << "Reading config file: " << config_file_path_ << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsea el YAML
|
||||||
|
auto yaml = fkyaml::node::deserialize(content);
|
||||||
|
|
||||||
|
// Lee la versión
|
||||||
|
if (yaml.contains("version")) {
|
||||||
|
version = yaml["version"].get_value<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si la versión no coincide, crea un fichero nuevo con valores por defecto
|
||||||
|
if (CONFIG_VERSION != version) {
|
||||||
|
if (console) {
|
||||||
|
std::cout << "Config version mismatch (expected: " << CONFIG_VERSION << ", got: " << version << "), creating new config\n";
|
||||||
|
}
|
||||||
|
init();
|
||||||
|
saveToFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lee window
|
||||||
|
if (yaml.contains("window")) {
|
||||||
|
const auto& win = yaml["window"];
|
||||||
|
if (win.contains("zoom")) {
|
||||||
|
int val = win["zoom"].get_value<int>();
|
||||||
|
window.zoom = (val > 0) ? val : GameDefaults::WINDOW_ZOOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lee video
|
||||||
|
if (yaml.contains("video")) {
|
||||||
|
const auto& vid = yaml["video"];
|
||||||
|
|
||||||
|
if (vid.contains("mode")) {
|
||||||
|
video.fullscreen = vid["mode"].get_value<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vid.contains("filter")) {
|
||||||
|
int val = vid["filter"].get_value<int>();
|
||||||
|
if (val == static_cast<int>(Screen::Filter::NEAREST) || val == static_cast<int>(Screen::Filter::LINEAR)) {
|
||||||
|
video.filter = static_cast<Screen::Filter>(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vid.contains("shaders")) {
|
||||||
|
video.shaders = vid["shaders"].get_value<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vid.contains("vertical_sync")) {
|
||||||
|
video.vertical_sync = vid["vertical_sync"].get_value<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vid.contains("integer_scale")) {
|
||||||
|
video.integer_scale = vid["integer_scale"].get_value<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vid.contains("keep_aspect")) {
|
||||||
|
video.keep_aspect = vid["keep_aspect"].get_value<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vid.contains("palette")) {
|
||||||
|
video.palette = vid["palette"].get_value<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lee border
|
||||||
|
if (vid.contains("border")) {
|
||||||
|
const auto& border = vid["border"];
|
||||||
|
|
||||||
|
if (border.contains("enabled")) {
|
||||||
|
video.border.enabled = border["enabled"].get_value<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (border.contains("width")) {
|
||||||
|
float val = border["width"].get_value<float>();
|
||||||
|
video.border.width = (val > 0) ? val : GameDefaults::BORDER_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (border.contains("height")) {
|
||||||
|
float val = border["height"].get_value<float>();
|
||||||
|
video.border.height = (val > 0) ? val : GameDefaults::BORDER_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lee controls
|
||||||
|
if (yaml.contains("controls")) {
|
||||||
|
const auto& ctrl = yaml["controls"];
|
||||||
|
|
||||||
|
if (ctrl.contains("left")) {
|
||||||
|
int val = ctrl["left"].get_value<int>();
|
||||||
|
controls.key_left = static_cast<SDL_Scancode>(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctrl.contains("right")) {
|
||||||
|
int val = ctrl["right"].get_value<int>();
|
||||||
|
controls.key_right = static_cast<SDL_Scancode>(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctrl.contains("jump")) {
|
||||||
|
int val = ctrl["jump"].get_value<int>();
|
||||||
|
controls.key_jump = static_cast<SDL_Scancode>(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lee gamepad_controls
|
||||||
|
if (yaml.contains("gamepad_controls")) {
|
||||||
|
const auto& gp = yaml["gamepad_controls"];
|
||||||
|
|
||||||
|
if (gp.contains("left")) {
|
||||||
|
gamepad_controls.button_left = gp["left"].get_value<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gp.contains("right")) {
|
||||||
|
gamepad_controls.button_right = gp["right"].get_value<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gp.contains("jump")) {
|
||||||
|
gamepad_controls.button_jump = gp["jump"].get_value<int>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (console) {
|
||||||
|
std::cout << "Config file loaded successfully\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (const fkyaml::exception& e) {
|
||||||
|
if (console) {
|
||||||
|
std::cerr << "Error parsing YAML config: " << e.what() << '\n';
|
||||||
|
std::cerr << "Creating new config with defaults\n";
|
||||||
|
}
|
||||||
|
init();
|
||||||
|
saveToFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guarda las opciones en un fichero
|
// Guarda las opciones al fichero configurado
|
||||||
auto saveToFile(const std::string& file_path) -> bool {
|
auto saveToFile() -> bool {
|
||||||
// Crea y abre el fichero de texto
|
// Crea el nodo YAML raíz como mapping
|
||||||
std::ofstream file(file_path);
|
fkyaml::node yaml(fkyaml::node_type::MAPPING);
|
||||||
bool success = file.is_open(); // Verifica si el archivo se abrió correctamente
|
|
||||||
|
|
||||||
if (!success) // Si no se pudo abrir el archivo, muestra un mensaje de error y devuelve false
|
// Establece la versión
|
||||||
{
|
yaml["version"] = GameDefaults::VERSION;
|
||||||
|
|
||||||
|
// Window
|
||||||
|
fkyaml::node window_node(fkyaml::node_type::MAPPING);
|
||||||
|
window_node["zoom"] = window.zoom;
|
||||||
|
yaml["window"] = window_node;
|
||||||
|
|
||||||
|
// Video
|
||||||
|
fkyaml::node video_node(fkyaml::node_type::MAPPING);
|
||||||
|
video_node["mode"] = video.fullscreen;
|
||||||
|
video_node["filter"] = static_cast<int>(video.filter);
|
||||||
|
video_node["shaders"] = video.shaders;
|
||||||
|
video_node["vertical_sync"] = video.vertical_sync;
|
||||||
|
video_node["integer_scale"] = video.integer_scale;
|
||||||
|
video_node["keep_aspect"] = video.keep_aspect;
|
||||||
|
video_node["palette"] = video.palette;
|
||||||
|
|
||||||
|
// Video border
|
||||||
|
fkyaml::node border_node(fkyaml::node_type::MAPPING);
|
||||||
|
border_node["enabled"] = video.border.enabled;
|
||||||
|
border_node["width"] = video.border.width;
|
||||||
|
border_node["height"] = video.border.height;
|
||||||
|
video_node["border"] = border_node;
|
||||||
|
|
||||||
|
yaml["video"] = video_node;
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
fkyaml::node controls_node(fkyaml::node_type::MAPPING);
|
||||||
|
controls_node["left"] = static_cast<int>(controls.key_left);
|
||||||
|
controls_node["right"] = static_cast<int>(controls.key_right);
|
||||||
|
controls_node["jump"] = static_cast<int>(controls.key_jump);
|
||||||
|
yaml["controls"] = controls_node;
|
||||||
|
|
||||||
|
// Gamepad controls
|
||||||
|
fkyaml::node gamepad_node(fkyaml::node_type::MAPPING);
|
||||||
|
gamepad_node["left"] = gamepad_controls.button_left;
|
||||||
|
gamepad_node["right"] = gamepad_controls.button_right;
|
||||||
|
gamepad_node["jump"] = gamepad_controls.button_jump;
|
||||||
|
yaml["gamepad_controls"] = gamepad_node;
|
||||||
|
|
||||||
|
// Serializa a string
|
||||||
|
std::string yaml_content = fkyaml::node::serialize(yaml);
|
||||||
|
|
||||||
|
// Abre el fichero para escritura
|
||||||
|
std::ofstream file(config_file_path_);
|
||||||
|
if (!file.is_open()) {
|
||||||
if (console) {
|
if (console) {
|
||||||
std::cerr << "Error: Unable to open file " << file_path << " for writing." << '\n';
|
std::cerr << "Error: Unable to open file " << config_file_path_ << " for writing\n";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (console) {
|
if (console) {
|
||||||
std::cout << file_path << " open for writing" << '\n';
|
std::cout << "Writing config file: " << config_file_path_ << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe en el fichero
|
// Escribe el encabezado con comentarios
|
||||||
file << "# Versión de la configuración\n";
|
file << "# JailDoctor's Dilemma - Configuration File\n";
|
||||||
file << "version " << version << "\n";
|
file << "# This file is automatically generated and managed by the game\n";
|
||||||
|
file << "#\n";
|
||||||
|
file << "# Video filters: 0 = Nearest (pixel perfect), 1 = Linear (smooth)\n";
|
||||||
|
file << "# SDL_Scancode values for keyboard controls (see SDL documentation)\n";
|
||||||
|
file << "# Gamepad button values: 0-20+ = SDL_GamepadButton, 100 = L2, 101 = R2, 200+ = Axes\n";
|
||||||
|
file << "\n";
|
||||||
|
|
||||||
file << "\n## WINDOW\n";
|
// Escribe el contenido YAML
|
||||||
file << "# Zoom de la ventana: 1 = Normal, 2 = Doble, 3 = Triple, ...\n";
|
file << yaml_content;
|
||||||
file << "window.zoom " << window.zoom << "\n";
|
|
||||||
|
|
||||||
file << "\n## VIDEO\n";
|
|
||||||
file << "# Modo de video: 0 = Ventana, 1 = Pantalla completa, 2 = Pantalla completa (escritorio)\n";
|
|
||||||
file << "video.mode " << video.fullscreen << "\n\n";
|
|
||||||
file << "# Filtro de pantalla: 0 = Nearest, 1 = Linear\n";
|
|
||||||
file << "video.filter " << static_cast<int>(video.filter) << "\n\n";
|
|
||||||
file << "# Shaders: 1 = Activado, 0 = Desactivado\n";
|
|
||||||
file << "video.shaders " << boolToString(video.shaders) << "\n\n";
|
|
||||||
file << "# Sincronización vertical: 1 = Activado, 0 = Desactivado\n";
|
|
||||||
file << "video.vertical_sync " << boolToString(video.vertical_sync) << "\n\n";
|
|
||||||
file << "# Escalado entero: 1 = Activado, 0 = Desactivado\n";
|
|
||||||
file << "video.integer_scale " << boolToString(video.integer_scale) << "\n\n";
|
|
||||||
file << "# Mantener aspecto: 1 = Activado, 0 = Desactivado\n";
|
|
||||||
file << "video.keep_aspect " << boolToString(video.keep_aspect) << "\n\n";
|
|
||||||
file << "# Borde: 1 = Activado, 0 = Desactivado\n";
|
|
||||||
file << "video.border.enabled " << boolToString(video.border.enabled) << "\n\n";
|
|
||||||
file << "# Ancho del borde\n";
|
|
||||||
file << "video.border.width " << video.border.width << "\n\n";
|
|
||||||
file << "# Alto del borde\n";
|
|
||||||
file << "video.border.height " << video.border.height << "\n\n";
|
|
||||||
file << "# Paleta\n";
|
|
||||||
file << "video.palette " << video.palette << "\n";
|
|
||||||
|
|
||||||
file << "\n## CONTROLS\n";
|
|
||||||
file << "# Tecla para mover a la izquierda (SDL_Scancode)\n";
|
|
||||||
file << "controls.left " << static_cast<int>(controls.key_left) << "\n\n";
|
|
||||||
file << "# Tecla para mover a la derecha (SDL_Scancode)\n";
|
|
||||||
file << "controls.right " << static_cast<int>(controls.key_right) << "\n\n";
|
|
||||||
file << "# Tecla para saltar (SDL_Scancode)\n";
|
|
||||||
file << "controls.jump " << static_cast<int>(controls.key_jump) << "\n";
|
|
||||||
|
|
||||||
file << "\n## GAMEPAD CONTROLS\n";
|
|
||||||
file << "# Botón del gamepad para mover a la izquierda\n";
|
|
||||||
file << "# Valores: 0-20+ = Botones SDL_GamepadButton, 100 = L2, 101 = R2, 200+ = Ejes\n";
|
|
||||||
file << "gamepad_controls.left " << gamepad_controls.button_left << "\n\n";
|
|
||||||
file << "# Botón del gamepad para mover a la derecha\n";
|
|
||||||
file << "gamepad_controls.right " << gamepad_controls.button_right << "\n\n";
|
|
||||||
file << "# Botón del gamepad para saltar\n";
|
|
||||||
file << "gamepad_controls.jump " << gamepad_controls.button_jump << "\n";
|
|
||||||
|
|
||||||
// Cierra el fichero
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return success;
|
if (console) {
|
||||||
}
|
std::cout << "Config file saved successfully\n\n";
|
||||||
|
|
||||||
auto setOptions(const std::string& var, const std::string& value) -> bool {
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> OPTION_HANDLERS = {
|
|
||||||
{"version", [](const std::string& v) { version = v; }},
|
|
||||||
{"keys", [](const std::string& v) {
|
|
||||||
// Parámetro obsoleto, se ignora silenciosamente para compatibilidad con archivos antiguos
|
|
||||||
(void)v;
|
|
||||||
}},
|
|
||||||
{"window.zoom", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, GameDefaults::WINDOW_ZOOM);
|
|
||||||
if (val > 0) {
|
|
||||||
window.zoom = val;
|
|
||||||
} else {
|
|
||||||
window.zoom = GameDefaults::WINDOW_ZOOM;
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{"video.mode", [](const std::string& v) { video.fullscreen = stringToBool(v); }},
|
|
||||||
{"video.filter", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, static_cast<int>(GameDefaults::VIDEO_FILTER));
|
|
||||||
if (val == static_cast<int>(Screen::Filter::NEAREST) || val == static_cast<int>(Screen::Filter::LINEAR)) {
|
|
||||||
video.filter = static_cast<Screen::Filter>(val);
|
|
||||||
} else {
|
|
||||||
video.filter = GameDefaults::VIDEO_FILTER;
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{"video.shaders", [](const std::string& v) { video.shaders = stringToBool(v); }},
|
|
||||||
{"video.vertical_sync", [](const std::string& v) { video.vertical_sync = stringToBool(v); }},
|
|
||||||
{"video.integer_scale", [](const std::string& v) { video.integer_scale = stringToBool(v); }},
|
|
||||||
{"video.keep_aspect", [](const std::string& v) { video.keep_aspect = stringToBool(v); }},
|
|
||||||
{"video.border.enabled", [](const std::string& v) { video.border.enabled = stringToBool(v); }},
|
|
||||||
{"video.border.width", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, GameDefaults::BORDER_WIDTH);
|
|
||||||
if (val > 0) {
|
|
||||||
video.border.width = val;
|
|
||||||
} else {
|
|
||||||
video.border.width = GameDefaults::BORDER_WIDTH;
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{"video.border.height", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, GameDefaults::BORDER_HEIGHT);
|
|
||||||
if (val > 0) {
|
|
||||||
video.border.height = val;
|
|
||||||
} else {
|
|
||||||
video.border.height = GameDefaults::BORDER_HEIGHT;
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{"video.palette", [](const std::string& v) {
|
|
||||||
video.palette = v;
|
|
||||||
}},
|
|
||||||
{"controls.left", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, SDL_SCANCODE_LEFT);
|
|
||||||
controls.key_left = static_cast<SDL_Scancode>(val);
|
|
||||||
}},
|
|
||||||
{"controls.right", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, SDL_SCANCODE_RIGHT);
|
|
||||||
controls.key_right = static_cast<SDL_Scancode>(val);
|
|
||||||
}},
|
|
||||||
{"controls.jump", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, SDL_SCANCODE_UP);
|
|
||||||
controls.key_jump = static_cast<SDL_Scancode>(val);
|
|
||||||
}},
|
|
||||||
{"gamepad_controls.left", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_LEFT));
|
|
||||||
gamepad_controls.button_left = val;
|
|
||||||
}},
|
|
||||||
{"gamepad_controls.right", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_RIGHT));
|
|
||||||
gamepad_controls.button_right = val;
|
|
||||||
}},
|
|
||||||
{"gamepad_controls.jump", [](const std::string& v) {
|
|
||||||
int val = safeStoi(v, static_cast<int>(SDL_GAMEPAD_BUTTON_WEST));
|
|
||||||
gamepad_controls.button_jump = val;
|
|
||||||
}}};
|
|
||||||
|
|
||||||
auto it = OPTION_HANDLERS.find(var);
|
|
||||||
if (it != OPTION_HANDLERS.end()) {
|
|
||||||
it->second(value);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Options
|
} // namespace Options
|
||||||
@@ -258,9 +258,13 @@ inline Audio audio{}; // Opciones relativas al audio
|
|||||||
inline ControlScheme controls{}; // Teclas usadas para jugar
|
inline ControlScheme controls{}; // Teclas usadas para jugar
|
||||||
inline GamepadControlScheme gamepad_controls{}; // Botones del gamepad usados para jugar
|
inline GamepadControlScheme gamepad_controls{}; // Botones del gamepad usados para jugar
|
||||||
|
|
||||||
|
// Ruta completa del fichero de configuración (establecida mediante setConfigFile)
|
||||||
|
inline std::string config_file_path_{};
|
||||||
|
|
||||||
// --- Funciones ---
|
// --- Funciones ---
|
||||||
void init(); // Crea e inicializa las opciones del programa
|
void init(); // Crea e inicializa las opciones del programa
|
||||||
auto loadFromFile(const std::string& file_path) -> bool; // Carga las opciones desde un fichero
|
void setConfigFile(const std::string& path); // Establece la ruta del fichero de configuración
|
||||||
auto saveToFile(const std::string& file_path) -> bool; // Guarda las opciones a un fichero
|
auto loadFromFile() -> bool; // Carga las opciones desde el fichero configurado
|
||||||
|
auto saveToFile() -> bool; // Guarda las opciones al fichero configurado
|
||||||
|
|
||||||
} // namespace Options
|
} // namespace Options
|
||||||
@@ -45,7 +45,7 @@ Title::Title()
|
|||||||
initMarquee(); // Inicializa la marquesina
|
initMarquee(); // Inicializa la marquesina
|
||||||
createCheevosTexture(); // Crea y rellena la textura para mostrar los logros
|
createCheevosTexture(); // Crea y rellena la textura para mostrar los logros
|
||||||
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); // Cambia el color del borde
|
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); // Cambia el color del borde
|
||||||
Audio::get()->playMusic("title.ogg"); // Inicia la musica
|
Audio::get()->playMusic("title.ogg"); // Inicia la musica
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa la marquesina
|
// Inicializa la marquesina
|
||||||
@@ -653,7 +653,7 @@ void Title::applyKeyboardRemap() {
|
|||||||
Input::get()->applyKeyboardBindingsFromOptions();
|
Input::get()->applyKeyboardBindingsFromOptions();
|
||||||
|
|
||||||
// Guardar a archivo de configuracion
|
// Guardar a archivo de configuracion
|
||||||
Options::saveToFile(Resource::List::get()->get("config.txt"));
|
Options::saveToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja la pantalla de redefinir teclado
|
// Dibuja la pantalla de redefinir teclado
|
||||||
@@ -836,7 +836,7 @@ void Title::applyJoystickRemap() {
|
|||||||
Input::get()->applyGamepadBindingsFromOptions();
|
Input::get()->applyGamepadBindingsFromOptions();
|
||||||
|
|
||||||
// Guardar a archivo de configuracion
|
// Guardar a archivo de configuracion
|
||||||
Options::saveToFile(Resource::List::get()->get("config.txt"));
|
Options::saveToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retorna el nombre amigable del botón del gamepad
|
// Retorna el nombre amigable del botón del gamepad
|
||||||
|
|||||||
Reference in New Issue
Block a user