refactor(#28): Director rep EngineConfig + ConfigPersistence, main orquestra
Pas 5/N del hallazgo #28. Director deixa d'incloure game/options.hpp i les seves crides a Options::*. El seu ctor accepta ara: - Config::EngineConfig& cfg → la struct runtime (window, console, ...). - Config::ConfigPersistence → 4 lambdes (init/set_path/load/save) que delegen la persistència a la capa concreta (game/Options::*). Cap més referència a Options:: ni a "game/..." dins del Director: - cfg_->* substitueix tot Options::* (window, console, player1/2, rendering, engine_config). - persistence_.{init,save,load,set_path} substitueix les funcions d'I/O de YAML. run() i checkProgramArguments deixen de ser estàtics (necessiten accés a cfg_ i persistence_). Això també desfà el smell del hallazgo #37 (Director::run estàtic que llegia estat d'instància). main.cpp queda com a orquestrador: construeix la struct ConfigPersistence amb lambdes que enllacen amb Options::* i la injecta al Director. Afegit: Config::ConfigPersistence a engine_config.hpp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Config {
|
namespace Config {
|
||||||
@@ -58,4 +59,14 @@ namespace Config {
|
|||||||
bool console{false};
|
bool console{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Capa de persistència delegada cap a l'EngineConfig. Permet al Director
|
||||||
|
// orquestrar init/load/save sense conèixer cap esquema concret (YAML,
|
||||||
|
// SQLite, ...) ni la capa que el conté (`game/options.cpp`).
|
||||||
|
struct ConfigPersistence {
|
||||||
|
std::function<void()> init_defaults; // Restaura valors per defecte
|
||||||
|
std::function<void(const std::string& path)> set_path; // Indica on guardar
|
||||||
|
std::function<bool()> load; // Llegeix path → EngineConfig
|
||||||
|
std::function<bool()> save; // Escriu EngineConfig → path
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Config
|
} // namespace Config
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#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 "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"
|
||||||
@@ -38,11 +37,15 @@ using SceneManager::SceneContext;
|
|||||||
using SceneType = SceneContext::SceneType;
|
using SceneType = SceneContext::SceneType;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Director::Director(std::vector<std::string> const& args) {
|
Director::Director(std::vector<std::string> const& args,
|
||||||
|
Config::EngineConfig& cfg,
|
||||||
|
Config::ConfigPersistence persistence)
|
||||||
|
: cfg_(&cfg),
|
||||||
|
persistence_(std::move(persistence)) {
|
||||||
std::cout << "Orni Attack - Inici\n";
|
std::cout << "Orni Attack - Inici\n";
|
||||||
|
|
||||||
// Inicialitzar opciones con valors per defecte
|
// Inicialitzar opciones con valors per defecte
|
||||||
Options::init();
|
persistence_.init_defaults();
|
||||||
|
|
||||||
// Comprovar arguments del programa
|
// Comprovar arguments del programa
|
||||||
executable_path_ = checkProgramArguments(args);
|
executable_path_ = checkProgramArguments(args);
|
||||||
@@ -90,22 +93,22 @@ Director::Director(std::vector<std::string> const& args) {
|
|||||||
createSystemFolder(std::string("jailgames/") + Project::NAME);
|
createSystemFolder(std::string("jailgames/") + Project::NAME);
|
||||||
|
|
||||||
// Establir ruta del file de configuración
|
// Establir ruta del file de configuración
|
||||||
Options::setConfigFile(system_folder_ + "/config.yaml");
|
persistence_.set_path(system_folder_ + "/config.yaml");
|
||||||
|
|
||||||
// Carregar o crear configuración
|
// Carregar o crear configuración
|
||||||
Options::loadFromFile();
|
persistence_.load();
|
||||||
|
|
||||||
// Inicialitzar sistema de input
|
// Inicialitzar sistema de input
|
||||||
Input::init("data/gamecontrollerdb.txt");
|
Input::init("data/gamecontrollerdb.txt");
|
||||||
|
|
||||||
// Aplicar configuración de controls dels jugadors
|
// Aplicar configuración de controls dels jugadors
|
||||||
Input::get()->applyPlayer1Bindings(Options::player1);
|
Input::get()->applyPlayer1Bindings(cfg_->player1);
|
||||||
Input::get()->applyPlayer2Bindings(Options::player2);
|
Input::get()->applyPlayer2Bindings(cfg_->player2);
|
||||||
|
|
||||||
if (Options::console) {
|
if (cfg_->console) {
|
||||||
std::cout << "Configuración carregada\n";
|
std::cout << "Configuración carregada\n";
|
||||||
std::cout << " Finestra: " << Options::window.width << "×"
|
std::cout << " Finestra: " << cfg_->window.width << "×"
|
||||||
<< Options::window.height << '\n';
|
<< cfg_->window.height << '\n';
|
||||||
std::cout << " Input: " << Input::get()->getNumGamepads()
|
std::cout << " Input: " << Input::get()->getNumGamepads()
|
||||||
<< " gamepad(s) detectat(s)\n";
|
<< " gamepad(s) detectat(s)\n";
|
||||||
}
|
}
|
||||||
@@ -115,7 +118,7 @@ Director::Director(std::vector<std::string> const& args) {
|
|||||||
|
|
||||||
Director::~Director() {
|
Director::~Director() {
|
||||||
// Guardar opciones
|
// Guardar opciones
|
||||||
Options::saveToFile();
|
persistence_.save();
|
||||||
|
|
||||||
// Cleanup input
|
// Cleanup input
|
||||||
Input::destroy();
|
Input::destroy();
|
||||||
@@ -136,11 +139,11 @@ auto Director::checkProgramArguments(std::vector<std::string> const& args)
|
|||||||
const std::string& argument = args[i];
|
const std::string& argument = args[i];
|
||||||
|
|
||||||
if (argument == "--console") {
|
if (argument == "--console") {
|
||||||
Options::console = true;
|
cfg_->console = true;
|
||||||
std::cout << "Mode consola activat\n";
|
std::cout << "Mode consola activat\n";
|
||||||
} else if (argument == "--reset-config") {
|
} else if (argument == "--reset-config") {
|
||||||
Options::init();
|
persistence_.init_defaults();
|
||||||
Options::saveToFile();
|
persistence_.save();
|
||||||
std::cout << "Configuración restablida als valors per defecte\n";
|
std::cout << "Configuración restablida als valors per defecte\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +210,7 @@ void Director::createSystemFolder(const std::string& folder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Options::console) {
|
if (cfg_->console) {
|
||||||
std::cout << "Carpeta del sistema: " << system_folder_ << '\n';
|
std::cout << "Carpeta del sistema: " << system_folder_ << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,18 +219,17 @@ void Director::createSystemFolder(const std::string& folder) {
|
|||||||
auto Director::run() -> int {
|
auto Director::run() -> int {
|
||||||
// Calculate initial size from saved zoom_factor
|
// Calculate initial size from saved zoom_factor
|
||||||
int initial_width = static_cast<int>(std::round(
|
int initial_width = static_cast<int>(std::round(
|
||||||
Defaults::Window::WIDTH * Options::window.zoom_factor));
|
Defaults::Window::WIDTH * cfg_->window.zoom_factor));
|
||||||
int initial_height = static_cast<int>(std::round(
|
int initial_height = static_cast<int>(std::round(
|
||||||
Defaults::Window::HEIGHT * Options::window.zoom_factor));
|
Defaults::Window::HEIGHT * cfg_->window.zoom_factor));
|
||||||
|
|
||||||
// Crear gestor SDL con configuración de Options.
|
// Crear gestor SDL amb la engine_config + callback de persistència
|
||||||
// Inyectamos la engine_config + un callback per persistir-la quan
|
// per a quan toggleVSync (F4) muti vsync. Mantenim sdl_manager agnòstic.
|
||||||
// toggleVSync (F4) muti vsync, sense que sdl_manager conegui Options.
|
SDLManager sdl(initial_width, initial_height, cfg_->window.fullscreen, *cfg_, [this] { persistence_.save(); });
|
||||||
SDLManager sdl(initial_width, initial_height, Options::window.fullscreen, Options::engine_config, [] { Options::saveToFile(); });
|
|
||||||
|
|
||||||
// CRÍTIC: Forçar ocultació del cursor DESPRÉS de toda la inicialización SDL
|
// CRÍTIC: Forçar ocultació del cursor DESPRÉS de toda la inicialización SDL
|
||||||
// Això evita que SDL mostre el cursor automàticament durante la creació de la finestra
|
// Això evita que SDL mostre el cursor automàticament durante la creació de la finestra
|
||||||
if (!Options::window.fullscreen) {
|
if (!cfg_->window.fullscreen) {
|
||||||
Mouse::forceHide();
|
Mouse::forceHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +248,7 @@ auto Director::run() -> int {
|
|||||||
// Precachear música para evitar lag al empezar
|
// Precachear música para evitar lag al empezar
|
||||||
AudioResource::getMusic("title.ogg");
|
AudioResource::getMusic("title.ogg");
|
||||||
AudioResource::getMusic("game.ogg");
|
AudioResource::getMusic("game.ogg");
|
||||||
if (Options::console) {
|
if (cfg_->console) {
|
||||||
std::cout << "Música precacheada\n";
|
std::cout << "Música precacheada\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +262,7 @@ auto Director::run() -> int {
|
|||||||
|
|
||||||
// Overlay de debug (FPS + VSync). Vive en el Director porque es global
|
// Overlay de debug (FPS + VSync). Vive en el Director porque es global
|
||||||
// a todas las escenas. Toggle con F11 (visible por defecto en _DEBUG).
|
// a todas las escenas. Toggle con F11 (visible por defecto en _DEBUG).
|
||||||
System::DebugOverlay debug_overlay(sdl.getRenderer(), Options::rendering);
|
System::DebugOverlay debug_overlay(sdl.getRenderer(), cfg_->rendering);
|
||||||
|
|
||||||
// Bucle principal: construir escena → frame loop → destruir → siguiente.
|
// Bucle principal: construir escena → frame loop → destruir → siguiente.
|
||||||
while (context.nextScene() != SceneType::EXIT) {
|
while (context.nextScene() != SceneType::EXIT) {
|
||||||
|
|||||||
@@ -4,27 +4,35 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "core/config/engine_config.hpp"
|
||||||
#include "scene_context.hpp"
|
#include "scene_context.hpp"
|
||||||
|
|
||||||
class Scene;
|
class Scene;
|
||||||
class SDLManager;
|
class SDLManager;
|
||||||
namespace System { class DebugOverlay; }
|
namespace System {
|
||||||
|
class DebugOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
class Director {
|
class Director {
|
||||||
public:
|
public:
|
||||||
explicit Director(std::vector<std::string> const& args);
|
// `cfg` ha de viure tant com el Director (típicament owned per main).
|
||||||
|
// `persistence` encapsula init/load/save delegats a la capa concreta
|
||||||
|
// (game/Options::*).
|
||||||
|
Director(std::vector<std::string> const& args,
|
||||||
|
Config::EngineConfig& cfg,
|
||||||
|
Config::ConfigPersistence persistence);
|
||||||
~Director();
|
~Director();
|
||||||
|
|
||||||
// Main game loop. Estático: los miembros del Director (executable_path_,
|
// Bucle principal del juego.
|
||||||
// system_folder_) se establecen en el ctor y no se vuelven a leer aquí;
|
auto run() -> int;
|
||||||
// el bucle solo orquesta sistemas globales (SDLManager, Options, Audio).
|
|
||||||
static auto run() -> int;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string executable_path_;
|
std::string executable_path_;
|
||||||
std::string system_folder_;
|
std::string system_folder_;
|
||||||
|
Config::EngineConfig* cfg_;
|
||||||
|
Config::ConfigPersistence persistence_;
|
||||||
|
|
||||||
static auto checkProgramArguments(std::vector<std::string> const& args)
|
auto checkProgramArguments(std::vector<std::string> const& args)
|
||||||
-> std::string;
|
-> std::string;
|
||||||
void createSystemFolder(const std::string& folder);
|
void createSystemFolder(const std::string& folder);
|
||||||
|
|
||||||
@@ -38,7 +46,5 @@ class Director {
|
|||||||
// Ejecuta el bucle de frames de UNA escena hasta que scene.isFinished()
|
// Ejecuta el bucle de frames de UNA escena hasta que scene.isFinished()
|
||||||
// sea true. Maneja delta_time, eventos (globales + escena), update y draw.
|
// sea true. Maneja delta_time, eventos (globales + escena), update y draw.
|
||||||
// El debug_overlay es global a todas las escenas; el Director lo posee.
|
// El debug_overlay es global a todas las escenas; el Director lo posee.
|
||||||
static void runFrameLoop(Scene& scene, SDLManager& sdl,
|
static void runFrameLoop(Scene& scene, SDLManager& sdl, SceneManager::SceneContext& context, System::DebugOverlay& debug_overlay);
|
||||||
SceneManager::SceneContext& context,
|
|
||||||
System::DebugOverlay& debug_overlay);
|
|
||||||
};
|
};
|
||||||
|
|||||||
+20
-5
@@ -1,18 +1,33 @@
|
|||||||
// main.cpp - Vec2 de entrada del juego Asteroides
|
// main.cpp - Punt d'entrada de l'aplicació
|
||||||
// © 2026 JailDesigner
|
// © 2026 JailDesigner
|
||||||
|
//
|
||||||
|
// Aquí orquestrem la capa de persistència (YAML via game/Options::*) i
|
||||||
|
// injectem el resultat al Director. El Director queda independent de
|
||||||
|
// game/options.hpp i pot operar només amb Config::EngineConfig.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "core/config/engine_config.hpp"
|
||||||
#include "core/system/director.hpp"
|
#include "core/system/director.hpp"
|
||||||
|
#include "game/options.hpp"
|
||||||
|
|
||||||
auto main(int argc, char* argv[]) -> int {
|
auto main(int argc, char* argv[]) -> int {
|
||||||
// Convertir arguments a std::vector<std::string>
|
// Convertir arguments a std::vector<std::string>
|
||||||
std::vector<std::string> args(argv, argv + argc);
|
std::vector<std::string> args(argv, argv + argc);
|
||||||
|
|
||||||
// Crear director (inicialitza sistema, opciones, configuración)
|
// Capa de persistència delegada: lambdes prim que enllacen el contracte
|
||||||
Director director(args);
|
// de Config::ConfigPersistence amb la implementació YAML de Options::*.
|
||||||
|
const Config::ConfigPersistence PERSISTENCE{
|
||||||
|
.init_defaults = [] { Options::init(); },
|
||||||
|
.set_path = [](const std::string& path) { Options::setConfigFile(path); },
|
||||||
|
.load = [] { return Options::loadFromFile(); },
|
||||||
|
.save = [] { return Options::saveToFile(); },
|
||||||
|
};
|
||||||
|
|
||||||
// Executar bucle principal del juego
|
// El Director rep la struct d'engine_config + la capa de persistència.
|
||||||
return Director::run();
|
// No coneix Options::* directament.
|
||||||
|
Director director(args, Options::engine_config, PERSISTENCE);
|
||||||
|
|
||||||
|
return director.run();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user