Files
coffee_crisis_arcade_edition/source/director.cpp
Sergio Valor 1e9e664012 creat param_red.txt
afegides guardes en setParams
2025-08-17 21:29:49 +02:00

327 lines
12 KiB
C++

// IWYU pragma: no_include <bits/chrono.h>
#include "director.h"
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_SetLogPriority, SDL_LogPriority, SDL_Quit
#include <cstdlib> // Para srand, exit, rand, EXIT_FAILURE
#include <ctime> // Para time
#include <iostream> // Para basic_ostream, operator<<, cerr, endl
#include <memory> // Para make_unique, unique_ptr
#include <span> // Para span
#include <stdexcept> // Para runtime_error
#include <string> // Para allocator, char_traits, operator==, string, basic_string, operator+
#include "asset.h" // Para Asset
#include "audio.h" // Para Audio
#include "input.h" // Para Input
#include "lang.h" // Para setLanguage
#include "manage_hiscore_table.h" // Para ManageHiScoreTable
#include "options.h" // Para loadFromFile, saveToFile, Settings, settings, setConfigFile, setControllersFile
#include "param.h" // Para loadParamsFromFile
#include "player.h" // Para Player
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.hpp" // Para Name, Options, name, options, AttractMode, attract_mode
#include "sections/credits.h" // Para Credits
#include "sections/game.h" // Para Game
#include "sections/hiscore_table.h" // Para HiScoreTable
#include "sections/instructions.h" // Para Instructions
#include "sections/intro.h" // Para Intro
#include "sections/logo.h" // Para Logo
#include "sections/title.h" // Para Title
#include "shutdown.h" // Para resultToString, shutdownSystem, ShutdownResult
#include "system_utils.h" // Para createApplicationFolder, resultToString, Result
#include "ui/notifier.h" // Para Notifier
#include "ui/service_menu.h" // Para ServiceMenu
#include "utils.h" // Para Overrides, overrides, getPath
// Constructor
Director::Director(int argc, std::span<char *> argv) {
#ifdef RECORDING
Section::name = Section::Name::GAME;
Section::options = Section::Options::GAME_PLAY_1P;
#elif _DEBUG
Section::name = Section::Name::GAME;
Section::options = Section::Options::GAME_PLAY_1P;
#else // NORMAL GAME
Section::name = Section::Name::LOGO;
Section::options = Section::Options::NONE;
#endif
Section::attract_mode = Section::AttractMode::TITLE_TO_DEMO;
// Establece el nivel de prioridad de la categoría de registro
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
SDL_SetLogPriority(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_ERROR);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Game start");
// Inicia la semilla aleatoria usando el tiempo actual en segundos
std::srand(static_cast<unsigned int>(std::time(nullptr)));
// Comprueba los parametros del programa
checkProgramArguments(argc, argv);
// Crea la carpeta del sistema donde guardar los datos persistentes
createSystemFolder("jailgames");
createSystemFolder("jailgames/coffee_crisis_arcade_edition");
init();
}
Director::~Director() {
close();
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nBye!");
}
// Inicializa todo
void Director::init() {
// Configuración inicial de parametros
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
loadAssets(); // Crea el índice de archivos
Input::init(Asset::get()->get("gamecontrollerdb.txt"), Asset::get()->get("controllers.json")); // Carga configuración de controles
Options::setConfigFile(Asset::get()->get("config.txt")); // Establece el fichero de configuración
Options::setControllersFile(Asset::get()->get("controllers.json")); // Establece el fichero de configuración de mandos
Options::loadFromFile(); // Carga el archivo de configuración
loadParams(); // Carga los parámetros del programa
loadScoreFile(); // Carga el archivo de puntuaciones
// Inicialización de subsistemas principales
Lang::setLanguage(Options::settings.language); // Carga el archivo de idioma
Screen::init(); // Inicializa la pantalla y el sistema de renderizado
Audio::init(); // Activa el sistema de audio
#ifdef _DEBUG
Resource::init(Resource::LoadingMode::PRELOAD); // Inicializa el sistema de gestión de recursos
#else
Resource::init(Resource::LoadingMode::PRELOAD); // Inicializa el sistema de gestión de recursos
#endif
ServiceMenu::init(); // Inicializa el menú de servicio
Notifier::init(std::string(), Resource::get()->getText("8bithud")); // Inicialización del sistema de notificaciones
Screen::get()->getSingletons(); // Obtiene los punteros al resto de singletones
}
// Cierra todo y libera recursos del sistema y de los singletons
void Director::close() {
// Guarda las opciones actuales en el archivo de configuración
Options::saveToFile();
// Libera los singletons y recursos en orden inverso al de inicialización
Notifier::destroy(); // Libera el sistema de notificaciones
ServiceMenu::destroy(); // Libera el sistema de menú de servicio
Input::destroy(); // Libera el sistema de entrada
Resource::destroy(); // Libera el sistema de recursos gráficos y de texto
Audio::destroy(); // Libera el sistema de audio
Screen::destroy(); // Libera el sistema de pantalla y renderizado
Asset::destroy(); // Libera el gestor de archivos
// Libera todos los recursos de SDL
SDL_Quit();
// Apaga el sistema
shutdownSystem(Section::options == Section::Options::SHUTDOWN);
}
// Carga los parametros
void Director::loadParams() {
// Carga los parametros para configurar el juego
#ifdef ANBERNIC
const std::string paramFilePath = asset->get("param_320x240.txt");
#else
const std::string PARAM_FILE_PATH = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_red.txt");
#endif
loadParamsFromFile(PARAM_FILE_PATH);
}
// Carga el fichero de puntuaciones
void Director::loadScoreFile() {
auto manager = std::make_unique<ManageHiScoreTable>(Options::settings.hi_score_table);
#ifdef _DEBUG
manager->clear();
#else
if (overrides.clear_hi_score_table) {
manager->clear();
} else {
manager->loadFromFile(Asset::get()->get("score.bin"));
}
#endif
}
// Carga el indice de ficheros desde un fichero
void Director::loadAssets() {
#ifdef MACOS_BUNDLE
const std::string PREFIX = "/../Resources";
#else
const std::string PREFIX;
#endif
// Cargar la configuración de assets (también aplicar el prefijo al archivo de configuración)
std::string config_path = executable_path_ + PREFIX + "/data/config/assets.txt";
Asset::get()->loadFromFile(config_path, PREFIX, system_folder_);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Assets configuration loaded successfully");
// Si falta algun fichero, sale del programa
if (!Asset::get()->check()) {
throw std::runtime_error("Falta algun fichero");
}
}
// Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, std::span<char *> argv) {
// Establece la ruta del programa
executable_path_ = getPath(argv[0]);
// Comprueba el resto de parámetros
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "--320x240") {
overrides.param_file = arg;
} else if (arg == "--clear_score") {
overrides.clear_hi_score_table = true;
}
}
}
// Crea la carpeta del sistema donde guardar datos
void Director::createSystemFolder(const std::string &folder) {
auto result = SystemUtils::createApplicationFolder(folder, system_folder_);
if (result != SystemUtils::Result::SUCCESS) {
std::cerr << "Error creando carpeta del sistema: "
<< SystemUtils::resultToString(result) << '\n';
exit(EXIT_FAILURE);
}
}
// Ejecuta la sección con el logo
void Director::runLogo() {
auto logo = std::make_unique<Logo>();
logo->run();
}
// Ejecuta la sección con la secuencia de introducción
void Director::runIntro() {
auto intro = std::make_unique<Intro>();
intro->run();
}
// Ejecuta la sección con el título del juego
void Director::runTitle() {
auto title = std::make_unique<Title>();
title->run();
}
// Ejecuta la sección donde se juega al juego
void Director::runGame() {
Player::Id player_id = Player::Id::PLAYER1;
switch (Section::options) {
case Section::Options::GAME_PLAY_1P:
player_id = Player::Id::PLAYER1;
break;
case Section::Options::GAME_PLAY_2P:
player_id = Player::Id::PLAYER2;
break;
case Section::Options::GAME_PLAY_BOTH:
player_id = Player::Id::BOTH_PLAYERS;
break;
default:
break;
}
#ifdef _DEBUG
constexpr int CURRENT_STAGE = 0;
#else
constexpr int CURRENT_STAGE = 0;
#endif
auto game = std::make_unique<Game>(player_id, CURRENT_STAGE, Game::DEMO_OFF);
game->run();
}
// Ejecuta la sección donde se muestran las instrucciones
void Director::runInstructions() {
auto instructions = std::make_unique<Instructions>();
instructions->run();
}
// Ejecuta la sección donde se muestran los creditos del programa
void Director::runCredits() {
auto credits = std::make_unique<Credits>();
credits->run();
}
// Ejecuta la sección donde se muestra la tabla de puntuaciones
void Director::runHiScoreTable() {
auto hi_score_table = std::make_unique<HiScoreTable>();
hi_score_table->run();
}
// Ejecuta el juego en modo demo
void Director::runDemoGame() {
const auto PLAYER_ID = static_cast<Player::Id>((rand() % 2) + 1);
constexpr auto CURRENT_STAGE = 0;
auto game = std::make_unique<Game>(PLAYER_ID, CURRENT_STAGE, Game::DEMO_ON);
game->run();
}
// Reinicia objetos y vuelve a la sección inicial
void Director::reset() {
Options::saveToFile();
Options::loadFromFile();
Lang::setLanguage(Options::settings.language);
Audio::get()->stopMusic();
Audio::get()->stopAllSounds();
Resource::get()->reload();
ServiceMenu::get()->reset();
Section::name = Section::Name::LOGO;
}
auto Director::run() -> int {
// Bucle principal
while (Section::name != Section::Name::QUIT) {
switch (Section::name) {
case Section::Name::RESET:
reset();
break;
case Section::Name::LOGO:
runLogo();
break;
case Section::Name::INTRO:
runIntro();
break;
case Section::Name::TITLE:
runTitle();
break;
case Section::Name::GAME:
runGame();
break;
case Section::Name::HI_SCORE_TABLE:
runHiScoreTable();
break;
case Section::Name::GAME_DEMO:
runDemoGame();
break;
case Section::Name::INSTRUCTIONS:
runInstructions();
break;
case Section::Name::CREDITS:
runCredits();
break;
default:
break;
}
}
return 0;
}
// Apaga el sistema de forma segura
void Director::shutdownSystem(bool should_shutdown) {
if (should_shutdown) {
auto result = SystemShutdown::shutdownSystem(5, true); // 5 segundos, forzar apps
if (result != SystemShutdown::ShutdownResult::SUCCESS) {
std::cerr << SystemShutdown::resultToString(result) << '\n';
}
}
}