refactor: eliminar Options::physics/audio/gameplay (codi mort)
Aquestes tres seccions s'estaven carregant del YAML, parsejant, validant i escrivint, però cap d'elles tenia consumidor en runtime: - Options::physics: l'únic call-site era un std::cout informatiu a director.cpp:109. Ship/Enemy/Bullet llegeixen Defaults::Physics directament. - Options::audio: explícitament desacoblat (audio.hpp:22-25) — la font de configuració era Defaults::Audio via Audio::Config. - Options::gameplay: zero readers. Els arrays són compile-time. Esborrats: - Structs Physics/Gameplay/Music/Sound/Audio i les globals. - Defaults a init(), helpers loadXxxConfigFromYaml, secció escrita a saveToFile, crides al loadFromFile. - La línia "Física: rotation=..." del console output del Director. Es manté Options::window i Options::rendering (sí utilitzats). Hallazgo #21 de CODE_REVIEW.md (opció a: borrar). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,10 +9,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "debug_overlay.hpp"
|
|
||||||
#include "scene.hpp"
|
|
||||||
#include "scene_context.hpp"
|
|
||||||
#include "global_events.hpp"
|
|
||||||
#include "core/audio/audio.hpp"
|
#include "core/audio/audio.hpp"
|
||||||
#include "core/audio/audio_adapter.hpp"
|
#include "core/audio/audio_adapter.hpp"
|
||||||
#include "core/defaults.hpp"
|
#include "core/defaults.hpp"
|
||||||
@@ -22,11 +18,15 @@
|
|||||||
#include "core/resources/resource_helper.hpp"
|
#include "core/resources/resource_helper.hpp"
|
||||||
#include "core/resources/resource_loader.hpp"
|
#include "core/resources/resource_loader.hpp"
|
||||||
#include "core/utils/path_utils.hpp"
|
#include "core/utils/path_utils.hpp"
|
||||||
|
#include "debug_overlay.hpp"
|
||||||
|
#include "game/options.hpp"
|
||||||
#include "game/scenes/game_scene.hpp"
|
#include "game/scenes/game_scene.hpp"
|
||||||
#include "game/scenes/logo_scene.hpp"
|
#include "game/scenes/logo_scene.hpp"
|
||||||
#include "game/scenes/title_scene.hpp"
|
#include "game/scenes/title_scene.hpp"
|
||||||
#include "game/options.hpp"
|
#include "global_events.hpp"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
#include "scene.hpp"
|
||||||
|
#include "scene_context.hpp"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@@ -106,8 +106,6 @@ Director::Director(std::vector<std::string> const& args) {
|
|||||||
std::cout << "Configuración carregada\n";
|
std::cout << "Configuración carregada\n";
|
||||||
std::cout << " Finestra: " << Options::window.width << "×"
|
std::cout << " Finestra: " << Options::window.width << "×"
|
||||||
<< Options::window.height << '\n';
|
<< Options::window.height << '\n';
|
||||||
std::cout << " Física: rotation=" << Options::physics.rotation_speed
|
|
||||||
<< " rad/s\n";
|
|
||||||
std::cout << " Input: " << Input::get()->getNumGamepads()
|
std::cout << " Input: " << Input::get()->getNumGamepads()
|
||||||
<< " gamepad(s) detectat(s)\n";
|
<< " gamepad(s) detectat(s)\n";
|
||||||
}
|
}
|
||||||
@@ -291,8 +289,7 @@ auto Director::buildScene(SceneType type, SDLManager& sdl, SceneContext& context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Director::runFrameLoop(Scene& scene, SDLManager& sdl, SceneContext& context,
|
void Director::runFrameLoop(Scene& scene, SDLManager& sdl, SceneContext& context, System::DebugOverlay& debug_overlay) {
|
||||||
System::DebugOverlay& debug_overlay) {
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
Uint64 last_time = SDL_GetTicks();
|
Uint64 last_time = SDL_GetTicks();
|
||||||
|
|
||||||
@@ -315,8 +312,7 @@ void Director::runFrameLoop(Scene& scene, SDLManager& sdl, SceneContext& context
|
|||||||
if (GlobalEvents::handle(event, sdl, context)) {
|
if (GlobalEvents::handle(event, sdl, context)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_F11) {
|
||||||
&& event.key.scancode == SDL_SCANCODE_F11) {
|
|
||||||
debug_overlay.toggle();
|
debug_overlay.toggle();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-188
@@ -11,10 +11,10 @@
|
|||||||
|
|
||||||
namespace Options {
|
namespace Options {
|
||||||
|
|
||||||
// ========== FUNCIONS AUXILIARS PER CONVERSIÓ DE CONTROLES ==========
|
// ========== FUNCIONS AUXILIARS PER CONVERSIÓ DE CONTROLES ==========
|
||||||
|
|
||||||
// Mapa de SDL_Scancode a string
|
// Mapa de SDL_Scancode a string
|
||||||
static const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
|
static const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
|
||||||
{SDL_SCANCODE_A, "A"},
|
{SDL_SCANCODE_A, "A"},
|
||||||
{SDL_SCANCODE_B, "B"},
|
{SDL_SCANCODE_B, "B"},
|
||||||
{SDL_SCANCODE_C, "C"},
|
{SDL_SCANCODE_C, "C"},
|
||||||
@@ -67,8 +67,8 @@ static const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING =
|
|||||||
{SDL_SCANCODE_LALT, "LALT"},
|
{SDL_SCANCODE_LALT, "LALT"},
|
||||||
{SDL_SCANCODE_RALT, "RALT"}};
|
{SDL_SCANCODE_RALT, "RALT"}};
|
||||||
|
|
||||||
// Mapa invers: string a SDL_Scancode
|
// Mapa invers: string a SDL_Scancode
|
||||||
static const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
|
static const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
|
||||||
{"A", SDL_SCANCODE_A},
|
{"A", SDL_SCANCODE_A},
|
||||||
{"B", SDL_SCANCODE_B},
|
{"B", SDL_SCANCODE_B},
|
||||||
{"C", SDL_SCANCODE_C},
|
{"C", SDL_SCANCODE_C},
|
||||||
@@ -121,8 +121,8 @@ static const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE =
|
|||||||
{"LALT", SDL_SCANCODE_LALT},
|
{"LALT", SDL_SCANCODE_LALT},
|
||||||
{"RALT", SDL_SCANCODE_RALT}};
|
{"RALT", SDL_SCANCODE_RALT}};
|
||||||
|
|
||||||
// Mapa de botó de gamepad (int) a string
|
// Mapa de botó de gamepad (int) a string
|
||||||
static const std::unordered_map<int, std::string> BUTTON_TO_STRING = {
|
static const std::unordered_map<int, std::string> BUTTON_TO_STRING = {
|
||||||
{SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"}, // A (Xbox), Cross (PS)
|
{SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"}, // A (Xbox), Cross (PS)
|
||||||
{SDL_GAMEPAD_BUTTON_EAST, "EAST"}, // B (Xbox), Circle (PS)
|
{SDL_GAMEPAD_BUTTON_EAST, "EAST"}, // B (Xbox), Circle (PS)
|
||||||
{SDL_GAMEPAD_BUTTON_WEST, "WEST"}, // X (Xbox), Square (PS)
|
{SDL_GAMEPAD_BUTTON_WEST, "WEST"}, // X (Xbox), Square (PS)
|
||||||
@@ -137,10 +137,10 @@ static const std::unordered_map<int, std::string> BUTTON_TO_STRING = {
|
|||||||
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
||||||
{100, "L2_AS_BUTTON"}, // Trigger L2 como a botó digital
|
{100, "L2_AS_BUTTON"}, // Trigger L2 como a botó digital
|
||||||
{101, "R2_AS_BUTTON"} // Trigger R2 como a botó digital
|
{101, "R2_AS_BUTTON"} // Trigger R2 como a botó digital
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mapa invers: string a botó de gamepad
|
// Mapa invers: string a botó de gamepad
|
||||||
static const std::unordered_map<std::string, int> STRING_TO_BUTTON = {
|
static const std::unordered_map<std::string, int> STRING_TO_BUTTON = {
|
||||||
{"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH},
|
{"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH},
|
||||||
{"EAST", SDL_GAMEPAD_BUTTON_EAST},
|
{"EAST", SDL_GAMEPAD_BUTTON_EAST},
|
||||||
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
||||||
@@ -156,30 +156,30 @@ static const std::unordered_map<std::string, int> STRING_TO_BUTTON = {
|
|||||||
{"L2_AS_BUTTON", 100},
|
{"L2_AS_BUTTON", 100},
|
||||||
{"R2_AS_BUTTON", 101}};
|
{"R2_AS_BUTTON", 101}};
|
||||||
|
|
||||||
static auto scancodeToString(SDL_Scancode code) -> std::string {
|
static auto scancodeToString(SDL_Scancode code) -> std::string {
|
||||||
auto it = SCANCODE_TO_STRING.find(code);
|
auto it = SCANCODE_TO_STRING.find(code);
|
||||||
return (it != SCANCODE_TO_STRING.end()) ? it->second : "UNKNOWN";
|
return (it != SCANCODE_TO_STRING.end()) ? it->second : "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto stringToScancode(const std::string& str) -> SDL_Scancode {
|
static auto stringToScancode(const std::string& str) -> SDL_Scancode {
|
||||||
auto it = STRING_TO_SCANCODE.find(str);
|
auto it = STRING_TO_SCANCODE.find(str);
|
||||||
return (it != STRING_TO_SCANCODE.end()) ? it->second : SDL_SCANCODE_UNKNOWN;
|
return (it != STRING_TO_SCANCODE.end()) ? it->second : SDL_SCANCODE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto buttonToString(int button) -> std::string {
|
static auto buttonToString(int button) -> std::string {
|
||||||
auto it = BUTTON_TO_STRING.find(button);
|
auto it = BUTTON_TO_STRING.find(button);
|
||||||
return (it != BUTTON_TO_STRING.end()) ? it->second : "UNKNOWN";
|
return (it != BUTTON_TO_STRING.end()) ? it->second : "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto stringToButton(const std::string& str) -> int {
|
static auto stringToButton(const std::string& str) -> int {
|
||||||
auto it = STRING_TO_BUTTON.find(str);
|
auto it = STRING_TO_BUTTON.find(str);
|
||||||
return (it != STRING_TO_BUTTON.end()) ? it->second : SDL_GAMEPAD_BUTTON_INVALID;
|
return (it != STRING_TO_BUTTON.end()) ? it->second : SDL_GAMEPAD_BUTTON_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== FI FUNCIONS AUXILIARS ==========
|
// ========== FI FUNCIONS AUXILIARS ==========
|
||||||
|
|
||||||
// Inicialitzar opciones con valors per defecte de Defaults::
|
// Inicialitzar opciones con valors per defecte de Defaults::
|
||||||
void init() {
|
void init() {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
console = true;
|
console = true;
|
||||||
#else
|
#else
|
||||||
@@ -192,44 +192,23 @@ void init() {
|
|||||||
window.fullscreen = Defaults::Window::FULLSCREEN;
|
window.fullscreen = Defaults::Window::FULLSCREEN;
|
||||||
window.zoom_factor = Defaults::Window::BASE_ZOOM;
|
window.zoom_factor = Defaults::Window::BASE_ZOOM;
|
||||||
|
|
||||||
// Physics
|
|
||||||
physics.rotation_speed = Defaults::Physics::ROTATION_SPEED;
|
|
||||||
physics.acceleration = Defaults::Physics::ACCELERATION;
|
|
||||||
physics.max_velocity = Defaults::Physics::MAX_VELOCITY;
|
|
||||||
physics.friction = Defaults::Physics::FRICTION;
|
|
||||||
physics.enemy_speed = Defaults::Physics::ENEMY_SPEED;
|
|
||||||
physics.bullet_speed = Defaults::Physics::BULLET_SPEED;
|
|
||||||
|
|
||||||
// Gameplay
|
|
||||||
gameplay.max_enemies = Defaults::Entities::MAX_ORNIS;
|
|
||||||
gameplay.max_bullets = Defaults::Entities::MAX_BALES;
|
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
rendering.vsync = Defaults::Rendering::VSYNC_DEFAULT;
|
rendering.vsync = Defaults::Rendering::VSYNC_DEFAULT;
|
||||||
|
|
||||||
// Audio
|
|
||||||
audio.enabled = Defaults::Audio::ENABLED;
|
|
||||||
audio.volume = Defaults::Audio::VOLUME;
|
|
||||||
audio.music.enabled = Defaults::Audio::MUSIC_ENABLED;
|
|
||||||
audio.music.volume = Defaults::Audio::MUSIC_VOLUME;
|
|
||||||
audio.sound.enabled = Defaults::Audio::SOUND_ENABLED;
|
|
||||||
audio.sound.volume = Defaults::Audio::SOUND_VOLUME;
|
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
version = std::string(Project::VERSION);
|
version = std::string(Project::VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establir la ruta del file de configuración
|
// Establir la ruta del file de configuración
|
||||||
void setConfigFile(const std::string& path) { config_file_path = path; }
|
void setConfigFile(const std::string& path) { config_file_path = path; }
|
||||||
|
|
||||||
// Funciones auxiliars per load seccions del YAML
|
// Funciones auxiliars per load seccions del YAML
|
||||||
|
|
||||||
// Lee un campo escalar del YAML aplicando un validador; si la clau no
|
// Lee un campo escalar del YAML aplicando un validador; si la clau no
|
||||||
// existe, deja `dest` intacto; si la conversió o la validació fallen,
|
// existe, deja `dest` intacto; si la conversió o la validació fallen,
|
||||||
// asigna `fallback`. Estàtic per quedar dins de la unitat de traducció.
|
// asigna `fallback`. Estàtic per quedar dins de la unitat de traducció.
|
||||||
template <typename T, typename Validator>
|
template <typename T, typename Validator>
|
||||||
static void readField(const fkyaml::node& parent, const char* key, T& dest,
|
static void readField(const fkyaml::node& parent, const char* key, T& dest, T fallback, Validator&& validate) {
|
||||||
T fallback, Validator&& validate) {
|
|
||||||
if (!parent.contains(key)) {
|
if (!parent.contains(key)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -239,11 +218,11 @@ static void readField(const fkyaml::node& parent, const char* key, T& dest,
|
|||||||
} catch (...) {
|
} catch (...) {
|
||||||
dest = fallback;
|
dest = fallback;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variant sin validador: només lectura amb fallback en cas d'error.
|
// Variant sin validador: només lectura amb fallback en cas d'error.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void readField(const fkyaml::node& parent, const char* key, T& dest, T fallback) {
|
static void readField(const fkyaml::node& parent, const char* key, T& dest, T fallback) {
|
||||||
if (!parent.contains(key)) {
|
if (!parent.contains(key)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -252,72 +231,28 @@ static void readField(const fkyaml::node& parent, const char* key, T& dest, T fa
|
|||||||
} catch (...) {
|
} catch (...) {
|
||||||
dest = fallback;
|
dest = fallback;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
|
static void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
|
||||||
if (!yaml.contains("window")) {
|
if (!yaml.contains("window")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& win = yaml["window"];
|
const auto& win = yaml["window"];
|
||||||
|
|
||||||
readField(win, "width", window.width, Defaults::Window::WIDTH,
|
readField(win, "width", window.width, Defaults::Window::WIDTH, [](int v) { return v >= Defaults::Window::MIN_WIDTH; });
|
||||||
[](int v) { return v >= Defaults::Window::MIN_WIDTH; });
|
readField(win, "height", window.height, Defaults::Window::HEIGHT, [](int v) { return v >= Defaults::Window::MIN_HEIGHT; });
|
||||||
readField(win, "height", window.height, Defaults::Window::HEIGHT,
|
|
||||||
[](int v) { return v >= Defaults::Window::MIN_HEIGHT; });
|
|
||||||
readField(win, "fullscreen", window.fullscreen, false);
|
readField(win, "fullscreen", window.fullscreen, false);
|
||||||
|
|
||||||
if (win.contains("zoom_factor")) {
|
if (win.contains("zoom_factor")) {
|
||||||
readField(win, "zoom_factor", window.zoom_factor, Defaults::Window::BASE_ZOOM,
|
readField(win, "zoom_factor", window.zoom_factor, Defaults::Window::BASE_ZOOM, [](float v) { return v >= Defaults::Window::MIN_ZOOM && v <= 10.0F; });
|
||||||
[](float v) { return v >= Defaults::Window::MIN_ZOOM && v <= 10.0F; });
|
|
||||||
} else {
|
} else {
|
||||||
// Legacy config: infer zoom from width
|
// Legacy config: infer zoom from width
|
||||||
window.zoom_factor = static_cast<float>(window.width) / Defaults::Window::WIDTH;
|
window.zoom_factor = static_cast<float>(window.width) / Defaults::Window::WIDTH;
|
||||||
window.zoom_factor = std::max(Defaults::Window::MIN_ZOOM, window.zoom_factor);
|
window.zoom_factor = std::max(Defaults::Window::MIN_ZOOM, window.zoom_factor);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void loadPhysicsConfigFromYaml(const fkyaml::node& yaml) {
|
|
||||||
if (!yaml.contains("physics")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto& phys = yaml["physics"];
|
|
||||||
constexpr auto POSITIVE = [](float v) { return v > 0.0F; };
|
|
||||||
|
|
||||||
readField(phys, "rotation_speed", physics.rotation_speed, Defaults::Physics::ROTATION_SPEED, POSITIVE);
|
|
||||||
readField(phys, "acceleration", physics.acceleration, Defaults::Physics::ACCELERATION, POSITIVE);
|
|
||||||
readField(phys, "max_velocity", physics.max_velocity, Defaults::Physics::MAX_VELOCITY, POSITIVE);
|
|
||||||
readField(phys, "friction", physics.friction, Defaults::Physics::FRICTION, POSITIVE);
|
|
||||||
readField(phys, "enemy_speed", physics.enemy_speed, Defaults::Physics::ENEMY_SPEED, POSITIVE);
|
|
||||||
readField(phys, "bullet_speed", physics.bullet_speed, Defaults::Physics::BULLET_SPEED, POSITIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void loadGameplayConfigFromYaml(const fkyaml::node& yaml) {
|
|
||||||
if (yaml.contains("gameplay")) {
|
|
||||||
const auto& game = yaml["gameplay"];
|
|
||||||
|
|
||||||
if (game.contains("max_enemies")) {
|
|
||||||
try {
|
|
||||||
auto val = game["max_enemies"].get_value<int>();
|
|
||||||
gameplay.max_enemies =
|
|
||||||
(val > 0 && val <= 50) ? val : Defaults::Entities::MAX_ORNIS;
|
|
||||||
} catch (...) {
|
|
||||||
gameplay.max_enemies = Defaults::Entities::MAX_ORNIS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.contains("max_bullets")) {
|
static void loadRenderingConfigFromYaml(const fkyaml::node& yaml) {
|
||||||
try {
|
|
||||||
auto val = game["max_bullets"].get_value<int>();
|
|
||||||
gameplay.max_bullets =
|
|
||||||
(val > 0 && val <= 10) ? val : Defaults::Entities::MAX_BALES;
|
|
||||||
} catch (...) {
|
|
||||||
gameplay.max_bullets = Defaults::Entities::MAX_BALES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void loadRenderingConfigFromYaml(const fkyaml::node& yaml) {
|
|
||||||
if (yaml.contains("rendering")) {
|
if (yaml.contains("rendering")) {
|
||||||
const auto& rend = yaml["rendering"];
|
const auto& rend = yaml["rendering"];
|
||||||
|
|
||||||
@@ -331,45 +266,10 @@ static void loadRenderingConfigFromYaml(const fkyaml::node& yaml) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void loadAudioMusicSection(const fkyaml::node& aud) {
|
|
||||||
if (!aud.contains("music")) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const auto& mus = aud["music"];
|
|
||||||
constexpr auto UNIT_RANGE = [](float v) { return v >= 0.0F && v <= 1.0F; };
|
|
||||||
|
|
||||||
readField(mus, "enabled", audio.music.enabled, Defaults::Audio::MUSIC_ENABLED);
|
// Carregar controls del player 1 desde YAML
|
||||||
readField(mus, "volume", audio.music.volume, Defaults::Audio::MUSIC_VOLUME, UNIT_RANGE);
|
static void loadPlayer1ControlsFromYaml(const fkyaml::node& yaml) {
|
||||||
}
|
|
||||||
|
|
||||||
static void loadAudioSoundSection(const fkyaml::node& aud) {
|
|
||||||
if (!aud.contains("sound")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto& snd = aud["sound"];
|
|
||||||
constexpr auto UNIT_RANGE = [](float v) { return v >= 0.0F && v <= 1.0F; };
|
|
||||||
|
|
||||||
readField(snd, "enabled", audio.sound.enabled, Defaults::Audio::SOUND_ENABLED);
|
|
||||||
readField(snd, "volume", audio.sound.volume, Defaults::Audio::SOUND_VOLUME, UNIT_RANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void loadAudioConfigFromYaml(const fkyaml::node& yaml) {
|
|
||||||
if (!yaml.contains("audio")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto& aud = yaml["audio"];
|
|
||||||
constexpr auto UNIT_RANGE = [](float v) { return v >= 0.0F && v <= 1.0F; };
|
|
||||||
|
|
||||||
readField(aud, "enabled", audio.enabled, Defaults::Audio::ENABLED);
|
|
||||||
readField(aud, "volume", audio.volume, Defaults::Audio::VOLUME, UNIT_RANGE);
|
|
||||||
loadAudioMusicSection(aud);
|
|
||||||
loadAudioSoundSection(aud);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carregar controls del player 1 desde YAML
|
|
||||||
static void loadPlayer1ControlsFromYaml(const fkyaml::node& yaml) {
|
|
||||||
if (!yaml.contains("player1")) {
|
if (!yaml.contains("player1")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -414,10 +314,10 @@ static void loadPlayer1ControlsFromYaml(const fkyaml::node& yaml) {
|
|||||||
if (p1.contains("gamepad_name")) {
|
if (p1.contains("gamepad_name")) {
|
||||||
player1.gamepad_name = p1["gamepad_name"].get_value<std::string>();
|
player1.gamepad_name = p1["gamepad_name"].get_value<std::string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carregar controls del player 2 desde YAML
|
// Carregar controls del player 2 desde YAML
|
||||||
static void loadPlayer2ControlsFromYaml(const fkyaml::node& yaml) {
|
static void loadPlayer2ControlsFromYaml(const fkyaml::node& yaml) {
|
||||||
if (!yaml.contains("player2")) {
|
if (!yaml.contains("player2")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -462,10 +362,10 @@ static void loadPlayer2ControlsFromYaml(const fkyaml::node& yaml) {
|
|||||||
if (p2.contains("gamepad_name")) {
|
if (p2.contains("gamepad_name")) {
|
||||||
player2.gamepad_name = p2["gamepad_name"].get_value<std::string>();
|
player2.gamepad_name = p2["gamepad_name"].get_value<std::string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carregar configuración des del file YAML
|
// Carregar configuración des del file YAML
|
||||||
auto loadFromFile() -> bool {
|
auto loadFromFile() -> bool {
|
||||||
const std::string CONFIG_VERSION = std::string(Project::VERSION);
|
const std::string CONFIG_VERSION = std::string(Project::VERSION);
|
||||||
|
|
||||||
std::ifstream file(config_file_path);
|
std::ifstream file(config_file_path);
|
||||||
@@ -507,10 +407,7 @@ auto loadFromFile() -> bool {
|
|||||||
|
|
||||||
// Carregar seccions
|
// Carregar seccions
|
||||||
loadWindowConfigFromYaml(yaml);
|
loadWindowConfigFromYaml(yaml);
|
||||||
loadPhysicsConfigFromYaml(yaml);
|
|
||||||
loadGameplayConfigFromYaml(yaml);
|
|
||||||
loadRenderingConfigFromYaml(yaml);
|
loadRenderingConfigFromYaml(yaml);
|
||||||
loadAudioConfigFromYaml(yaml);
|
|
||||||
loadPlayer1ControlsFromYaml(yaml);
|
loadPlayer1ControlsFromYaml(yaml);
|
||||||
loadPlayer2ControlsFromYaml(yaml);
|
loadPlayer2ControlsFromYaml(yaml);
|
||||||
|
|
||||||
@@ -531,10 +428,10 @@ auto loadFromFile() -> bool {
|
|||||||
saveToFile();
|
saveToFile();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guardar controls del player 1 a YAML
|
// Guardar controls del player 1 a YAML
|
||||||
static void savePlayer1ControlsToYaml(std::ofstream& file) {
|
static void savePlayer1ControlsToYaml(std::ofstream& file) {
|
||||||
file << "# CONTROLS JUGADOR 1\n";
|
file << "# CONTROLS JUGADOR 1\n";
|
||||||
file << "player1:\n";
|
file << "player1:\n";
|
||||||
file << " keyboard:\n";
|
file << " keyboard:\n";
|
||||||
@@ -548,10 +445,10 @@ static void savePlayer1ControlsToYaml(std::ofstream& file) {
|
|||||||
file << " button_thrust: " << buttonToString(player1.gamepad.button_thrust) << "\n";
|
file << " button_thrust: " << buttonToString(player1.gamepad.button_thrust) << "\n";
|
||||||
file << " button_shoot: " << buttonToString(player1.gamepad.button_shoot) << "\n";
|
file << " button_shoot: " << buttonToString(player1.gamepad.button_shoot) << "\n";
|
||||||
file << " gamepad_name: \"" << player1.gamepad_name << "\" # Buit = primer disponible\n\n";
|
file << " gamepad_name: \"" << player1.gamepad_name << "\" # Buit = primer disponible\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guardar controls del player 2 a YAML
|
// Guardar controls del player 2 a YAML
|
||||||
static void savePlayer2ControlsToYaml(std::ofstream& file) {
|
static void savePlayer2ControlsToYaml(std::ofstream& file) {
|
||||||
file << "# CONTROLS JUGADOR 2\n";
|
file << "# CONTROLS JUGADOR 2\n";
|
||||||
file << "player2:\n";
|
file << "player2:\n";
|
||||||
file << " keyboard:\n";
|
file << " keyboard:\n";
|
||||||
@@ -565,10 +462,10 @@ static void savePlayer2ControlsToYaml(std::ofstream& file) {
|
|||||||
file << " button_thrust: " << buttonToString(player2.gamepad.button_thrust) << "\n";
|
file << " button_thrust: " << buttonToString(player2.gamepad.button_thrust) << "\n";
|
||||||
file << " button_shoot: " << buttonToString(player2.gamepad.button_shoot) << "\n";
|
file << " button_shoot: " << buttonToString(player2.gamepad.button_shoot) << "\n";
|
||||||
file << " gamepad_name: \"" << player2.gamepad_name << "\" # Buit = segon disponible\n\n";
|
file << " gamepad_name: \"" << player2.gamepad_name << "\" # Buit = segon disponible\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guardar configuración al file YAML
|
// Guardar configuración al file YAML
|
||||||
auto saveToFile() -> bool {
|
auto saveToFile() -> bool {
|
||||||
std::ofstream file(config_file_path);
|
std::ofstream file(config_file_path);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
if (console) {
|
if (console) {
|
||||||
@@ -592,37 +489,10 @@ auto saveToFile() -> bool {
|
|||||||
file << " fullscreen: " << (window.fullscreen ? "true" : "false") << "\n";
|
file << " fullscreen: " << (window.fullscreen ? "true" : "false") << "\n";
|
||||||
file << " zoom_factor: " << window.zoom_factor << " # 0.5x-max (0.1 increments)\n\n";
|
file << " zoom_factor: " << window.zoom_factor << " # 0.5x-max (0.1 increments)\n\n";
|
||||||
|
|
||||||
file << "# FÍSICA (todos los valors en px/s, rad/s, etc.)\n";
|
|
||||||
file << "physics:\n";
|
|
||||||
file << " rotation_speed: " << physics.rotation_speed << " # rad/s\n";
|
|
||||||
file << " acceleration: " << physics.acceleration << " # px/s²\n";
|
|
||||||
file << " max_velocity: " << physics.max_velocity << " # px/s\n";
|
|
||||||
file << " friction: " << physics.friction << " # px/s²\n";
|
|
||||||
file << " enemy_speed: " << physics.enemy_speed
|
|
||||||
<< " # unitats/frame\n";
|
|
||||||
file << " bullet_speed: " << physics.bullet_speed
|
|
||||||
<< " # unitats/frame\n\n";
|
|
||||||
|
|
||||||
file << "# GAMEPLAY\n";
|
|
||||||
file << "gameplay:\n";
|
|
||||||
file << " max_enemies: " << gameplay.max_enemies << "\n";
|
|
||||||
file << " max_bullets: " << gameplay.max_bullets << "\n\n";
|
|
||||||
|
|
||||||
file << "# RENDERITZACIÓ\n";
|
file << "# RENDERITZACIÓ\n";
|
||||||
file << "rendering:\n";
|
file << "rendering:\n";
|
||||||
file << " vsync: " << rendering.vsync << " # 0=disabled, 1=enabled\n\n";
|
file << " vsync: " << rendering.vsync << " # 0=disabled, 1=enabled\n\n";
|
||||||
|
|
||||||
file << "# AUDIO\n";
|
|
||||||
file << "audio:\n";
|
|
||||||
file << " enabled: " << (audio.enabled ? "true" : "false") << "\n";
|
|
||||||
file << " volume: " << audio.volume << " # 0.0 to 1.0\n";
|
|
||||||
file << " music:\n";
|
|
||||||
file << " enabled: " << (audio.music.enabled ? "true" : "false") << "\n";
|
|
||||||
file << " volume: " << audio.music.volume << " # 0.0 to 1.0\n";
|
|
||||||
file << " sound:\n";
|
|
||||||
file << " enabled: " << (audio.sound.enabled ? "true" : "false") << "\n";
|
|
||||||
file << " volume: " << audio.sound.volume << " # 0.0 to 1.0\n\n";
|
|
||||||
|
|
||||||
// Guardar controls de jugadors
|
// Guardar controls de jugadors
|
||||||
savePlayer1ControlsToYaml(file);
|
savePlayer1ControlsToYaml(file);
|
||||||
savePlayer2ControlsToYaml(file);
|
savePlayer2ControlsToYaml(file);
|
||||||
@@ -634,6 +504,6 @@ auto saveToFile() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Options
|
} // namespace Options
|
||||||
|
|||||||
+31
-65
@@ -6,85 +6,51 @@
|
|||||||
|
|
||||||
namespace Options {
|
namespace Options {
|
||||||
|
|
||||||
// Estructures de configuración
|
// Estructures de configuración
|
||||||
|
|
||||||
struct Window {
|
struct Window {
|
||||||
int width{1280};
|
int width{1280};
|
||||||
int height{720};
|
int height{720};
|
||||||
bool fullscreen{false};
|
bool fullscreen{false};
|
||||||
float zoom_factor{1.0F}; // Zoom level (0.5x to max_zoom)
|
float zoom_factor{1.0F}; // Zoom level (0.5x to max_zoom)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Physics {
|
struct Rendering {
|
||||||
float rotation_speed{3.14F}; // rad/s
|
|
||||||
float acceleration{400.0F}; // px/s²
|
|
||||||
float max_velocity{120.0F}; // px/s
|
|
||||||
float friction{20.0F}; // px/s²
|
|
||||||
float enemy_speed{2.0F}; // unitats/frame
|
|
||||||
float bullet_speed{6.0F}; // unitats/frame
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Gameplay {
|
|
||||||
int max_enemies{15};
|
|
||||||
int max_bullets{3};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Rendering {
|
|
||||||
int vsync{1}; // 0=disabled, 1=enabled
|
int vsync{1}; // 0=disabled, 1=enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Music {
|
// Controles de jugadors
|
||||||
bool enabled{true};
|
|
||||||
float volume{0.8F};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Sound {
|
struct KeyboardControls {
|
||||||
bool enabled{true};
|
|
||||||
float volume{1.0F};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Audio {
|
|
||||||
Music music{};
|
|
||||||
Sound sound{};
|
|
||||||
bool enabled{true};
|
|
||||||
float volume{1.0F};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Controles de jugadors
|
|
||||||
|
|
||||||
struct KeyboardControls {
|
|
||||||
SDL_Scancode key_left{SDL_SCANCODE_LEFT};
|
SDL_Scancode key_left{SDL_SCANCODE_LEFT};
|
||||||
SDL_Scancode key_right{SDL_SCANCODE_RIGHT};
|
SDL_Scancode key_right{SDL_SCANCODE_RIGHT};
|
||||||
SDL_Scancode key_thrust{SDL_SCANCODE_UP};
|
SDL_Scancode key_thrust{SDL_SCANCODE_UP};
|
||||||
SDL_Scancode key_shoot{SDL_SCANCODE_SPACE};
|
SDL_Scancode key_shoot{SDL_SCANCODE_SPACE};
|
||||||
SDL_Scancode key_start{SDL_SCANCODE_1};
|
SDL_Scancode key_start{SDL_SCANCODE_1};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GamepadControls {
|
struct GamepadControls {
|
||||||
int button_left{SDL_GAMEPAD_BUTTON_DPAD_LEFT};
|
int button_left{SDL_GAMEPAD_BUTTON_DPAD_LEFT};
|
||||||
int button_right{SDL_GAMEPAD_BUTTON_DPAD_RIGHT};
|
int button_right{SDL_GAMEPAD_BUTTON_DPAD_RIGHT};
|
||||||
int button_thrust{SDL_GAMEPAD_BUTTON_WEST}; // X button
|
int button_thrust{SDL_GAMEPAD_BUTTON_WEST}; // X button
|
||||||
int button_shoot{SDL_GAMEPAD_BUTTON_SOUTH}; // A button
|
int button_shoot{SDL_GAMEPAD_BUTTON_SOUTH}; // A button
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerControls {
|
struct PlayerControls {
|
||||||
KeyboardControls keyboard{};
|
KeyboardControls keyboard{};
|
||||||
GamepadControls gamepad{};
|
GamepadControls gamepad{};
|
||||||
std::string gamepad_name; // Buit = auto-assignar per índex
|
std::string gamepad_name; // Buit = auto-assignar per índex
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variables globals (inline per evitar ODR violations)
|
// Variables globals (inline per evitar ODR violations)
|
||||||
|
|
||||||
inline std::string version{}; // Versión del config per validació
|
inline std::string version{}; // Versión del config per validació
|
||||||
inline bool console{false}; // Eixida de debug
|
inline bool console{false}; // Eixida de debug
|
||||||
inline Window window{};
|
inline Window window{};
|
||||||
inline Physics physics{};
|
inline Rendering rendering{};
|
||||||
inline Gameplay gameplay{};
|
|
||||||
inline Rendering rendering{};
|
|
||||||
inline Audio audio{};
|
|
||||||
|
|
||||||
// Controles per player
|
// Controles per player
|
||||||
inline PlayerControls player1{
|
inline PlayerControls player1{
|
||||||
.keyboard =
|
.keyboard =
|
||||||
{.key_left = SDL_SCANCODE_LEFT,
|
{.key_left = SDL_SCANCODE_LEFT,
|
||||||
.key_right = SDL_SCANCODE_RIGHT,
|
.key_right = SDL_SCANCODE_RIGHT,
|
||||||
@@ -92,9 +58,9 @@ inline PlayerControls player1{
|
|||||||
.key_shoot = SDL_SCANCODE_SPACE,
|
.key_shoot = SDL_SCANCODE_SPACE,
|
||||||
.key_start = SDL_SCANCODE_1},
|
.key_start = SDL_SCANCODE_1},
|
||||||
.gamepad_name = "" // Primer gamepad disponible
|
.gamepad_name = "" // Primer gamepad disponible
|
||||||
};
|
};
|
||||||
|
|
||||||
inline PlayerControls player2{
|
inline PlayerControls player2{
|
||||||
.keyboard =
|
.keyboard =
|
||||||
{.key_left = SDL_SCANCODE_A,
|
{.key_left = SDL_SCANCODE_A,
|
||||||
.key_right = SDL_SCANCODE_D,
|
.key_right = SDL_SCANCODE_D,
|
||||||
@@ -102,20 +68,20 @@ inline PlayerControls player2{
|
|||||||
.key_shoot = SDL_SCANCODE_LSHIFT,
|
.key_shoot = SDL_SCANCODE_LSHIFT,
|
||||||
.key_start = SDL_SCANCODE_2},
|
.key_start = SDL_SCANCODE_2},
|
||||||
.gamepad_name = "" // Segon gamepad disponible
|
.gamepad_name = "" // Segon gamepad disponible
|
||||||
};
|
};
|
||||||
|
|
||||||
// Per compatibilitat con pollo (no utilitzat en orni, pero necessari per Input)
|
// Per compatibilitat con pollo (no utilitzat en orni, pero necessari per Input)
|
||||||
inline KeyboardControls keyboard_controls{};
|
inline KeyboardControls keyboard_controls{};
|
||||||
inline GamepadControls gamepad_controls{};
|
inline GamepadControls gamepad_controls{};
|
||||||
|
|
||||||
inline std::string config_file_path{}; // Establert per setConfigFile()
|
inline std::string config_file_path{}; // Establert per setConfigFile()
|
||||||
|
|
||||||
// Funciones públiques
|
// Funciones públiques
|
||||||
|
|
||||||
void init(); // Inicialitzar con valors per defecte
|
void init(); // Inicialitzar con valors per defecte
|
||||||
void setConfigFile(
|
void setConfigFile(
|
||||||
const std::string& path); // Establir ruta del file de config
|
const std::string& path); // Establir ruta del file de config
|
||||||
auto loadFromFile() -> bool; // Carregar config YAML
|
auto loadFromFile() -> bool; // Carregar config YAML
|
||||||
auto saveToFile() -> bool; // Guardar config YAML
|
auto saveToFile() -> bool; // Guardar config YAML
|
||||||
|
|
||||||
} // namespace Options
|
} // namespace Options
|
||||||
|
|||||||
Reference in New Issue
Block a user