Files
orni-attack/source/core/system/director.cpp
T
JailDesigner 5871d29d48 Fase 1c: rename d'escenes i sistema d'escenes
Tots els tipus, fitxers, namespace, enums i metodes relacionats amb
les escenes passen del catala a l'angles seguint el .clang-tidy:

Fitxers (renames git):
- source/game/escenes/escena_joc.{hpp,cpp} -> game/scenes/game_scene.{hpp,cpp}
- source/game/escenes/escena_titol.{hpp,cpp} -> game/scenes/title_scene.{hpp,cpp}
- source/game/escenes/escena_logo.{hpp,cpp} -> game/scenes/logo_scene.{hpp,cpp}
- source/core/system/context_escenes.hpp -> core/system/scene_context.hpp
- Carpeta game/escenes/ -> game/scenes/

Tipus (CamelCase):
- EscenaJoc -> GameScene
- EscenaTitol -> TitleScene
- EscenaLogo -> LogoScene
- ContextEscenes -> SceneContext
- Escena (enum class) -> SceneType
- Opcio -> Option
- EstatGameOver -> GameOverState
- EstatTitol -> TitleState
- EstatAnimacio -> AnimationState
- ConfigPartida -> MatchConfig

Namespace:
- GestorEscenes -> SceneManager

Valors d'enum SceneType:
- TITOL -> TITLE
- JOC -> GAME
- EIXIR -> EXIT
(LOGO mantingut)

Metodes (camelBack):
- executar -> run
- canviar_escena -> setNextScene
- escena_desti -> nextScene
- opcio (getter) -> option
- consumir_opcio -> consumeOption
- reset_opcio -> resetOption
- set_config_partida -> setMatchConfig
- get_config_partida -> getMatchConfig

Camps privats (lower_case_):
- escena_desti_ -> next_scene_
- opcio_ -> option_
- config_partida_ -> match_config_

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:41:11 +02:00

283 lines
8.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "director.hpp"
#include <SDL3/SDL.h>
#include <sys/stat.h>
#include <cerrno>
#include <cstdlib>
#include <iostream>
#include "scene_context.hpp"
#include "core/audio/audio.hpp"
#include "core/audio/audio_cache.hpp"
#include "core/defaults.hpp"
#include "core/input/input.hpp"
#include "core/input/mouse.hpp"
#include "core/rendering/sdl_manager.hpp"
#include "core/resources/resource_helper.hpp"
#include "core/resources/resource_loader.hpp"
#include "core/utils/path_utils.hpp"
#include "game/scenes/game_scene.hpp"
#include "game/scenes/logo_scene.hpp"
#include "game/scenes/title_scene.hpp"
#include "game/options.hpp"
#include "project.h"
#ifndef _WIN32
#include <pwd.h>
#include <unistd.h>
#endif
// Using declarations per simplificar el codi
using SceneManager::SceneContext;
using SceneType = SceneContext::SceneType;
// Constructor
Director::Director(std::vector<std::string> const& args) {
std::cout << "Orni Attack - Inici\n";
// Inicialitzar opcions amb valors per defecte
Options::init();
// Comprovar arguments del programa
executable_path_ = checkProgramArguments(args);
// Inicialitzar sistema de rutes
Utils::initializePathSystem(args[0].c_str());
// Obtenir ruta base dels recursos
std::string resource_base = Utils::getResourceBasePath();
// Inicialitzar sistema de recursos
#ifdef RELEASE_BUILD
// Mode release: paquet obligatori, sense fallback
std::string pack_path = resource_base + "/resources.pack";
if (!Resource::Helper::initializeResourceSystem(pack_path, false)) {
std::cerr << "ERROR FATAL: No es pot carregar " << pack_path << "\n";
std::cerr << "El joc no pot continuar sense els recursos.\n";
std::exit(1);
}
// Validar integritat del paquet
if (!Resource::Loader::get().validatePack()) {
std::cerr << "ERROR FATAL: El paquet de recursos està corromput\n";
std::exit(1);
}
std::cout << "Sistema de recursos inicialitzat (mode release)\n";
#else
// Mode desenvolupament: intentar paquet amb fallback a data/
std::string pack_path = resource_base + "/resources.pack";
Resource::Helper::initializeResourceSystem(pack_path, true);
if (Resource::Helper::isPackLoaded()) {
std::cout << "Sistema de recursos inicialitzat (mode dev amb paquet)\n";
} else {
std::cout << "Sistema de recursos inicialitzat (mode dev, fallback a data/)\n";
}
// Establir ruta base per al fallback
Resource::Loader::get().setBasePath(resource_base);
#endif
// Crear carpetes del sistema
createSystemFolder("jailgames");
createSystemFolder(std::string("jailgames/") + Project::NAME);
// Establir ruta del fitxer de configuració
Options::setConfigFile(system_folder_ + "/config.yaml");
// Carregar o crear configuració
Options::loadFromFile();
// Inicialitzar sistema d'input
Input::init("data/gamecontrollerdb.txt");
// Aplicar configuració de controls dels jugadors
Input::get()->applyPlayer1BindingsFromOptions();
Input::get()->applyPlayer2BindingsFromOptions();
if (Options::console) {
std::cout << "Configuració carregada\n";
std::cout << " Finestra: " << Options::window.width << "×"
<< Options::window.height << '\n';
std::cout << " Física: rotation=" << Options::physics.rotation_speed
<< " rad/s\n";
std::cout << " Input: " << Input::get()->getNumGamepads()
<< " gamepad(s) detectat(s)\n";
}
std::cout << '\n';
}
Director::~Director() {
// Guardar opcions
Options::saveToFile();
// Cleanup input
Input::destroy();
// Cleanup audio
Audio::destroy();
// Cleanup SDL
SDL_Quit();
std::cout << "\nAdéu!\n";
}
// Comprovar arguments del programa
auto Director::checkProgramArguments(std::vector<std::string> const& args)
-> std::string {
for (std::size_t i = 1; i < args.size(); ++i) {
const std::string& argument = args[i];
if (argument == "--console") {
Options::console = true;
std::cout << "Mode consola activat\n";
} else if (argument == "--reset-config") {
Options::init();
Options::saveToFile();
std::cout << "Configuració restablida als valors per defecte\n";
}
}
return args[0]; // Retornar ruta de l'executable
}
// Crear carpeta del sistema (específic per plataforma)
void Director::createSystemFolder(const std::string& folder) {
#ifdef _WIN32
system_folder_ = std::string(getenv("APPDATA")) + "/" + folder;
#elif __APPLE__
struct passwd* pw = getpwuid(getuid());
const char* homedir = pw->pw_dir;
system_folder_ =
std::string(homedir) + "/Library/Application Support/" + folder;
#elif __linux__
struct passwd* pw = getpwuid(getuid());
const char* homedir = pw->pw_dir;
system_folder_ = std::string(homedir) + "/.config/" + folder;
// CRÍTIC: Crear ~/.config si no existeix
{
std::string config_base_folder = std::string(homedir) + "/.config";
int ret = mkdir(config_base_folder.c_str(), S_IRWXU);
if (ret == -1 && errno != EEXIST) {
printf("ERROR: No es pot crear la carpeta ~/.config\n");
exit(EXIT_FAILURE);
}
}
#endif
// Comprovar si la carpeta existeix
struct stat st = {.st_dev = 0};
if (stat(system_folder_.c_str(), &st) == -1) {
errno = 0;
#ifdef _WIN32
int ret = mkdir(system_folder_.c_str());
#else
int ret = mkdir(system_folder_.c_str(), S_IRWXU);
#endif
if (ret == -1) {
switch (errno) {
case EACCES:
printf("ERROR: Permisos denegats creant %s\n", system_folder_.c_str());
exit(EXIT_FAILURE);
case EEXIST:
// La carpeta ja existeix (race condition), continuar
break;
case ENAMETOOLONG:
printf("ERROR: Ruta massa llarga: %s\n", system_folder_.c_str());
exit(EXIT_FAILURE);
default:
perror("mkdir");
exit(EXIT_FAILURE);
}
}
}
if (Options::console) {
std::cout << "Carpeta del sistema: " << system_folder_ << '\n';
}
}
// Bucle principal del joc
auto Director::run() -> int {
// Calculate initial size from saved zoom_factor
int initial_width = static_cast<int>(std::round(
Defaults::Window::WIDTH * Options::window.zoom_factor));
int initial_height = static_cast<int>(std::round(
Defaults::Window::HEIGHT * Options::window.zoom_factor));
// Crear gestor SDL amb configuració de Options
SDLManager sdl(initial_width, initial_height, Options::window.fullscreen);
// CRÍTIC: Forçar ocultació del cursor DESPRÉS de tota la inicialització SDL
// Això evita que SDL mostre el cursor automàticament durant la creació de la finestra
if (!Options::window.fullscreen) {
Mouse::forceHide();
}
// Inicialitzar sistema d'audio
Audio::init();
Audio::get()->setMusicVolume(1.0);
Audio::get()->setSoundVolume(0.4);
// Precachejar música per evitar lag al començar
AudioCache::getMusic("title.ogg");
AudioCache::getMusic("game.ogg");
if (Options::console) {
std::cout << "Música precachejada: "
<< AudioCache::getMusicCacheSize() << " fitxers\n";
}
// Crear context d'escenes
SceneContext context;
#ifdef _DEBUG
context.setNextScene(SceneType::TITLE);
#else
context.setNextScene(SceneType::LOGO);
#endif
// Bucle principal de gestió d'escenes
while (context.nextScene() != SceneType::EXIT) {
// Sincronitzar SceneManager::actual amb context
// (altres sistemes encara poden llegir SceneManager::actual)
SceneManager::actual = context.nextScene();
switch (context.nextScene()) {
case SceneType::LOGO: {
LogoScene logo(sdl, context);
logo.run();
break;
}
case SceneType::TITLE: {
TitleScene titol(sdl, context);
titol.run();
break;
}
case SceneType::GAME: {
GameScene joc(sdl, context);
joc.run();
break;
}
default:
break;
}
}
// Sincronitzar final amb SceneManager::actual
SceneManager::actual = SceneType::EXIT;
return 0;
}