diff --git a/source/core/rendering/sdl_manager.cpp b/source/core/rendering/sdl_manager.cpp index 114470b..61d8aa5 100644 --- a/source/core/rendering/sdl_manager.cpp +++ b/source/core/rendering/sdl_manager.cpp @@ -32,7 +32,7 @@ SDLManager::SDLManager() // Calcular mida màxima des del display calculateMaxWindowSize(); - // Construir títol dinàmic igual que en pollo + // Construir títol dinàmic std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME, Project::VERSION, Project::COPYRIGHT); // Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED) @@ -60,6 +60,9 @@ SDLManager::SDLManager() return; } + // Aplicar configuració de V-Sync + SDL_SetRenderVSync(renderer_, Options::rendering.vsync); + // CRÍTIC: Configurar viewport scaling updateLogicalPresentation(); @@ -122,6 +125,9 @@ SDLManager::SDLManager(int width, int height, bool fullscreen) return; } + // Aplicar configuració de V-Sync + SDL_SetRenderVSync(renderer_, Options::rendering.vsync); + // Configurar viewport scaling updateLogicalPresentation(); @@ -343,3 +349,17 @@ void SDLManager::setWindowTitle(const std::string& title) { SDL_SetWindowTitle(finestra_, title.c_str()); } } + +// [NUEVO] Toggle V-Sync (F4) +void SDLManager::toggleVSync() { + // Toggle: 1 → 0 → 1 + Options::rendering.vsync = (Options::rendering.vsync == 1) ? 0 : 1; + + // Aplicar a SDL + if (renderer_) { + SDL_SetRenderVSync(renderer_, Options::rendering.vsync); + } + + // Guardar configuració + Options::saveToFile(); +} diff --git a/source/core/rendering/sdl_manager.hpp b/source/core/rendering/sdl_manager.hpp index d49eac2..14c4128 100644 --- a/source/core/rendering/sdl_manager.hpp +++ b/source/core/rendering/sdl_manager.hpp @@ -26,6 +26,7 @@ class SDLManager { void increaseWindowSize(); // F2: +100px void decreaseWindowSize(); // F1: -100px void toggleFullscreen(); // F3 + void toggleVSync(); // F4 bool handleWindowEvent(const SDL_Event& event); // Per a SDL_EVENT_WINDOW_RESIZED diff --git a/source/game/escenes/escena_logo.hpp b/source/game/escenes/escena_logo.hpp index 6cb5f06..92768e8 100644 --- a/source/game/escenes/escena_logo.hpp +++ b/source/game/escenes/escena_logo.hpp @@ -13,6 +13,7 @@ #include "../../core/rendering/sdl_manager.hpp" #include "../../core/types.hpp" #include "../effects/debris_manager.hpp" +#include "core/defaults.hpp" class EscenaLogo { public: @@ -64,8 +65,8 @@ class EscenaLogo { // Constants d'animació seqüencial static constexpr float THRESHOLD_LETRA = 0.6f; // Umbral per activar següent lletra (0.0-1.0) - static constexpr float ORIGEN_ZOOM_X = 640.0f / 2.0f; // Punt inicial X del zoom (320) - static constexpr float ORIGEN_ZOOM_Y = 480.0f * 0.4f; // Punt inicial Y del zoom (240) + static constexpr float ORIGEN_ZOOM_X = Defaults::Game::WIDTH * 0.5f; // Punt inicial X del zoom + static constexpr float ORIGEN_ZOOM_Y = Defaults::Game::HEIGHT * 0.4f; // Punt inicial Y del zoom // Mètodes privats void inicialitzar_lletres(); diff --git a/source/game/options.cpp b/source/game/options.cpp index ae5cfbb..2ed7d7b 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -36,6 +36,9 @@ void init() { gameplay.max_enemies = Defaults::Entities::MAX_ORNIS; gameplay.max_bullets = Defaults::Entities::MAX_BALES; + // Rendering + rendering.vsync = Defaults::Rendering::VSYNC_DEFAULT; + // Version version = std::string(Project::VERSION); } @@ -181,6 +184,22 @@ static void loadGameplayConfigFromYaml(const fkyaml::node& yaml) { } } +static void loadRenderingConfigFromYaml(const fkyaml::node& yaml) { + if (yaml.contains("rendering")) { + const auto& rend = yaml["rendering"]; + + if (rend.contains("vsync")) { + try { + int val = rend["vsync"].get_value(); + // Validar: només 0 o 1 + rendering.vsync = (val == 0 || val == 1) ? val : Defaults::Rendering::VSYNC_DEFAULT; + } catch (...) { + rendering.vsync = Defaults::Rendering::VSYNC_DEFAULT; + } + } + } +} + // Carregar configuració des del fitxer YAML auto loadFromFile() -> bool { const std::string CONFIG_VERSION = std::string(Project::VERSION); @@ -226,6 +245,7 @@ auto loadFromFile() -> bool { loadWindowConfigFromYaml(yaml); loadPhysicsConfigFromYaml(yaml); loadGameplayConfigFromYaml(yaml); + loadRenderingConfigFromYaml(yaml); if (console) { std::cout << "Config carregada correctament des de: " << config_file_path @@ -285,7 +305,11 @@ auto saveToFile() -> bool { file << "# GAMEPLAY\n"; file << "gameplay:\n"; file << " max_enemies: " << gameplay.max_enemies << "\n"; - file << " max_bullets: " << gameplay.max_bullets << "\n"; + file << " max_bullets: " << gameplay.max_bullets << "\n\n"; + + file << "# RENDERITZACIÓ\n"; + file << "rendering:\n"; + file << " vsync: " << rendering.vsync << " # 0=disabled, 1=enabled\n"; file.close(); diff --git a/source/game/options.hpp b/source/game/options.hpp index c9bbcb8..001a6f6 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -27,6 +27,10 @@ struct Gameplay { int max_bullets{3}; }; +struct Rendering { + int vsync{1}; // 0=disabled, 1=enabled +}; + // Variables globals (inline per evitar ODR violations) inline std::string version{}; // Versió del config per validació @@ -34,6 +38,7 @@ inline bool console{false}; // Eixida de debug inline Window window{}; inline Physics physics{}; inline Gameplay gameplay{}; +inline Rendering rendering{}; inline std::string config_file_path{}; // Establert per setConfigFile()