primer commit

This commit is contained in:
2025-11-23 11:44:31 +01:00
commit 6ada29eaf8
613 changed files with 484459 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
#include "core/system/debug.hpp"
#ifdef _DEBUG
#include <algorithm> // Para max
#include <memory> // Para __shared_ptr_access, shared_ptr
#include "core/rendering/text.hpp" // Para Text
#include "core/resources/resource_cache.hpp" // Para Resource
#include "utils/defines.hpp" // Para PlayArea
#include "utils/color.hpp" // Para Color
// [SINGLETON]
Debug* Debug::debug = nullptr;
// [SINGLETON] Crearemos el objeto con esta función estática
void Debug::init() {
Debug::debug = new Debug();
}
// [SINGLETON] Destruiremos el objeto con esta función estática
void Debug::destroy() {
delete Debug::debug;
}
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
auto Debug::get() -> Debug* {
return Debug::debug;
}
// Dibuja en pantalla
void Debug::render() {
auto text = Resource::Cache::get()->getText("aseprite");
int y = y_;
int w = 0;
for (const auto& s : slot_) {
text->write(x_, y, s);
w = (std::max(w, (int)s.length()));
y += text->getCharacterSize() + 1;
if (y > PlayArea::HEIGHT - text->getCharacterSize()) {
y = y_;
x_ += w * text->getCharacterSize() + 2;
}
}
y = 0;
for (const auto& l : log_) {
text->writeColored(x_ + 10, y, l, Color::index(Color::Cpc::WHITE));
y += text->getCharacterSize() + 1;
}
}
// Establece la posición donde se colocará la información de debug
void Debug::setPos(SDL_FPoint p) {
x_ = p.x;
y_ = p.y;
}
#endif // _DEBUG

View File

@@ -0,0 +1,44 @@
#pragma once
#ifdef _DEBUG
#include <SDL3/SDL.h>
#include <string> // Para string
#include <vector> // Para vector
// Clase Debug
class Debug {
public:
static void init(); // [SINGLETON] Crearemos el objeto con esta función estática
static void destroy(); // [SINGLETON] Destruiremos el objeto con esta función estática
static auto get() -> Debug*; // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
void render(); // Dibuja en pantalla
void setPos(SDL_FPoint p); // Establece la posición donde se colocará la información de debug
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } // Obtiene si el debug está activo
void add(const std::string& text) { slot_.push_back(text); } // Añade texto al slot de debug
void clear() { slot_.clear(); } // Limpia el slot de debug
void addToLog(const std::string& text) { log_.push_back(text); } // Añade texto al log
void clearLog() { log_.clear(); } // Limpia el log
void setEnabled(bool value) { enabled_ = value; } // Establece si el debug está activo
void toggleEnabled() { enabled_ = !enabled_; } // Alterna el estado del debug
private:
static Debug* debug; // [SINGLETON] Objeto privado
Debug() = default; // Constructor
~Debug() = default; // Destructor
// Variables
std::vector<std::string> slot_; // Vector con los textos a escribir
std::vector<std::string> log_; // Vector con los textos a escribir
int x_ = 0; // Posicion donde escribir el texto de debug
int y_ = 0; // Posición donde escribir el texto de debug
bool enabled_ = false; // Indica si esta activo el modo debug
};
#endif // _DEBUG

View File

@@ -0,0 +1,308 @@
#include "core/system/director.hpp"
#include <SDL3/SDL.h>
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
#include <unistd.h> // Para getuid
#include <cerrno> // Para errno, EEXIST, EACCES, ENAMETOO...
#include <cstdio> // Para printf, perror
#include <cstdlib> // Para exit, EXIT_FAILURE, srand
#include <iostream> // Para basic_ostream, operator<<, cout
#include <memory> // Para make_unique, unique_ptr
#include <string> // Para operator+, allocator, char_traits
#include "core/audio/audio.hpp" // Para Audio
#include "core/input/input.hpp" // Para Input, InputAction
#include "core/rendering/screen.hpp" // Para Screen
#include "core/resources/resource_cache.hpp" // Para Resource
#include "core/resources/resource_helper.hpp" // Para ResourceHelper
#include "core/resources/resource_list.hpp" // Para Asset, AssetType
#include "core/resources/resource_loader.hpp" // Para ResourceLoader
#include "game/options.hpp" // Para Options, options, OptionsVideo
#include "game/scene_manager.hpp" // Para SceneManager
#include "game/scenes/game.hpp" // Para Game, GameMode
#include "game/scenes/logo.hpp" // Para Logo
#include "game/scenes/title.hpp" // Para Title
#include "game/ui/notifier.hpp" // Para Notifier
#include "project.h"
#include "utils/defines.hpp" // Para WINDOW_CAPTION
#ifdef _DEBUG
#include "core/system/debug.hpp" // Para Debug
#endif
#ifndef _WIN32
#include <pwd.h>
#endif
// Constructor
Director::Director(std::vector<std::string> const& args) {
std::cout << "Game start" << '\n';
// Crea e inicializa las opciones del programa
Options::init();
// Comprueba los parametros del programa
executable_path_ = getPath(checkProgramArguments(args));
// Crea la carpeta del sistema donde guardar datos
createSystemFolder("jailgames");
createSystemFolder(std::string("jailgames/") + Project::NAME);
// Determinar el prefijo de ruta según la plataforma
#ifdef MACOS_BUNDLE
const std::string PREFIX = "/../Resources";
#else
const std::string PREFIX;
#endif
// Preparar ruta al pack (en macOS bundle está en Contents/Resources/)
std::string pack_path = executable_path_ + PREFIX + "/resources.pack";
#ifdef RELEASE_BUILD
// ============================================================
// RELEASE BUILD: Pack-first architecture
// ============================================================
std::cout << "\n** RELEASE MODE: Pack-first initialization\n";
// 1. Initialize resource pack system (required, no fallback)
std::cout << "Initializing resource pack: " << pack_path << '\n';
if (!Resource::Helper::initializeResourceSystem(pack_path, false)) {
std::cerr << "ERROR: Failed to load resources.pack (required in release builds)\n";
exit(EXIT_FAILURE);
}
// 2. Validate pack integrity
std::cout << "Validating pack integrity..." << '\n';
if (!Resource::Loader::get().validatePack()) {
std::cerr << "ERROR: Pack validation failed\n";
exit(EXIT_FAILURE);
}
// 3. Load assets.yaml from pack
std::cout << "Loading assets configuration from pack..." << '\n';
std::string assets_config = Resource::Loader::get().loadAssetsConfig();
if (assets_config.empty()) {
std::cerr << "ERROR: Failed to load assets.yaml from pack\n";
exit(EXIT_FAILURE);
}
// 4. Initialize Asset system with config from pack
// NOTE: In release, don't use executable_path or PREFIX - paths in pack are relative
// Pass empty string to avoid issues when running from different directories
Resource::List::init(""); // Empty executable_path in release
Resource::List::get()->loadFromString(assets_config, "", system_folder_); // Empty PREFIX for pack
std::cout << "Asset system initialized from pack\n";
#else
// ============================================================
// DEVELOPMENT BUILD: Filesystem-first architecture
// ============================================================
std::cout << "\n** DEVELOPMENT MODE: Filesystem-first initialization\n";
// 1. Initialize Asset system from filesystem
Resource::List::init(executable_path_);
// 2. Load asset configuration from disk
// Note: Asset verification happens during Resource::Cache::load()
setFileList();
// 3. Initialize resource pack system (optional, with fallback)
std::cout << "Initializing resource pack (development mode): " << pack_path << '\n';
Resource::Helper::initializeResourceSystem(pack_path, true);
#endif
// Configura la ruta y carga las opciones desde un fichero
Options::setConfigFile(Resource::List::get()->get("config.yaml"));
Options::loadFromFile();
// Inicializa JailAudio
Audio::init();
// Crea los objetos
Screen::init();
// Initialize resources (works for both release and development)
Resource::Cache::init();
Notifier::init("", "8bithud");
Screen::get()->setNotificationsEnabled(true);
// Special handling for gamecontrollerdb.txt - SDL needs filesystem path
#ifdef RELEASE_BUILD
// In release, construct the path manually (not from Asset which has empty executable_path)
std::string gamecontroller_db = executable_path_ + PREFIX + "/gamecontrollerdb.txt";
Input::init(gamecontroller_db);
#else
// In development, use Asset as normal
Input::init(Resource::List::get()->get("gamecontrollerdb.txt")); // Carga configuración de controles
#endif
// Aplica las teclas y botones del gamepad configurados desde Options
Input::get()->applyKeyboardBindingsFromOptions();
Input::get()->applyGamepadBindingsFromOptions();
#ifdef _DEBUG
Debug::init();
#endif
std::cout << "\n"; // Fin de inicialización de sistemas
}
Director::~Director() {
// Guarda las opciones a un fichero
Options::saveToFile();
// Destruye los singletones
#ifdef _DEBUG
Debug::destroy();
#endif
Input::destroy();
Notifier::destroy();
Resource::Cache::destroy();
Resource::Helper::shutdownResourceSystem(); // Shutdown resource pack system
Audio::destroy();
Screen::destroy();
Resource::List::destroy();
SDL_Quit();
std::cout << "\nBye!" << '\n';
}
// Comprueba los parametros del programa
auto Director::checkProgramArguments(std::vector<std::string> const& args) -> std::string {
// Iterar sobre los argumentos del programa (saltando args[0] que es el ejecutable)
for (std::size_t i = 1; i < args.size(); ++i) {
const std::string& argument = args[i];
if (argument == "--console") {
Options::console = true;
} else if (argument == "--infiniteLives") {
Options::cheats.infinite_lives = Options::Cheat::State::ENABLED;
} else if (argument == "--invincible") {
Options::cheats.invincible = Options::Cheat::State::ENABLED;
} else if (argument == "--jailEnabled") {
Options::cheats.jail_is_open = Options::Cheat::State::ENABLED;
} else if (argument == "--altSkin") {
Options::cheats.alternate_skin = Options::Cheat::State::ENABLED;
}
}
return args[0];
}
// Crea la carpeta del sistema donde guardar datos
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;
{
// Intenta crear ".config", per 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 CREATING CONFIG BASE FOLDER.");
exit(EXIT_FAILURE);
}
}
#endif
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("the parent directory does not allow write");
exit(EXIT_FAILURE);
case EEXIST:
printf("pathname already exists");
exit(EXIT_FAILURE);
case ENAMETOOLONG:
printf("pathname is too long");
exit(EXIT_FAILURE);
default:
perror("mkdir");
exit(EXIT_FAILURE);
}
}
}
}
// Carga la configuración de assets desde assets.yaml
void Director::setFileList() {
// Determinar el prefijo de ruta según la plataforma
#ifdef MACOS_BUNDLE
const std::string PREFIX = "/../Resources";
#else
const std::string PREFIX;
#endif
// Construir ruta al archivo de configuración de assets
std::string config_path = executable_path_ + PREFIX + "/config/assets.yaml";
// Cargar todos los assets desde el archivo de configuración
// La verificación de existencia de archivos se realiza durante Resource::Cache::load()
Resource::List::get()->loadFromFile(config_path, PREFIX, system_folder_);
}
// Ejecuta la seccion de juego con el logo
void Director::runLogo() {
auto logo = std::make_unique<Logo>();
logo->run();
}
// Ejecuta la seccion de juego con el titulo y los menus
void Director::runTitle() {
auto title = std::make_unique<Title>();
title->run();
}
// Ejecuta la seccion de juego donde se juega
void Director::runGame() {
Audio::get()->stopMusic();
auto game = std::make_unique<Game>(Game::Mode::GAME);
game->run();
}
auto Director::run() -> int {
// Bucle principal
while (SceneManager::current != SceneManager::Scene::QUIT) {
switch (SceneManager::current) {
case SceneManager::Scene::LOGO:
runLogo();
break;
case SceneManager::Scene::TITLE:
runTitle();
break;
case SceneManager::Scene::GAME:
runGame();
break;
default:
break;
}
}
return 0;
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // Para string
#include <vector> // Para vector
class Director {
public:
explicit Director(std::vector<std::string> const& args); // Constructor
~Director(); // Destructor
static auto run() -> int; // Bucle principal
private:
// --- Variables ---
std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos
static auto checkProgramArguments(std::vector<std::string> const& args) -> std::string; // Comprueba los parametros del programa
// --- Funciones ---
void createSystemFolder(const std::string& folder); // Crea la carpeta del sistema donde guardar datos
void setFileList(); // Carga la configuración de assets desde assets.yaml
static void runLogo(); // Ejecuta la seccion de juego con el logo
static void runTitle(); // Ejecuta la seccion de juego con el titulo y los menus
static void runGame(); // Ejecuta la seccion de juego donde se juega
};

View File

@@ -0,0 +1,22 @@
#include "core/system/global_events.hpp"
#include "core/input/mouse.hpp"
#include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio
#include "game/scene_manager.hpp" // Para SceneManager
namespace GlobalEvents {
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void handle(const SDL_Event& event) {
// Evento de salida de la aplicación
if (event.type == SDL_EVENT_QUIT) {
SceneManager::current = SceneManager::Scene::QUIT;
return;
}
if (event.type == SDL_EVENT_RENDER_DEVICE_RESET || event.type == SDL_EVENT_RENDER_TARGETS_RESET) {
// reLoadTextures();
}
Mouse::handleEvent(event);
}
} // namespace GlobalEvents

View File

@@ -0,0 +1,8 @@
#pragma once
#include <SDL3/SDL.h>
namespace GlobalEvents {
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void handle(const SDL_Event& event);
} // namespace GlobalEvents