migrat Assets a la ultima versió (fitxers no hardcoded)

This commit is contained in:
2025-10-31 12:52:22 +01:00
parent 2f20ac422e
commit 70bfced50d
7 changed files with 804 additions and 396 deletions

View File

@@ -181,6 +181,9 @@ source/
│ └── utils.hpp/cpp # Helper functions (colors, math) │ └── utils.hpp/cpp # Helper functions (colors, math)
└── main.cpp # Application entry point └── main.cpp # Application entry point
config/ # Configuration files
└── assets.txt # Asset registry (text-based configuration)
data/ # Game assets data/ # Game assets
├── font/ # Bitmap fonts + descriptors ├── font/ # Bitmap fonts + descriptors
├── palette/ # Color palettes (.pal files) ├── palette/ # Color palettes (.pal files)
@@ -386,13 +389,17 @@ Game::run() {
``` ```
Director::setFileList() Director::setFileList()
├─ Asset::add(file, type) - Register all assets ├─ Asset::loadFromFile(config_path, PREFIX, system_folder_)
└─ Asset::check() - Verify files exist │ ├─ 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 Game Scene initialization
└─ Resource::init() - Loads all resources └─ Resource::init() - Loads all resources
├─ loadSounds() - WAV files ├─ loadSounds() - WAV files
├─ loadMusics() - OGG files ├─ loadMusics() - OGG files
├─ loadSurfaces() - GIF/PNG images ├─ loadSurfaces() - GIF/PNG images
├─ loadAnimations() - .ani animation definitions ├─ loadAnimations() - .ani animation definitions
├─ loadTileMaps() - .room tilemap data ├─ loadTileMaps() - .room tilemap data
@@ -568,7 +575,7 @@ Achievements trigger notifications on unlock.
| `Input` | Keyboard & gamepad input | Singleton | | `Input` | Keyboard & gamepad input | Singleton |
| `Audio` | Music and SFX playback | Singleton | | `Audio` | Music and SFX playback | Singleton |
| `Resource` | Asset caching and loading | 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 | | `Debug` | Debug overlay information | Singleton |
| `globalEvents` | Global SDL event handling (quit, device reset, mouse) | Namespace | | `globalEvents` | Global SDL event handling (quit, device reset, mouse) | Namespace |
@@ -631,12 +638,16 @@ Achievements trigger notifications on unlock.
### Adding Game Assets ### Adding Game Assets
1. Place file in `data/` directory 1. Place file in `data/` directory
2. Register in `Director::setFileList()`: 2. Add entry to `config/assets.txt`:
```cpp
Asset::get()->add("/data/path/file.ext", AssetType::TYPE);
``` ```
3. Resource loads automatically during `Resource::init()` TYPE|${PREFIX}/data/path/file.ext
4. Access via: `Resource::get()->getSurface("name")` ```
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 ### Modifying Collision Detection
@@ -692,6 +703,40 @@ In debug builds (`#ifdef DEBUG`), renders:
## 11. File Format Reference ## 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) ### Animation Files (.ani)
List of animation names, one per line: 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 - `Player::update()` - Physics and movement
### For Asset Management ### 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 - `Resource::load()` - Asset loading
- `Director::setFileList()` - Complete asset registry - `Director::setFileList()` - Calls `Asset::loadFromFile()` with PREFIX and system_folder
--- ---

396
config/assets.txt Normal file
View File

@@ -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

View File

@@ -38,7 +38,7 @@ auto Screen::get() -> Screen* {
// Constructor // Constructor
Screen::Screen() Screen::Screen()
: palettes_(Asset::get()->getListByType(AssetType::PALETTE)) { : palettes_(Asset::get()->getListByType(Asset::Type::PALETTE)) {
// Arranca SDL VIDEO, crea la ventana y el renderizador // Arranca SDL VIDEO, crea la ventana y el renderizador
initSDLVideo(); initSDLVideo();

View File

@@ -1,79 +1,205 @@
#include "core/resources/asset.hpp" #include "core/resources/asset.hpp"
#include <algorithm> // Para find_if, max #include <SDL3/SDL.h> // Para SDL_LogWarn, SDL_LogCategory, SDL_LogError
#include <fstream> // Para basic_ostream, operator<<, basic_ifstream, endl
#include <iostream> // Para cout #include <algorithm> // Para sort
#include <string> // Para allocator, char_traits, string, operator+, oper... #include <cstddef> // Para size_t
#include <exception> // Para exception
#include <filesystem> // Para exists, path
#include <fstream> // Para ifstream, istringstream
#include <iostream> // Para cout
#include <sstream> // Para istringstream
#include <stdexcept> // Para runtime_error
#include "utils/utils.hpp" // Para getFileName, printWithDots #include "utils/utils.hpp" // Para getFileName, printWithDots
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // Singleton
Asset* Asset::asset = nullptr; Asset* Asset::instance = nullptr;
// [SINGLETON] Crearemos el objeto asset con esta función estática
void Asset::init(const std::string& executable_path) { 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() { 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* { 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 // Añade un elemento a la lista
void Asset::add(const std::string& file, AssetType type, bool required, bool absolute) { void Asset::add(const std::string& file_path, Type type, bool required, bool absolute) {
file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required); addToMap(file_path, type, required, absolute);
longest_name_ = std::max(longest_name_, static_cast<int>(file_list_.back().file.size()));
} }
// Devuelve la ruta completa a un fichero a partir de una cadena // Carga recursos desde un archivo de configuración con soporte para variables
auto Asset::get(const std::string& text) const -> std::string { void Asset::loadFromFile(const std::string& config_file_path, const std::string& prefix, const std::string& system_folder) {
auto it = std::ranges::find_if(file_list_, [&text](const auto& f) { std::ifstream file(config_file_path);
return getFileName(f.file) == text; if (!file.is_open()) {
}); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error: Cannot open config file: %s",
if (it != file_list_.end()) { config_file_path.c_str());
return it->file; 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<std::string> 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 ""; return "";
} }
// Carga datos del archivo
auto Asset::loadData(const std::string& filename) const -> std::vector<uint8_t> {
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<uint8_t> data(size);
file.read(reinterpret_cast<char*>(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 // Comprueba que existen todos los elementos
auto Asset::check() const -> bool { auto Asset::check() const -> bool {
bool success = true; bool success = true;
std::cout << "\n** CHECKING FILES" << '\n'; std::cout << "\n** CHECKING FILES" << '\n';
// std::cout << "Executable path is: " << executable_path_ << std::endl; // Agrupar por tipo para mostrar organizado
// std::cout << "Sample filepath: " << file_list_.back().file << std::endl; std::unordered_map<Type, std::vector<const Item*>> by_type;
// Comprueba la lista de ficheros clasificandolos por tipo for (const auto& [filename, item] : file_list_) {
for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type) { if (item.required) {
// Comprueba si hay ficheros de ese tipo by_type[item.type].push_back(&item);
bool any = false;
for (const auto& f : file_list_) {
if (f.required && f.type == static_cast<AssetType>(type)) {
any = true;
}
} }
}
// Si hay ficheros de ese tipo, comprueba si existen // Verificar por tipo
if (any) { for (int type = 0; type < static_cast<int>(Type::SIZE); ++type) {
std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << '\n'; Type asset_type = static_cast<Type>(type);
for (const auto& f : file_list_) { if (by_type.find(asset_type) != by_type.end()) {
if (f.required && f.type == static_cast<AssetType>(type)) { std::cout << "\n>> " << getTypeName(asset_type) << " FILES" << '\n';
success &= checkFile(f.file);
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'; std::cout << " All files are OK." << '\n';
} }
} }
@@ -86,7 +212,7 @@ auto Asset::check() const -> bool {
} }
// Comprueba que existe un fichero // 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); std::ifstream file(path);
bool success = file.good(); bool success = file.good();
file.close(); file.close();
@@ -98,60 +224,120 @@ auto Asset::checkFile(const std::string& path) -> bool {
return success; 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 // Devuelve el nombre del tipo de recurso
auto Asset::getTypeName(AssetType type) -> std::string { auto Asset::getTypeName(Type type) -> std::string {
switch (type) { switch (type) {
case AssetType::DATA: case Type::DATA:
return "DATA"; return "DATA";
break; case Type::BITMAP:
case AssetType::BITMAP:
return "BITMAP"; return "BITMAP";
break; case Type::ANIMATION:
case AssetType::ANIMATION:
return "ANIMATION"; return "ANIMATION";
break; case Type::MUSIC:
case AssetType::MUSIC:
return "MUSIC"; return "MUSIC";
break; case Type::SOUND:
case AssetType::SOUND:
return "SOUND"; return "SOUND";
break; case Type::FONT:
case AssetType::FONT:
return "FONT"; return "FONT";
break; case Type::ROOM:
case AssetType::ROOM:
return "ROOM"; return "ROOM";
break; case Type::TILEMAP:
case AssetType::TILEMAP:
return "TILEMAP"; return "TILEMAP";
break; case Type::PALETTE:
case AssetType::PALETTE:
return "PALETTE"; return "PALETTE";
break;
default: default:
return "ERROR"; return "ERROR";
break;
} }
} }
// Devuelve la lista de recursos de un tipo // Devuelve la lista de recursos de un tipo
auto Asset::getListByType(AssetType type) const -> std::vector<std::string> { auto Asset::getListByType(Type type) const -> std::vector<std::string> {
std::vector<std::string> list; std::vector<std::string> list;
for (const auto& f : file_list_) { for (const auto& [filename, item] : file_list_) {
if (f.type == type) { if (item.type == type) {
list.push_back(f.file); list.push_back(item.file);
} }
} }
// Ordenar alfabéticamente para garantizar orden consistente
std::ranges::sort(list);
return list; return list;
} }
// 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;
}
}
}

View File

@@ -1,80 +1,74 @@
#pragma once #pragma once
#include <string> // para string, basic_string #include <cstdint> // Para uint8_t
#include <utility> #include <string> // Para string
#include <vector> // para vector #include <unordered_map> // Para unordered_map
#include <utility> // Para move
#include <vector> // Para vector
#include "utils/utils.hpp" // --- Clase Asset: gestor optimizado de recursos (singleton) ---
enum class AssetType : int {
DATA,
BITMAP,
ANIMATION,
MUSIC,
SOUND,
FONT,
ROOM,
TILEMAP,
PALETTE,
MAX_ASSET_TYPE
};
// Clase Asset
class Asset { 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<uint8_t>; // Carga datos del archivo
[[nodiscard]] auto check() const -> bool;
[[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>;
[[nodiscard]] auto exists(const std::string& filename) const -> bool; // Verifica si un asset existe
private: private:
// [SINGLETON] Objeto asset privado para Don Melitón // --- Estructuras privadas ---
static Asset* asset; 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 Item(std::string path, Type asset_type, bool is_required)
struct AssetItem { : file(std::move(path)),
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)),
type(asset_type), type(asset_type),
required(is_required) {} required(is_required) {}
}; };
// Variables // --- Variables internas ---
int longest_name_ = 0; // Contiene la longitud del nombre de fichero mas largo std::unordered_map<std::string, Item> file_list_; // Mapa para búsqueda O(1)
std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros std::string executable_path_; // Ruta del ejecutable
std::string executable_path_; // Ruta al ejecutable
// Comprueba que existe un fichero // --- Métodos internos ---
static auto checkFile(const std::string& path) -> bool; [[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 // --- Constructores y destructor privados (singleton) ---
static auto getTypeName(AssetType type) -> std::string; explicit Asset(std::string executable_path) // Constructor privado
: executable_path_(std::move(executable_path)) {}
~Asset() = default; // Destructor privado
// Constructor // --- Instancia singleton ---
explicit Asset(const std::string& executable_path) static Asset* instance; // Instancia única de Asset
: 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<std::string>;
};

View File

@@ -183,7 +183,7 @@ auto Resource::getRooms() -> std::vector<ResourceRoom>& {
// Carga los sonidos // Carga los sonidos
void Resource::loadSounds() { void Resource::loadSounds() {
std::cout << "\n>> SOUND FILES" << '\n'; std::cout << "\n>> SOUND FILES" << '\n';
auto list = Asset::get()->getListByType(AssetType::SOUND); auto list = Asset::get()->getListByType(Asset::Type::SOUND);
sounds_.clear(); sounds_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -197,7 +197,7 @@ void Resource::loadSounds() {
// Carga las musicas // Carga las musicas
void Resource::loadMusics() { void Resource::loadMusics() {
std::cout << "\n>> MUSIC FILES" << '\n'; std::cout << "\n>> MUSIC FILES" << '\n';
auto list = Asset::get()->getListByType(AssetType::MUSIC); auto list = Asset::get()->getListByType(Asset::Type::MUSIC);
musics_.clear(); musics_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -211,7 +211,7 @@ void Resource::loadMusics() {
// Carga las texturas // Carga las texturas
void Resource::loadSurfaces() { void Resource::loadSurfaces() {
std::cout << "\n>> SURFACES" << '\n'; std::cout << "\n>> SURFACES" << '\n';
auto list = Asset::get()->getListByType(AssetType::BITMAP); auto list = Asset::get()->getListByType(Asset::Type::BITMAP);
surfaces_.clear(); surfaces_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -234,7 +234,7 @@ void Resource::loadSurfaces() {
// Carga las paletas // Carga las paletas
void Resource::loadPalettes() { void Resource::loadPalettes() {
std::cout << "\n>> PALETTES" << '\n'; std::cout << "\n>> PALETTES" << '\n';
auto list = Asset::get()->getListByType(AssetType::PALETTE); auto list = Asset::get()->getListByType(Asset::Type::PALETTE);
palettes_.clear(); palettes_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -247,7 +247,7 @@ void Resource::loadPalettes() {
// Carga los ficheros de texto // Carga los ficheros de texto
void Resource::loadTextFiles() { void Resource::loadTextFiles() {
std::cout << "\n>> TEXT FILES" << '\n'; std::cout << "\n>> TEXT FILES" << '\n';
auto list = Asset::get()->getListByType(AssetType::FONT); auto list = Asset::get()->getListByType(Asset::Type::FONT);
text_files_.clear(); text_files_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -260,7 +260,7 @@ void Resource::loadTextFiles() {
// Carga las animaciones // Carga las animaciones
void Resource::loadAnimations() { void Resource::loadAnimations() {
std::cout << "\n>> ANIMATIONS" << '\n'; std::cout << "\n>> ANIMATIONS" << '\n';
auto list = Asset::get()->getListByType(AssetType::ANIMATION); auto list = Asset::get()->getListByType(Asset::Type::ANIMATION);
animations_.clear(); animations_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -273,7 +273,7 @@ void Resource::loadAnimations() {
// Carga los mapas de tiles // Carga los mapas de tiles
void Resource::loadTileMaps() { void Resource::loadTileMaps() {
std::cout << "\n>> TILE MAPS" << '\n'; std::cout << "\n>> TILE MAPS" << '\n';
auto list = Asset::get()->getListByType(AssetType::TILEMAP); auto list = Asset::get()->getListByType(Asset::Type::TILEMAP);
tile_maps_.clear(); tile_maps_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -287,7 +287,7 @@ void Resource::loadTileMaps() {
// Carga las habitaciones // Carga las habitaciones
void Resource::loadRooms() { void Resource::loadRooms() {
std::cout << "\n>> ROOMS" << '\n'; std::cout << "\n>> ROOMS" << '\n';
auto list = Asset::get()->getListByType(AssetType::ROOM); auto list = Asset::get()->getListByType(Asset::Type::ROOM);
rooms_.clear(); rooms_.clear();
for (const auto& l : list) { for (const auto& l : list) {
@@ -352,15 +352,15 @@ void Resource::clearMusics() {
// Calcula el numero de recursos para cargar // Calcula el numero de recursos para cargar
void Resource::calculateTotal() { void Resource::calculateTotal() {
std::vector<AssetType> asset_types = { std::vector<Asset::Type> asset_types = {
AssetType::SOUND, Asset::Type::SOUND,
AssetType::MUSIC, Asset::Type::MUSIC,
AssetType::BITMAP, Asset::Type::BITMAP,
AssetType::PALETTE, Asset::Type::PALETTE,
AssetType::FONT, Asset::Type::FONT,
AssetType::ANIMATION, Asset::Type::ANIMATION,
AssetType::TILEMAP, Asset::Type::TILEMAP,
AssetType::ROOM}; Asset::Type::ROOM};
size_t total = 0; size_t total = 0;
for (const auto& asset_type : asset_types) { for (const auto& asset_type : asset_types) {

View File

@@ -43,7 +43,7 @@ Director::Director(std::vector<std::string> const& args) {
Options::init(); Options::init();
// Comprueba los parametros del programa // Comprueba los parametros del programa
executable_path_ = checkProgramArguments(args); executable_path_ = getPath(checkProgramArguments(args));
// Crea el objeto que controla los ficheros de recursos // Crea el objeto que controla los ficheros de recursos
Asset::init(executable_path_); Asset::init(executable_path_);
@@ -239,235 +239,20 @@ void Director::initInput() {
// Crea el indice de ficheros // Crea el indice de ficheros
auto Director::setFileList() -> bool { auto Director::setFileList() -> bool {
// Determinar el prefijo de ruta según la plataforma
#ifdef MACOS_BUNDLE #ifdef MACOS_BUNDLE
const std::string prefix = "/../Resources"; const std::string PREFIX = "/../Resources";
#else #else
const std::string PREFIX; const std::string PREFIX;
#endif #endif
// Texto // Construir ruta al archivo de configuración de assets
Asset::get()->add(PREFIX + "/data/font/smb2.gif", AssetType::BITMAP); std::string config_path = executable_path_ + PREFIX + "/config/assets.txt";
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);
// Paletas // Cargar todos los assets desde el archivo de configuración
Asset::get()->add(PREFIX + "/data/palette/zx-spectrum.pal", AssetType::PALETTE); Asset::get()->loadFromFile(config_path, PREFIX, system_folder_);
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);
// Verificar que todos los assets requeridos existen
return Asset::get()->check(); return Asset::get()->check();
} }