From 70bfced50d381050ba12c742902843735eb50a9b Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Fri, 31 Oct 2025 12:52:22 +0100 Subject: [PATCH] =?UTF-8?q?migrat=20Assets=20a=20la=20ultima=20versi=C3=B3?= =?UTF-8?q?=20(fitxers=20no=20hardcoded)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 69 ++++- config/assets.txt | 396 +++++++++++++++++++++++++++++ source/core/rendering/screen.cpp | 2 +- source/core/resources/asset.cpp | 340 +++++++++++++++++++------ source/core/resources/asset.hpp | 128 +++++----- source/core/resources/resource.cpp | 34 +-- source/core/system/director.cpp | 231 +---------------- 7 files changed, 804 insertions(+), 396 deletions(-) create mode 100644 config/assets.txt diff --git a/CLAUDE.md b/CLAUDE.md index 6338a64..6e6fdfa 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -181,6 +181,9 @@ source/ │ └── utils.hpp/cpp # Helper functions (colors, math) └── main.cpp # Application entry point +config/ # Configuration files +└── assets.txt # Asset registry (text-based configuration) + data/ # Game assets ├── font/ # Bitmap fonts + descriptors ├── palette/ # Color palettes (.pal files) @@ -386,13 +389,17 @@ Game::run() { ``` Director::setFileList() - ├─ Asset::add(file, type) - Register all assets - └─ Asset::check() - Verify files exist + ├─ Asset::loadFromFile(config_path, PREFIX, system_folder_) + │ ├─ Read config/assets.txt - Parse text configuration file + │ ├─ Parse each line: TYPE|PATH|OPTIONS - Extract asset information + │ ├─ Replace variables (${PREFIX}, ${SYSTEM_FOLDER}) + │ └─ Store in unordered_map (O(1) lookup) - Fast asset path retrieval + └─ Asset::check() - Verify required files exist Game Scene initialization └─ Resource::init() - Loads all resources ├─ loadSounds() - WAV files - ├─ loadMusics() - OGG files + ├─ loadMusics() - OGG files ├─ loadSurfaces() - GIF/PNG images ├─ loadAnimations() - .ani animation definitions ├─ loadTileMaps() - .room tilemap data @@ -568,7 +575,7 @@ Achievements trigger notifications on unlock. | `Input` | Keyboard & gamepad input | Singleton | | `Audio` | Music and SFX playback | Singleton | | `Resource` | Asset caching and loading | Singleton | -| `Asset` | Asset path registry | Singleton | +| `Asset` | Asset path registry from config/assets.txt, O(1) lookups, variable substitution | Singleton | | `Debug` | Debug overlay information | Singleton | | `globalEvents` | Global SDL event handling (quit, device reset, mouse) | Namespace | @@ -631,12 +638,16 @@ Achievements trigger notifications on unlock. ### Adding Game Assets 1. Place file in `data/` directory -2. Register in `Director::setFileList()`: - ```cpp - Asset::get()->add("/data/path/file.ext", AssetType::TYPE); +2. Add entry to `config/assets.txt`: ``` -3. Resource loads automatically during `Resource::init()` -4. Access via: `Resource::get()->getSurface("name")` + TYPE|${PREFIX}/data/path/file.ext + ``` + Available types: `DATA`, `BITMAP`, `ANIMATION`, `MUSIC`, `SOUND`, `FONT`, `ROOM`, `TILEMAP`, `PALETTE` +3. Optional flags can be added: `TYPE|${PREFIX}/path/file.ext|optional,absolute` +4. Resource loads automatically during `Resource::init()` +5. Access via: `Resource::get()->getSurface("name")` + +**Note:** No recompilation needed when adding/removing/modifying assets in `config/assets.txt` ### Modifying Collision Detection @@ -692,6 +703,40 @@ In debug builds (`#ifdef DEBUG`), renders: ## 11. File Format Reference +### Asset Configuration File (config/assets.txt) +Text-based asset registry with pipe-delimited format: +``` +# Format: TYPE|PATH [|OPTIONS] +# Comments start with # or ; +# Variables: ${PREFIX}, ${SYSTEM_FOLDER} +# Options: optional, absolute (comma-separated) + +# Example entries: +BITMAP|${PREFIX}/data/player/player.gif +ANIMATION|${PREFIX}/data/player/player.ani +MUSIC|${PREFIX}/data/music/title.ogg +DATA|${SYSTEM_FOLDER}/config.txt|optional,absolute +``` + +**Available Asset Types:** +- `DATA` - General data files (text, JSON, etc.) +- `BITMAP` - Images (GIF, PNG) +- `ANIMATION` - Animation definition files (.ani) +- `MUSIC` - Music files (OGG) +- `SOUND` - Sound effects (WAV) +- `FONT` - Font definition files +- `ROOM` - Room data files (.room) +- `TILEMAP` - Tilemap files (.tmx) +- `PALETTE` - Color palette files (.pal) + +**Options:** +- `optional` - File is not required (won't fail check if missing) +- `absolute` - Path is absolute (not relative to executable) + +**Variables:** +- `${PREFIX}` - Replaced with `/../Resources` on macOS bundles, empty otherwise +- `${SYSTEM_FOLDER}` - Replaced with user's system config folder + ### Animation Files (.ani) List of animation names, one per line: ``` @@ -741,9 +786,11 @@ Binary 256-color palette format (256 × 4 bytes RGBA). - `Player::update()` - Physics and movement ### For Asset Management -- `Asset::add()` - Asset registration +- `config/assets.txt` - Asset configuration file (text-based, no recompilation needed) +- `Asset::loadFromFile()` - Loads assets from config file +- `Asset::get()` - Retrieves asset path (O(1) lookup with unordered_map) - `Resource::load()` - Asset loading -- `Director::setFileList()` - Complete asset registry +- `Director::setFileList()` - Calls `Asset::loadFromFile()` with PREFIX and system_folder --- diff --git a/config/assets.txt b/config/assets.txt new file mode 100644 index 0000000..ff49ad9 --- /dev/null +++ b/config/assets.txt @@ -0,0 +1,396 @@ +# JailDoctor's Dilemma - Asset Configuration +# Format: TYPE|PATH [|OPTIONS] +# Options: optional, absolute (comma-separated) +# Variables: ${PREFIX}, ${SYSTEM_FOLDER} + +# =================================================================== +# FONTS +# =================================================================== +BITMAP|${PREFIX}/data/font/smb2.gif +FONT|${PREFIX}/data/font/smb2.txt +BITMAP|${PREFIX}/data/font/debug.gif +FONT|${PREFIX}/data/font/debug.txt +BITMAP|${PREFIX}/data/font/gauntlet.gif +FONT|${PREFIX}/data/font/gauntlet.txt +BITMAP|${PREFIX}/data/font/subatomic.gif +FONT|${PREFIX}/data/font/subatomic.txt +BITMAP|${PREFIX}/data/font/8bithud.gif +FONT|${PREFIX}/data/font/8bithud.txt + +# =================================================================== +# PALETTES +# =================================================================== +PALETTE|${PREFIX}/data/palette/zx-spectrum.pal +PALETTE|${PREFIX}/data/palette/zx-spectrum-adjusted.pal +PALETTE|${PREFIX}/data/palette/zxarne-5-2.pal +PALETTE|${PREFIX}/data/palette/black-and-white.pal +PALETTE|${PREFIX}/data/palette/green-phosphor.pal +PALETTE|${PREFIX}/data/palette/orange-screen.pal +PALETTE|${PREFIX}/data/palette/ruzx-spectrum.pal +PALETTE|${PREFIX}/data/palette/ruzx-spectrum-revision-2.pal +PALETTE|${PREFIX}/data/palette/pico-8.pal +PALETTE|${PREFIX}/data/palette/sweetie-16.pal +PALETTE|${PREFIX}/data/palette/island-joy-16.pal +PALETTE|${PREFIX}/data/palette/lost-century.pal +PALETTE|${PREFIX}/data/palette/na16.pal +PALETTE|${PREFIX}/data/palette/steam-lords.pal + +# =================================================================== +# SHADERS +# =================================================================== +DATA|${PREFIX}/data/shaders/crtpi_vertex.glsl +DATA|${PREFIX}/data/shaders/crtpi_fragment.glsl +DATA|${PREFIX}/data/shaders/crtpi_vertex_es.glsl +DATA|${PREFIX}/data/shaders/crtpi_fragment_es.glsl + +# =================================================================== +# INPUT DATA +# =================================================================== +DATA|${PREFIX}/data/input/gamecontrollerdb.txt + +# =================================================================== +# SYSTEM FILES (optional, absolute paths) +# =================================================================== +DATA|${SYSTEM_FOLDER}/config.txt|optional,absolute +DATA|${SYSTEM_FOLDER}/stats_buffer.csv|optional,absolute +DATA|${SYSTEM_FOLDER}/stats.csv|optional,absolute +DATA|${SYSTEM_FOLDER}/cheevos.bin|optional,absolute + +# =================================================================== +# ROOMS AND TILEMAPS (60 rooms) +# =================================================================== +TILEMAP|${PREFIX}/data/room/01.tmx +ROOM|${PREFIX}/data/room/01.room +TILEMAP|${PREFIX}/data/room/02.tmx +ROOM|${PREFIX}/data/room/02.room +TILEMAP|${PREFIX}/data/room/03.tmx +ROOM|${PREFIX}/data/room/03.room +TILEMAP|${PREFIX}/data/room/04.tmx +ROOM|${PREFIX}/data/room/04.room +TILEMAP|${PREFIX}/data/room/05.tmx +ROOM|${PREFIX}/data/room/05.room +TILEMAP|${PREFIX}/data/room/06.tmx +ROOM|${PREFIX}/data/room/06.room +TILEMAP|${PREFIX}/data/room/07.tmx +ROOM|${PREFIX}/data/room/07.room +TILEMAP|${PREFIX}/data/room/08.tmx +ROOM|${PREFIX}/data/room/08.room +TILEMAP|${PREFIX}/data/room/09.tmx +ROOM|${PREFIX}/data/room/09.room +TILEMAP|${PREFIX}/data/room/10.tmx +ROOM|${PREFIX}/data/room/10.room +TILEMAP|${PREFIX}/data/room/11.tmx +ROOM|${PREFIX}/data/room/11.room +TILEMAP|${PREFIX}/data/room/12.tmx +ROOM|${PREFIX}/data/room/12.room +TILEMAP|${PREFIX}/data/room/13.tmx +ROOM|${PREFIX}/data/room/13.room +TILEMAP|${PREFIX}/data/room/14.tmx +ROOM|${PREFIX}/data/room/14.room +TILEMAP|${PREFIX}/data/room/15.tmx +ROOM|${PREFIX}/data/room/15.room +TILEMAP|${PREFIX}/data/room/16.tmx +ROOM|${PREFIX}/data/room/16.room +TILEMAP|${PREFIX}/data/room/17.tmx +ROOM|${PREFIX}/data/room/17.room +TILEMAP|${PREFIX}/data/room/18.tmx +ROOM|${PREFIX}/data/room/18.room +TILEMAP|${PREFIX}/data/room/19.tmx +ROOM|${PREFIX}/data/room/19.room +TILEMAP|${PREFIX}/data/room/20.tmx +ROOM|${PREFIX}/data/room/20.room +TILEMAP|${PREFIX}/data/room/21.tmx +ROOM|${PREFIX}/data/room/21.room +TILEMAP|${PREFIX}/data/room/22.tmx +ROOM|${PREFIX}/data/room/22.room +TILEMAP|${PREFIX}/data/room/23.tmx +ROOM|${PREFIX}/data/room/23.room +TILEMAP|${PREFIX}/data/room/24.tmx +ROOM|${PREFIX}/data/room/24.room +TILEMAP|${PREFIX}/data/room/25.tmx +ROOM|${PREFIX}/data/room/25.room +TILEMAP|${PREFIX}/data/room/26.tmx +ROOM|${PREFIX}/data/room/26.room +TILEMAP|${PREFIX}/data/room/27.tmx +ROOM|${PREFIX}/data/room/27.room +TILEMAP|${PREFIX}/data/room/28.tmx +ROOM|${PREFIX}/data/room/28.room +TILEMAP|${PREFIX}/data/room/29.tmx +ROOM|${PREFIX}/data/room/29.room +TILEMAP|${PREFIX}/data/room/30.tmx +ROOM|${PREFIX}/data/room/30.room +TILEMAP|${PREFIX}/data/room/31.tmx +ROOM|${PREFIX}/data/room/31.room +TILEMAP|${PREFIX}/data/room/32.tmx +ROOM|${PREFIX}/data/room/32.room +TILEMAP|${PREFIX}/data/room/33.tmx +ROOM|${PREFIX}/data/room/33.room +TILEMAP|${PREFIX}/data/room/34.tmx +ROOM|${PREFIX}/data/room/34.room +TILEMAP|${PREFIX}/data/room/35.tmx +ROOM|${PREFIX}/data/room/35.room +TILEMAP|${PREFIX}/data/room/36.tmx +ROOM|${PREFIX}/data/room/36.room +TILEMAP|${PREFIX}/data/room/37.tmx +ROOM|${PREFIX}/data/room/37.room +TILEMAP|${PREFIX}/data/room/38.tmx +ROOM|${PREFIX}/data/room/38.room +TILEMAP|${PREFIX}/data/room/39.tmx +ROOM|${PREFIX}/data/room/39.room +TILEMAP|${PREFIX}/data/room/40.tmx +ROOM|${PREFIX}/data/room/40.room +TILEMAP|${PREFIX}/data/room/41.tmx +ROOM|${PREFIX}/data/room/41.room +TILEMAP|${PREFIX}/data/room/42.tmx +ROOM|${PREFIX}/data/room/42.room +TILEMAP|${PREFIX}/data/room/43.tmx +ROOM|${PREFIX}/data/room/43.room +TILEMAP|${PREFIX}/data/room/44.tmx +ROOM|${PREFIX}/data/room/44.room +TILEMAP|${PREFIX}/data/room/45.tmx +ROOM|${PREFIX}/data/room/45.room +TILEMAP|${PREFIX}/data/room/46.tmx +ROOM|${PREFIX}/data/room/46.room +TILEMAP|${PREFIX}/data/room/47.tmx +ROOM|${PREFIX}/data/room/47.room +TILEMAP|${PREFIX}/data/room/48.tmx +ROOM|${PREFIX}/data/room/48.room +TILEMAP|${PREFIX}/data/room/49.tmx +ROOM|${PREFIX}/data/room/49.room +TILEMAP|${PREFIX}/data/room/50.tmx +ROOM|${PREFIX}/data/room/50.room +TILEMAP|${PREFIX}/data/room/51.tmx +ROOM|${PREFIX}/data/room/51.room +TILEMAP|${PREFIX}/data/room/52.tmx +ROOM|${PREFIX}/data/room/52.room +TILEMAP|${PREFIX}/data/room/53.tmx +ROOM|${PREFIX}/data/room/53.room +TILEMAP|${PREFIX}/data/room/54.tmx +ROOM|${PREFIX}/data/room/54.room +TILEMAP|${PREFIX}/data/room/55.tmx +ROOM|${PREFIX}/data/room/55.room +TILEMAP|${PREFIX}/data/room/56.tmx +ROOM|${PREFIX}/data/room/56.room +TILEMAP|${PREFIX}/data/room/57.tmx +ROOM|${PREFIX}/data/room/57.room +TILEMAP|${PREFIX}/data/room/58.tmx +ROOM|${PREFIX}/data/room/58.room +TILEMAP|${PREFIX}/data/room/59.tmx +ROOM|${PREFIX}/data/room/59.room +TILEMAP|${PREFIX}/data/room/60.tmx +ROOM|${PREFIX}/data/room/60.room + +# =================================================================== +# TILESETS +# =================================================================== +BITMAP|${PREFIX}/data/tilesets/standard.gif + +# =================================================================== +# ENEMIES +# =================================================================== +ANIMATION|${PREFIX}/data/enemies/abad_bell.ani +BITMAP|${PREFIX}/data/enemies/abad_bell.gif +ANIMATION|${PREFIX}/data/enemies/abad.ani +BITMAP|${PREFIX}/data/enemies/abad.gif +ANIMATION|${PREFIX}/data/enemies/amstrad_cs.ani +BITMAP|${PREFIX}/data/enemies/amstrad_cs.gif +ANIMATION|${PREFIX}/data/enemies/flying_arounder.ani +BITMAP|${PREFIX}/data/enemies/flying_arounder.gif +ANIMATION|${PREFIX}/data/enemies/stopped_arounder.ani +BITMAP|${PREFIX}/data/enemies/stopped_arounder.gif +ANIMATION|${PREFIX}/data/enemies/walking_arounder.ani +BITMAP|${PREFIX}/data/enemies/walking_arounder.gif +ANIMATION|${PREFIX}/data/enemies/arounders_door.ani +BITMAP|${PREFIX}/data/enemies/arounders_door.gif +ANIMATION|${PREFIX}/data/enemies/arounders_machine.ani +BITMAP|${PREFIX}/data/enemies/arounders_machine.gif +ANIMATION|${PREFIX}/data/enemies/bat.ani +BITMAP|${PREFIX}/data/enemies/bat.gif +ANIMATION|${PREFIX}/data/enemies/batman_bell.ani +BITMAP|${PREFIX}/data/enemies/batman_bell.gif +ANIMATION|${PREFIX}/data/enemies/batman_fire.ani +BITMAP|${PREFIX}/data/enemies/batman_fire.gif +ANIMATION|${PREFIX}/data/enemies/batman.ani +BITMAP|${PREFIX}/data/enemies/batman.gif +ANIMATION|${PREFIX}/data/enemies/bell.ani +BITMAP|${PREFIX}/data/enemies/bell.gif +ANIMATION|${PREFIX}/data/enemies/bin.ani +BITMAP|${PREFIX}/data/enemies/bin.gif +ANIMATION|${PREFIX}/data/enemies/bird.ani +BITMAP|${PREFIX}/data/enemies/bird.gif +ANIMATION|${PREFIX}/data/enemies/breakout.ani +BITMAP|${PREFIX}/data/enemies/breakout.gif +ANIMATION|${PREFIX}/data/enemies/bry.ani +BITMAP|${PREFIX}/data/enemies/bry.gif +ANIMATION|${PREFIX}/data/enemies/chip.ani +BITMAP|${PREFIX}/data/enemies/chip.gif +ANIMATION|${PREFIX}/data/enemies/code.ani +BITMAP|${PREFIX}/data/enemies/code.gif +ANIMATION|${PREFIX}/data/enemies/congo.ani +BITMAP|${PREFIX}/data/enemies/congo.gif +ANIMATION|${PREFIX}/data/enemies/crosshair.ani +BITMAP|${PREFIX}/data/enemies/crosshair.gif +ANIMATION|${PREFIX}/data/enemies/demon.ani +BITMAP|${PREFIX}/data/enemies/demon.gif +ANIMATION|${PREFIX}/data/enemies/dimallas.ani +BITMAP|${PREFIX}/data/enemies/dimallas.gif +ANIMATION|${PREFIX}/data/enemies/floppy.ani +BITMAP|${PREFIX}/data/enemies/floppy.gif +ANIMATION|${PREFIX}/data/enemies/dong.ani +BITMAP|${PREFIX}/data/enemies/dong.gif +ANIMATION|${PREFIX}/data/enemies/guitar.ani +BITMAP|${PREFIX}/data/enemies/guitar.gif +ANIMATION|${PREFIX}/data/enemies/heavy.ani +BITMAP|${PREFIX}/data/enemies/heavy.gif +ANIMATION|${PREFIX}/data/enemies/jailer_#1.ani +BITMAP|${PREFIX}/data/enemies/jailer_#1.gif +ANIMATION|${PREFIX}/data/enemies/jailer_#2.ani +BITMAP|${PREFIX}/data/enemies/jailer_#2.gif +ANIMATION|${PREFIX}/data/enemies/jailer_#3.ani +BITMAP|${PREFIX}/data/enemies/jailer_#3.gif +ANIMATION|${PREFIX}/data/enemies/jailbattle_alien.ani +BITMAP|${PREFIX}/data/enemies/jailbattle_alien.gif +ANIMATION|${PREFIX}/data/enemies/jailbattle_human.ani +BITMAP|${PREFIX}/data/enemies/jailbattle_human.gif +ANIMATION|${PREFIX}/data/enemies/jeannine.ani +BITMAP|${PREFIX}/data/enemies/jeannine.gif +ANIMATION|${PREFIX}/data/enemies/lamp.ani +BITMAP|${PREFIX}/data/enemies/lamp.gif +ANIMATION|${PREFIX}/data/enemies/lord_abad.ani +BITMAP|${PREFIX}/data/enemies/lord_abad.gif +ANIMATION|${PREFIX}/data/enemies/matatunos.ani +BITMAP|${PREFIX}/data/enemies/matatunos.gif +ANIMATION|${PREFIX}/data/enemies/mummy.ani +BITMAP|${PREFIX}/data/enemies/mummy.gif +ANIMATION|${PREFIX}/data/enemies/paco.ani +BITMAP|${PREFIX}/data/enemies/paco.gif +ANIMATION|${PREFIX}/data/enemies/elsa.ani +BITMAP|${PREFIX}/data/enemies/elsa.gif +ANIMATION|${PREFIX}/data/enemies/qvoid.ani +BITMAP|${PREFIX}/data/enemies/qvoid.gif +ANIMATION|${PREFIX}/data/enemies/robot.ani +BITMAP|${PREFIX}/data/enemies/robot.gif +ANIMATION|${PREFIX}/data/enemies/sam.ani +BITMAP|${PREFIX}/data/enemies/sam.gif +ANIMATION|${PREFIX}/data/enemies/shock.ani +BITMAP|${PREFIX}/data/enemies/shock.gif +ANIMATION|${PREFIX}/data/enemies/sigmasua.ani +BITMAP|${PREFIX}/data/enemies/sigmasua.gif +ANIMATION|${PREFIX}/data/enemies/spark.ani +BITMAP|${PREFIX}/data/enemies/spark.gif +ANIMATION|${PREFIX}/data/enemies/special/aerojailer.ani +BITMAP|${PREFIX}/data/enemies/special/aerojailer.gif +ANIMATION|${PREFIX}/data/enemies/special/arounder.ani +BITMAP|${PREFIX}/data/enemies/special/arounder.gif +ANIMATION|${PREFIX}/data/enemies/special/pepe_rosita_job.ani +BITMAP|${PREFIX}/data/enemies/special/pepe_rosita_job.gif +ANIMATION|${PREFIX}/data/enemies/special/shooting_star.ani +BITMAP|${PREFIX}/data/enemies/special/shooting_star.gif +ANIMATION|${PREFIX}/data/enemies/spider.ani +BITMAP|${PREFIX}/data/enemies/spider.gif +ANIMATION|${PREFIX}/data/enemies/tree_thing.ani +BITMAP|${PREFIX}/data/enemies/tree_thing.gif +ANIMATION|${PREFIX}/data/enemies/tuno.ani +BITMAP|${PREFIX}/data/enemies/tuno.gif +ANIMATION|${PREFIX}/data/enemies/tv_panel.ani +BITMAP|${PREFIX}/data/enemies/tv_panel.gif +ANIMATION|${PREFIX}/data/enemies/tv.ani +BITMAP|${PREFIX}/data/enemies/tv.gif +ANIMATION|${PREFIX}/data/enemies/upv_student.ani +BITMAP|${PREFIX}/data/enemies/upv_student.gif +ANIMATION|${PREFIX}/data/enemies/wave.ani +BITMAP|${PREFIX}/data/enemies/wave.gif +ANIMATION|${PREFIX}/data/enemies/z80.ani +BITMAP|${PREFIX}/data/enemies/z80.gif + +# =================================================================== +# PLAYER +# =================================================================== +BITMAP|${PREFIX}/data/player/player.gif +ANIMATION|${PREFIX}/data/player/player.ani +BITMAP|${PREFIX}/data/player/player2.gif +ANIMATION|${PREFIX}/data/player/player2.ani +BITMAP|${PREFIX}/data/player/player_game_over.gif +ANIMATION|${PREFIX}/data/player/player_game_over.ani + +# =================================================================== +# ITEMS +# =================================================================== +BITMAP|${PREFIX}/data/items/items.gif + +# =================================================================== +# MUSIC +# =================================================================== +MUSIC|${PREFIX}/data/music/title.ogg +MUSIC|${PREFIX}/data/music/game.ogg +MUSIC|${PREFIX}/data/music/loading_sound1.ogg +MUSIC|${PREFIX}/data/music/loading_sound2.ogg +MUSIC|${PREFIX}/data/music/loading_sound3.ogg +MUSIC|${PREFIX}/data/music/ending1.ogg +MUSIC|${PREFIX}/data/music/ending2.ogg +MUSIC|${PREFIX}/data/music/game_over.ogg + +# =================================================================== +# SOUND EFFECTS +# =================================================================== +SOUND|${PREFIX}/data/sound/item.wav +SOUND|${PREFIX}/data/sound/death.wav +SOUND|${PREFIX}/data/sound/notify.wav + +# Jump sounds (1-24) +SOUND|${PREFIX}/data/sound/jump1.wav +SOUND|${PREFIX}/data/sound/jump2.wav +SOUND|${PREFIX}/data/sound/jump3.wav +SOUND|${PREFIX}/data/sound/jump4.wav +SOUND|${PREFIX}/data/sound/jump5.wav +SOUND|${PREFIX}/data/sound/jump6.wav +SOUND|${PREFIX}/data/sound/jump7.wav +SOUND|${PREFIX}/data/sound/jump8.wav +SOUND|${PREFIX}/data/sound/jump9.wav +SOUND|${PREFIX}/data/sound/jump10.wav +SOUND|${PREFIX}/data/sound/jump11.wav +SOUND|${PREFIX}/data/sound/jump12.wav +SOUND|${PREFIX}/data/sound/jump13.wav +SOUND|${PREFIX}/data/sound/jump14.wav +SOUND|${PREFIX}/data/sound/jump15.wav +SOUND|${PREFIX}/data/sound/jump16.wav +SOUND|${PREFIX}/data/sound/jump17.wav +SOUND|${PREFIX}/data/sound/jump18.wav +SOUND|${PREFIX}/data/sound/jump19.wav +SOUND|${PREFIX}/data/sound/jump20.wav +SOUND|${PREFIX}/data/sound/jump21.wav +SOUND|${PREFIX}/data/sound/jump22.wav +SOUND|${PREFIX}/data/sound/jump23.wav +SOUND|${PREFIX}/data/sound/jump24.wav + +# =================================================================== +# LOGO +# =================================================================== +BITMAP|${PREFIX}/data/logo/jailgames.gif +BITMAP|${PREFIX}/data/logo/since_1998.gif + +# =================================================================== +# LOADING SCREEN +# =================================================================== +BITMAP|${PREFIX}/data/loading/loading_screen_bn.gif +BITMAP|${PREFIX}/data/loading/loading_screen_color.gif + +# =================================================================== +# TITLE SCREEN +# =================================================================== +BITMAP|${PREFIX}/data/title/title_logo.gif + +# =================================================================== +# ENDING SCREENS +# =================================================================== +BITMAP|${PREFIX}/data/ending/ending1.gif +BITMAP|${PREFIX}/data/ending/ending2.gif +BITMAP|${PREFIX}/data/ending/ending3.gif +BITMAP|${PREFIX}/data/ending/ending4.gif +BITMAP|${PREFIX}/data/ending/ending5.gif + +# =================================================================== +# CREDITS +# =================================================================== +BITMAP|${PREFIX}/data/credits/shine.gif +ANIMATION|${PREFIX}/data/credits/shine.ani diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 678f64d..75b59c2 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -38,7 +38,7 @@ auto Screen::get() -> Screen* { // Constructor Screen::Screen() - : palettes_(Asset::get()->getListByType(AssetType::PALETTE)) { + : palettes_(Asset::get()->getListByType(Asset::Type::PALETTE)) { // Arranca SDL VIDEO, crea la ventana y el renderizador initSDLVideo(); diff --git a/source/core/resources/asset.cpp b/source/core/resources/asset.cpp index 9d72f71..4b0b9fd 100644 --- a/source/core/resources/asset.cpp +++ b/source/core/resources/asset.cpp @@ -1,79 +1,205 @@ #include "core/resources/asset.hpp" -#include // Para find_if, max -#include // Para basic_ostream, operator<<, basic_ifstream, endl -#include // Para cout -#include // Para allocator, char_traits, string, operator+, oper... +#include // Para SDL_LogWarn, SDL_LogCategory, SDL_LogError + +#include // Para sort +#include // Para size_t +#include // Para exception +#include // Para exists, path +#include // Para ifstream, istringstream +#include // Para cout +#include // Para istringstream +#include // Para runtime_error #include "utils/utils.hpp" // Para getFileName, printWithDots -// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado -Asset* Asset::asset = nullptr; +// Singleton +Asset* Asset::instance = nullptr; -// [SINGLETON] Crearemos el objeto asset con esta función estática void Asset::init(const std::string& executable_path) { - Asset::asset = new Asset(executable_path); + Asset::instance = new Asset(executable_path); } -// [SINGLETON] Destruiremos el objeto asset con esta función estática void Asset::destroy() { - delete Asset::asset; + delete Asset::instance; } -// [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él auto Asset::get() -> Asset* { - return Asset::asset; + return Asset::instance; +} + +// Añade un elemento al mapa (función auxiliar) +void Asset::addToMap(const std::string& file_path, Type type, bool required, bool absolute) { + std::string full_path = absolute ? file_path : executable_path_ + file_path; + std::string filename = getFileName(full_path); + + // Verificar si ya existe el archivo + if (file_list_.find(filename) != file_list_.end()) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Warning: Asset '%s' already exists, overwriting", + filename.c_str()); + } + + file_list_.emplace(filename, Item{std::move(full_path), type, required}); } // Añade un elemento a la lista -void Asset::add(const std::string& file, AssetType type, bool required, bool absolute) { - file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required); - longest_name_ = std::max(longest_name_, static_cast(file_list_.back().file.size())); +void Asset::add(const std::string& file_path, Type type, bool required, bool absolute) { + addToMap(file_path, type, required, absolute); } -// Devuelve la ruta completa a un fichero a partir de una cadena -auto Asset::get(const std::string& text) const -> std::string { - auto it = std::ranges::find_if(file_list_, [&text](const auto& f) { - return getFileName(f.file) == text; - }); - - if (it != file_list_.end()) { - return it->file; +// Carga recursos desde un archivo de configuración con soporte para variables +void Asset::loadFromFile(const std::string& config_file_path, const std::string& prefix, const std::string& system_folder) { + std::ifstream file(config_file_path); + if (!file.is_open()) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Error: Cannot open config file: %s", + config_file_path.c_str()); + return; } - std::cout << "Warning: file " << text << " not found" << '\n'; + + std::string line; + int line_number = 0; + + while (std::getline(file, line)) { + ++line_number; + + // Limpiar espacios en blanco al principio y final + line.erase(0, line.find_first_not_of(" \t\r")); + line.erase(line.find_last_not_of(" \t\r") + 1); + + // Ignorar líneas vacías y comentarios + if (line.empty() || line[0] == '#' || line[0] == ';') { + continue; + } + + // Dividir la línea por el separador '|' + std::vector parts; + std::istringstream iss(line); + std::string part; + + while (std::getline(iss, part, '|')) { + parts.push_back(part); + } + + // Verificar que tenemos al menos tipo y ruta + if (parts.size() < 2) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Warning: Malformed line %d in config file (insufficient fields)", + line_number); + continue; + } + + try { + const std::string& type_str = parts[0]; + std::string path = parts[1]; + + // Valores por defecto + bool required = true; + bool absolute = false; + + // Si hay opciones en el tercer campo, parsearlas + if (parts.size() >= 3) { + parseOptions(parts[2], required, absolute); + } + + // Reemplazar variables en la ruta + path = replaceVariables(path, prefix, system_folder); + + // Parsear el tipo de asset + Type type = parseAssetType(type_str); + + // Añadir al mapa + addToMap(path, type, required, absolute); + + } catch (const std::exception& e) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Error parsing line %d in config file: %s", + line_number, + e.what()); + } + } + + std::cout << "Loaded " << file_list_.size() << " assets from config file" << '\n'; + file.close(); +} + +// Devuelve la ruta completa a un fichero (búsqueda O(1)) +auto Asset::get(const std::string& filename) const -> std::string { + auto it = file_list_.find(filename); + if (it != file_list_.end()) { + return it->second.file; + } + + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found", filename.c_str()); return ""; } +// Carga datos del archivo +auto Asset::loadData(const std::string& filename) const -> std::vector { + auto it = file_list_.find(filename); + if (it != file_list_.end()) { + std::ifstream file(it->second.file, std::ios::binary); + if (!file.is_open()) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Warning: Could not open file %s for data loading", + filename.c_str()); + return {}; + } + + // Obtener tamaño del archivo + file.seekg(0, std::ios::end); + size_t size = file.tellg(); + file.seekg(0, std::ios::beg); + + // Leer datos + std::vector data(size); + file.read(reinterpret_cast(data.data()), size); + file.close(); + + return data; + } + + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found for data loading", filename.c_str()); + return {}; +} + +// Verifica si un recurso existe +auto Asset::exists(const std::string& filename) const -> bool { + return file_list_.find(filename) != file_list_.end(); +} + // Comprueba que existen todos los elementos auto Asset::check() const -> bool { bool success = true; std::cout << "\n** CHECKING FILES" << '\n'; - // std::cout << "Executable path is: " << executable_path_ << std::endl; - // std::cout << "Sample filepath: " << file_list_.back().file << std::endl; + // Agrupar por tipo para mostrar organizado + std::unordered_map> by_type; - // Comprueba la lista de ficheros clasificandolos por tipo - for (int type = 0; type < static_cast(AssetType::MAX_ASSET_TYPE); ++type) { - // Comprueba si hay ficheros de ese tipo - bool any = false; - - for (const auto& f : file_list_) { - if (f.required && f.type == static_cast(type)) { - any = true; - } + for (const auto& [filename, item] : file_list_) { + if (item.required) { + by_type[item.type].push_back(&item); } + } - // Si hay ficheros de ese tipo, comprueba si existen - if (any) { - std::cout << "\n>> " << getTypeName(static_cast(type)).c_str() << " FILES" << '\n'; + // Verificar por tipo + for (int type = 0; type < static_cast(Type::SIZE); ++type) { + Type asset_type = static_cast(type); - for (const auto& f : file_list_) { - if (f.required && f.type == static_cast(type)) { - success &= checkFile(f.file); + if (by_type.find(asset_type) != by_type.end()) { + std::cout << "\n>> " << getTypeName(asset_type) << " FILES" << '\n'; + + bool type_success = true; + for (const auto* item : by_type[asset_type]) { + if (!checkFile(item->file)) { + success = false; + type_success = false; } } - if (success) { + + if (type_success) { std::cout << " All files are OK." << '\n'; } } @@ -86,7 +212,7 @@ auto Asset::check() const -> bool { } // Comprueba que existe un fichero -auto Asset::checkFile(const std::string& path) -> bool { +auto Asset::checkFile(const std::string& path) const -> bool { std::ifstream file(path); bool success = file.good(); file.close(); @@ -98,60 +224,120 @@ auto Asset::checkFile(const std::string& path) -> bool { return success; } +// Parsea string a Type +auto Asset::parseAssetType(const std::string& type_str) -> Type { + if (type_str == "DATA") { + return Type::DATA; + } + if (type_str == "BITMAP") { + return Type::BITMAP; + } + if (type_str == "ANIMATION") { + return Type::ANIMATION; + } + if (type_str == "MUSIC") { + return Type::MUSIC; + } + if (type_str == "SOUND") { + return Type::SOUND; + } + if (type_str == "FONT") { + return Type::FONT; + } + if (type_str == "ROOM") { + return Type::ROOM; + } + if (type_str == "TILEMAP") { + return Type::TILEMAP; + } + if (type_str == "PALETTE") { + return Type::PALETTE; + } + + throw std::runtime_error("Unknown asset type: " + type_str); +} + // Devuelve el nombre del tipo de recurso -auto Asset::getTypeName(AssetType type) -> std::string { +auto Asset::getTypeName(Type type) -> std::string { switch (type) { - case AssetType::DATA: + case Type::DATA: return "DATA"; - break; - - case AssetType::BITMAP: + case Type::BITMAP: return "BITMAP"; - break; - - case AssetType::ANIMATION: + case Type::ANIMATION: return "ANIMATION"; - break; - - case AssetType::MUSIC: + case Type::MUSIC: return "MUSIC"; - break; - - case AssetType::SOUND: + case Type::SOUND: return "SOUND"; - break; - - case AssetType::FONT: + case Type::FONT: return "FONT"; - break; - - case AssetType::ROOM: + case Type::ROOM: return "ROOM"; - break; - - case AssetType::TILEMAP: + case Type::TILEMAP: return "TILEMAP"; - break; - - case AssetType::PALETTE: + case Type::PALETTE: return "PALETTE"; - break; - default: return "ERROR"; - break; } } // Devuelve la lista de recursos de un tipo -auto Asset::getListByType(AssetType type) const -> std::vector { +auto Asset::getListByType(Type type) const -> std::vector { std::vector list; - for (const auto& f : file_list_) { - if (f.type == type) { - list.push_back(f.file); + for (const auto& [filename, item] : file_list_) { + if (item.type == type) { + list.push_back(item.file); } } + // Ordenar alfabéticamente para garantizar orden consistente + std::ranges::sort(list); + return list; -} \ No newline at end of file +} + +// Reemplaza variables en las rutas +auto Asset::replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string { + std::string result = path; + + // Reemplazar ${PREFIX} + size_t pos = 0; + while ((pos = result.find("${PREFIX}", pos)) != std::string::npos) { + result.replace(pos, 9, prefix); // 9 = longitud de "${PREFIX}" + pos += prefix.length(); + } + + // Reemplazar ${SYSTEM_FOLDER} + pos = 0; + while ((pos = result.find("${SYSTEM_FOLDER}", pos)) != std::string::npos) { + result.replace(pos, 16, system_folder); // 16 = longitud de "${SYSTEM_FOLDER}" + pos += system_folder.length(); + } + + return result; +} + +// Parsea las opciones de una línea de configuración +auto Asset::parseOptions(const std::string& options, bool& required, bool& absolute) -> void { + if (options.empty()) { + return; + } + + std::istringstream iss(options); + std::string option; + + while (std::getline(iss, option, ',')) { + // Eliminar espacios + option.erase(0, option.find_first_not_of(" \t")); + option.erase(option.find_last_not_of(" \t") + 1); + + if (option == "optional") { + required = false; + } else if (option == "absolute") { + absolute = true; + } + } +} diff --git a/source/core/resources/asset.hpp b/source/core/resources/asset.hpp index 3c39625..d6e231e 100644 --- a/source/core/resources/asset.hpp +++ b/source/core/resources/asset.hpp @@ -1,80 +1,74 @@ #pragma once -#include // para string, basic_string -#include -#include // para vector +#include // Para uint8_t +#include // Para string +#include // Para unordered_map +#include // Para move +#include // Para vector -#include "utils/utils.hpp" - -enum class AssetType : int { - DATA, - BITMAP, - ANIMATION, - MUSIC, - SOUND, - FONT, - ROOM, - TILEMAP, - PALETTE, - MAX_ASSET_TYPE -}; - -// Clase Asset +// --- Clase Asset: gestor optimizado de recursos (singleton) --- class Asset { + public: + // --- Enums --- + enum class Type : int { + DATA, // Datos + BITMAP, // Imágenes + ANIMATION, // Animaciones + MUSIC, // Música + SOUND, // Sonidos + FONT, // Fuentes + ROOM, // Datos de habitación (.room) + TILEMAP, // Tilemaps (.tmx) + PALETTE, // Paletas + SIZE, // Tamaño (para iteración) + }; + + // --- Métodos de singleton --- + static void init(const std::string& executable_path); + static void destroy(); + static auto get() -> Asset*; + Asset(const Asset&) = delete; + auto operator=(const Asset&) -> Asset& = delete; + + // --- Métodos para la gestión de recursos --- + void add(const std::string& file_path, Type type, bool required = true, bool absolute = false); + void loadFromFile(const std::string& config_file_path, const std::string& prefix = "", const std::string& system_folder = ""); // Con soporte para variables + [[nodiscard]] auto get(const std::string& filename) const -> std::string; // Obtiene la ruta completa + [[nodiscard]] auto loadData(const std::string& filename) const -> std::vector; // Carga datos del archivo + [[nodiscard]] auto check() const -> bool; + [[nodiscard]] auto getListByType(Type type) const -> std::vector; + [[nodiscard]] auto exists(const std::string& filename) const -> bool; // Verifica si un asset existe + private: - // [SINGLETON] Objeto asset privado para Don Melitón - static Asset* asset; + // --- Estructuras privadas --- + struct Item { + std::string file; // Ruta completa del archivo + Type type; // Tipo de recurso + bool required; // Indica si el archivo es obligatorio - // Estructura para definir un item - struct AssetItem { - std::string file; // Ruta del fichero desde la raíz del directorio - AssetType type; // Indica el tipo de recurso - bool required; // Indica si es un fichero que debe de existir - - // Constructor - AssetItem(std::string file_path, AssetType asset_type, bool is_required) - : file(std::move(file_path)), + Item(std::string path, Type asset_type, bool is_required) + : file(std::move(path)), type(asset_type), required(is_required) {} }; - // Variables - int longest_name_ = 0; // Contiene la longitud del nombre de fichero mas largo - std::vector file_list_; // Listado con todas las rutas a los ficheros - std::string executable_path_; // Ruta al ejecutable + // --- Variables internas --- + std::unordered_map file_list_; // Mapa para búsqueda O(1) + std::string executable_path_; // Ruta del ejecutable - // Comprueba que existe un fichero - static auto checkFile(const std::string& path) -> bool; + // --- Métodos internos --- + [[nodiscard]] auto checkFile(const std::string& path) const -> bool; // Verifica si un archivo existe + [[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo + [[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type; // Convierte string a tipo + void addToMap(const std::string& file_path, Type type, bool required, bool absolute); // Añade archivo al mapa + [[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string; // Reemplaza variables en la ruta + static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void; // Parsea opciones - // Devuelve el nombre del tipo de recurso - static auto getTypeName(AssetType type) -> std::string; + // --- Constructores y destructor privados (singleton) --- + explicit Asset(std::string executable_path) // Constructor privado + : executable_path_(std::move(executable_path)) {} + ~Asset() = default; // Destructor privado - // Constructor - explicit Asset(const std::string& executable_path) - : executable_path_(getPath(executable_path)) {} - - // Destructor - ~Asset() = default; - - public: - // [SINGLETON] Crearemos el objeto con esta función estática - static void init(const std::string& executable_path); - - // [SINGLETON] Destruiremos el objeto con esta función estática - static void destroy(); - - // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él - static auto get() -> Asset*; - - // Añade un elemento a la lista - void add(const std::string& file, AssetType type, bool required = true, bool absolute = false); - - // Devuelve la ruta completa a un fichero a partir de una cadena - [[nodiscard]] auto get(const std::string& text) const -> std::string; - - // Comprueba que existen todos los elementos - [[nodiscard]] auto check() const -> bool; - - // Devuelve la lista de recursos de un tipo - [[nodiscard]] auto getListByType(AssetType type) const -> std::vector; -}; \ No newline at end of file + // --- Instancia singleton --- + static Asset* instance; // Instancia única de Asset +}; diff --git a/source/core/resources/resource.cpp b/source/core/resources/resource.cpp index d82b9d6..996989d 100644 --- a/source/core/resources/resource.cpp +++ b/source/core/resources/resource.cpp @@ -183,7 +183,7 @@ auto Resource::getRooms() -> std::vector& { // Carga los sonidos void Resource::loadSounds() { std::cout << "\n>> SOUND FILES" << '\n'; - auto list = Asset::get()->getListByType(AssetType::SOUND); + auto list = Asset::get()->getListByType(Asset::Type::SOUND); sounds_.clear(); for (const auto& l : list) { @@ -197,7 +197,7 @@ void Resource::loadSounds() { // Carga las musicas void Resource::loadMusics() { std::cout << "\n>> MUSIC FILES" << '\n'; - auto list = Asset::get()->getListByType(AssetType::MUSIC); + auto list = Asset::get()->getListByType(Asset::Type::MUSIC); musics_.clear(); for (const auto& l : list) { @@ -211,7 +211,7 @@ void Resource::loadMusics() { // Carga las texturas void Resource::loadSurfaces() { std::cout << "\n>> SURFACES" << '\n'; - auto list = Asset::get()->getListByType(AssetType::BITMAP); + auto list = Asset::get()->getListByType(Asset::Type::BITMAP); surfaces_.clear(); for (const auto& l : list) { @@ -234,7 +234,7 @@ void Resource::loadSurfaces() { // Carga las paletas void Resource::loadPalettes() { std::cout << "\n>> PALETTES" << '\n'; - auto list = Asset::get()->getListByType(AssetType::PALETTE); + auto list = Asset::get()->getListByType(Asset::Type::PALETTE); palettes_.clear(); for (const auto& l : list) { @@ -247,7 +247,7 @@ void Resource::loadPalettes() { // Carga los ficheros de texto void Resource::loadTextFiles() { std::cout << "\n>> TEXT FILES" << '\n'; - auto list = Asset::get()->getListByType(AssetType::FONT); + auto list = Asset::get()->getListByType(Asset::Type::FONT); text_files_.clear(); for (const auto& l : list) { @@ -260,7 +260,7 @@ void Resource::loadTextFiles() { // Carga las animaciones void Resource::loadAnimations() { std::cout << "\n>> ANIMATIONS" << '\n'; - auto list = Asset::get()->getListByType(AssetType::ANIMATION); + auto list = Asset::get()->getListByType(Asset::Type::ANIMATION); animations_.clear(); for (const auto& l : list) { @@ -273,7 +273,7 @@ void Resource::loadAnimations() { // Carga los mapas de tiles void Resource::loadTileMaps() { std::cout << "\n>> TILE MAPS" << '\n'; - auto list = Asset::get()->getListByType(AssetType::TILEMAP); + auto list = Asset::get()->getListByType(Asset::Type::TILEMAP); tile_maps_.clear(); for (const auto& l : list) { @@ -287,7 +287,7 @@ void Resource::loadTileMaps() { // Carga las habitaciones void Resource::loadRooms() { std::cout << "\n>> ROOMS" << '\n'; - auto list = Asset::get()->getListByType(AssetType::ROOM); + auto list = Asset::get()->getListByType(Asset::Type::ROOM); rooms_.clear(); for (const auto& l : list) { @@ -352,15 +352,15 @@ void Resource::clearMusics() { // Calcula el numero de recursos para cargar void Resource::calculateTotal() { - std::vector asset_types = { - AssetType::SOUND, - AssetType::MUSIC, - AssetType::BITMAP, - AssetType::PALETTE, - AssetType::FONT, - AssetType::ANIMATION, - AssetType::TILEMAP, - AssetType::ROOM}; + std::vector asset_types = { + Asset::Type::SOUND, + Asset::Type::MUSIC, + Asset::Type::BITMAP, + Asset::Type::PALETTE, + Asset::Type::FONT, + Asset::Type::ANIMATION, + Asset::Type::TILEMAP, + Asset::Type::ROOM}; size_t total = 0; for (const auto& asset_type : asset_types) { diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 3747886..0c1c99e 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -43,7 +43,7 @@ Director::Director(std::vector const& args) { Options::init(); // Comprueba los parametros del programa - executable_path_ = checkProgramArguments(args); + executable_path_ = getPath(checkProgramArguments(args)); // Crea el objeto que controla los ficheros de recursos Asset::init(executable_path_); @@ -239,235 +239,20 @@ void Director::initInput() { // Crea el indice de ficheros auto Director::setFileList() -> bool { + // Determinar el prefijo de ruta según la plataforma #ifdef MACOS_BUNDLE - const std::string prefix = "/../Resources"; + const std::string PREFIX = "/../Resources"; #else const std::string PREFIX; #endif - // Texto - Asset::get()->add(PREFIX + "/data/font/smb2.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/font/smb2.txt", AssetType::FONT); - Asset::get()->add(PREFIX + "/data/font/debug.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/font/debug.txt", AssetType::FONT); - Asset::get()->add(PREFIX + "/data/font/gauntlet.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/font/gauntlet.txt", AssetType::FONT); - Asset::get()->add(PREFIX + "/data/font/subatomic.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/font/subatomic.txt", AssetType::FONT); - Asset::get()->add(PREFIX + "/data/font/8bithud.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/font/8bithud.txt", AssetType::FONT); + // Construir ruta al archivo de configuración de assets + std::string config_path = executable_path_ + PREFIX + "/config/assets.txt"; - // Paletas - Asset::get()->add(PREFIX + "/data/palette/zx-spectrum.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/zx-spectrum-adjusted.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/zxarne-5-2.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/black-and-white.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/green-phosphor.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/orange-screen.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/ruzx-spectrum.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/ruzx-spectrum-revision-2.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/pico-8.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/sweetie-16.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/island-joy-16.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/lost-century.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/na16.pal", AssetType::PALETTE); - Asset::get()->add(PREFIX + "/data/palette/steam-lords.pal", AssetType::PALETTE); - - // Shaders - Asset::get()->add(PREFIX + "/data/shaders/crtpi_vertex.glsl", AssetType::DATA); - Asset::get()->add(PREFIX + "/data/shaders/crtpi_fragment.glsl", AssetType::DATA); - Asset::get()->add(PREFIX + "/data/shaders/crtpi_vertex_es.glsl", AssetType::DATA); - Asset::get()->add(PREFIX + "/data/shaders/crtpi_fragment_es.glsl", AssetType::DATA); - - // Datos - Asset::get()->add(PREFIX + "/data/input/gamecontrollerdb.txt", AssetType::DATA); - - // Ficheros de sistema - Asset::get()->add(system_folder_ + "/config.txt", AssetType::DATA, false, true); - Asset::get()->add(system_folder_ + "/stats_buffer.csv", AssetType::DATA, false, true); - Asset::get()->add(system_folder_ + "/stats.csv", AssetType::DATA, false, true); - Asset::get()->add(system_folder_ + "/cheevos.bin", AssetType::DATA, false, true); - - // Tilemaps y Rooms - for (int i = 1; i <= 60; ++i) { - std::string index = (i < 10 ? "0" : "") + std::to_string(i); - Asset::get()->add(PREFIX + "/data/room/" + index + ".tmx", AssetType::TILEMAP); - Asset::get()->add(PREFIX + "/data/room/" + index + ".room", AssetType::ROOM); - } - - // Tilesets - Asset::get()->add(PREFIX + "/data/tilesets/standard.gif", AssetType::BITMAP); - - // Enemigos - Asset::get()->add(PREFIX + "/data/enemies/abad_bell.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/abad_bell.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/abad.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/abad.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/amstrad_cs.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/amstrad_cs.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/flying_arounder.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/flying_arounder.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/stopped_arounder.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/stopped_arounder.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/walking_arounder.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/walking_arounder.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/arounders_door.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/arounders_door.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/arounders_machine.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/arounders_machine.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/bat.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/bat.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/batman_bell.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/batman_bell.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/batman_fire.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/batman_fire.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/batman.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/batman.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/bell.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/bell.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/bin.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/bin.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/bird.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/bird.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/breakout.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/breakout.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/bry.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/bry.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/chip.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/chip.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/code.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/code.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/congo.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/congo.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/crosshair.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/crosshair.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/demon.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/demon.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/dimallas.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/dimallas.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/floppy.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/floppy.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/dong.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/dong.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/guitar.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/guitar.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/heavy.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/heavy.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/jailer_#1.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/jailer_#1.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/jailer_#2.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/jailer_#2.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/jailer_#3.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/jailer_#3.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/jailbattle_alien.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/jailbattle_alien.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/jailbattle_human.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/jailbattle_human.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/jeannine.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/jeannine.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/lamp.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/lamp.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/lord_abad.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/lord_abad.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/matatunos.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/matatunos.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/mummy.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/mummy.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/paco.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/paco.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/elsa.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/elsa.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/qvoid.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/qvoid.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/robot.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/robot.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/sam.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/sam.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/shock.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/shock.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/sigmasua.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/sigmasua.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/spark.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/spark.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/special/aerojailer.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/special/aerojailer.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/special/arounder.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/special/arounder.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/special/pepe_rosita_job.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/special/pepe_rosita_job.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/special/shooting_star.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/special/shooting_star.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/spider.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/spider.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/tree_thing.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/tree_thing.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/tuno.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/tuno.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/tv_panel.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/tv_panel.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/tv.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/tv.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/upv_student.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/upv_student.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/wave.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/wave.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/enemies/z80.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/enemies/z80.gif", AssetType::BITMAP); - - // Jugador - Asset::get()->add(PREFIX + "/data/player/player.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/player/player.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/player/player2.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/player/player2.ani", AssetType::ANIMATION); - Asset::get()->add(PREFIX + "/data/player/player_game_over.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/player/player_game_over.ani", AssetType::ANIMATION); - - // Items - Asset::get()->add(PREFIX + "/data/items/items.gif", AssetType::BITMAP); - - // Musicas - Asset::get()->add(PREFIX + "/data/music/title.ogg", AssetType::MUSIC); - Asset::get()->add(PREFIX + "/data/music/game.ogg", AssetType::MUSIC); - Asset::get()->add(PREFIX + "/data/music/loading_sound1.ogg", AssetType::MUSIC); - Asset::get()->add(PREFIX + "/data/music/loading_sound2.ogg", AssetType::MUSIC); - Asset::get()->add(PREFIX + "/data/music/loading_sound3.ogg", AssetType::MUSIC); - Asset::get()->add(PREFIX + "/data/music/ending1.ogg", AssetType::MUSIC); - Asset::get()->add(PREFIX + "/data/music/ending2.ogg", AssetType::MUSIC); - Asset::get()->add(PREFIX + "/data/music/game_over.ogg", AssetType::MUSIC); - - // Efectos de sonido - Asset::get()->add(PREFIX + "/data/sound/item.wav", AssetType::SOUND); - Asset::get()->add(PREFIX + "/data/sound/death.wav", AssetType::SOUND); - Asset::get()->add(PREFIX + "/data/sound/notify.wav", AssetType::SOUND); - - // Efectos de sonido para el salto - for (int i = 1; i <= 24; ++i) { - std::string jump_index = std::to_string(i); - Asset::get()->add(PREFIX + "/data/sound/jump" + jump_index + ".wav", AssetType::SOUND); - } - - // Logo - Asset::get()->add(PREFIX + "/data/logo/jailgames.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/logo/since_1998.gif", AssetType::BITMAP); - - // Loading - Asset::get()->add(PREFIX + "/data/loading/loading_screen_bn.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/loading/loading_screen_color.gif", AssetType::BITMAP); - - // Title - Asset::get()->add(PREFIX + "/data/title/title_logo.gif", AssetType::BITMAP); - - // Ending - Asset::get()->add(PREFIX + "/data/ending/ending1.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/ending/ending2.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/ending/ending3.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/ending/ending4.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/ending/ending5.gif", AssetType::BITMAP); - - // Credits - Asset::get()->add(PREFIX + "/data/credits/shine.gif", AssetType::BITMAP); - Asset::get()->add(PREFIX + "/data/credits/shine.ani", AssetType::ANIMATION); + // Cargar todos los assets desde el archivo de configuración + Asset::get()->loadFromFile(config_path, PREFIX, system_folder_); + // Verificar que todos los assets requeridos existen return Asset::get()->check(); }