primer commit
This commit is contained in:
60
source/core/system/debug.cpp
Normal file
60
source/core/system/debug.cpp
Normal 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
|
||||
44
source/core/system/debug.hpp
Normal file
44
source/core/system/debug.hpp
Normal 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
|
||||
308
source/core/system/director.cpp
Normal file
308
source/core/system/director.cpp
Normal 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;
|
||||
}
|
||||
26
source/core/system/director.hpp
Normal file
26
source/core/system/director.hpp
Normal 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
|
||||
};
|
||||
22
source/core/system/global_events.cpp
Normal file
22
source/core/system/global_events.cpp
Normal 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
|
||||
8
source/core/system/global_events.hpp
Normal file
8
source/core/system/global_events.hpp
Normal 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
|
||||
Reference in New Issue
Block a user