#include "resource.h" #include // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN #include // Para SDLK_ESCAPE #include // Para SDL_Rect #include // Para Uint8 #include // Para exit, size_t #include // Para find_if #include // Para basic_ostream, operator<<, endl, cout #include // Para runtime_error #include "asset.h" // Para AssetType, Asset #include "jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_Loa... #include "options.h" // Para Options, OptionsGame, options #include "room.h" // Para RoomData, loadRoomFile, loadRoomTileFile #include "screen.h" // Para Screen #include "text.h" // Para Text, loadTextFile #include "utils.h" // Para getFileName, printWithDots, PaletteColor struct JA_Music_t; // lines 17-17 struct JA_Sound_t; // lines 18-18 // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado Resource *Resource::resource_ = nullptr; // [SINGLETON] Crearemos el objeto screen con esta función estática void Resource::init() { Resource::resource_ = new Resource(); } // [SINGLETON] Destruiremos el objeto screen con esta función estática void Resource::destroy() { delete Resource::resource_; } // [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él Resource *Resource::get() { return Resource::resource_; } // Constructor Resource::Resource() { load(); } // Vacia todos los vectores de recursos void Resource::clear() { clearSounds(); clearMusics(); surfaces_.clear(); palettes_.clear(); text_files_.clear(); texts_.clear(); animations_.clear(); } // Carga todos los recursos void Resource::load() { calculateTotal(); Screen::get()->show(); Screen::get()->setBorderColor(static_cast(PaletteColor::BLACK)); std::cout << "** LOADING RESOURCES" << std::endl; loadSounds(); loadMusics(); loadSurfaces(); loadPalettes(); loadTextFiles(); loadAnimations(); loadTileMaps(); loadRooms(); createText(); std::cout << "\n** RESOURCES LOADED" << std::endl; } // Recarga todos los recursos void Resource::reload() { clear(); load(); } // Obtiene el sonido a partir de un nombre JA_Sound_t *Resource::getSound(const std::string &name) { auto it = std::find_if(sounds_.begin(), sounds_.end(), [&name](const auto &s) { return s.name == name; }); if (it != sounds_.end()) { return it->sound; } std::cerr << "Error: Sonido no encontrado " << name << std::endl; throw std::runtime_error("Sonido no encontrado: " + name); } // Obtiene la música a partir de un nombre JA_Music_t *Resource::getMusic(const std::string &name) { auto it = std::find_if(musics_.begin(), musics_.end(), [&name](const auto &m) { return m.name == name; }); if (it != musics_.end()) { return it->music; } std::cerr << "Error: Música no encontrada " << name << std::endl; throw std::runtime_error("Música no encontrada: " + name); } // Obtiene la surface a partir de un nombre std::shared_ptr Resource::getSurface(const std::string &name) { auto it = std::find_if(surfaces_.begin(), surfaces_.end(), [&name](const auto &t) { return t.name == name; }); if (it != surfaces_.end()) { return it->surface; } std::cerr << "Error: Imagen no encontrada " << name << std::endl; throw std::runtime_error("Imagen no encontrada: " + name); } // Obtiene la paleta a partir de un nombre Palette Resource::getPalette(const std::string &name) { auto it = std::find_if(palettes_.begin(), palettes_.end(), [&name](const auto &t) { return t.name == name; }); if (it != palettes_.end()) { return it->palette; } std::cerr << "Error: Paleta no encontrada " << name << std::endl; throw std::runtime_error("Paleta no encontrada: " + name); } // Obtiene el fichero de texto a partir de un nombre std::shared_ptr Resource::getTextFile(const std::string &name) { auto it = std::find_if(text_files_.begin(), text_files_.end(), [&name](const auto &t) { return t.name == name; }); if (it != text_files_.end()) { return it->text_file; } std::cerr << "Error: TextFile no encontrado " << name << std::endl; throw std::runtime_error("TextFile no encontrado: " + name); } // Obtiene el objeto de texto a partir de un nombre std::shared_ptr Resource::getText(const std::string &name) { auto it = std::find_if(texts_.begin(), texts_.end(), [&name](const auto &t) { return t.name == name; }); if (it != texts_.end()) { return it->text; } std::cerr << "Error: Text no encontrado " << name << std::endl; throw std::runtime_error("Texto no encontrado: " + name); } // Obtiene la animación a partir de un nombre Animations &Resource::getAnimations(const std::string &name) { auto it = std::find_if(animations_.begin(), animations_.end(), [&name](const auto &a) { return a.name == name; }); if (it != animations_.end()) { return it->animation; } std::cerr << "Error: Animación no encontrada " << name << std::endl; throw std::runtime_error("Animación no encontrada: " + name); } // Obtiene el mapa de tiles a partir de un nombre std::vector &Resource::getTileMap(const std::string &name) { auto it = std::find_if(tile_maps_.begin(), tile_maps_.end(), [&name](const auto &t) { return t.name == name; }); if (it != tile_maps_.end()) { return it->tileMap; } std::cerr << "Error: Mapa de tiles no encontrado " << name << std::endl; throw std::runtime_error("Mapa de tiles no encontrado: " + name); } // Obtiene la habitación a partir de un nombre std::shared_ptr Resource::getRoom(const std::string &name) { auto it = std::find_if(rooms_.begin(), rooms_.end(), [&name](const auto &r) { return r.name == name; }); if (it != rooms_.end()) { return it->room; } std::cerr << "Error: Habitación no encontrada " << name << std::endl; throw std::runtime_error("Habitación no encontrada: " + name); } // Obtiene todas las habitaciones std::vector &Resource::getRooms() { return rooms_; } // Carga los sonidos void Resource::loadSounds() { std::cout << "\n>> SOUND FILES" << std::endl; auto list = Asset::get()->getListByType(AssetType::SOUND); sounds_.clear(); for (const auto &l : list) { auto name = getFileName(l); sounds_.emplace_back(ResourceSound(name, JA_LoadSound(l.c_str()))); printWithDots("Sound : ", name, "[ LOADED ]"); updateLoadingProgress(); } } // Carga las musicas void Resource::loadMusics() { std::cout << "\n>> MUSIC FILES" << std::endl; auto list = Asset::get()->getListByType(AssetType::MUSIC); musics_.clear(); for (const auto &l : list) { auto name = getFileName(l); musics_.emplace_back(ResourceMusic(name, JA_LoadMusic(l.c_str()))); printWithDots("Music : ", name, "[ LOADED ]"); updateLoadingProgress(); } } // Carga las texturas void Resource::loadSurfaces() { std::cout << "\n>> SURFACES" << std::endl; auto list = Asset::get()->getListByType(AssetType::BITMAP); surfaces_.clear(); for (const auto &l : list) { auto name = getFileName(l); surfaces_.emplace_back(ResourceSurface(name, std::make_shared(l))); surfaces_.back().surface->setTransparentColor(0); updateLoadingProgress(); } // Reconfigura el color transparente de algunas surfaces getSurface("loading_screen_color.gif")->setTransparentColor(); getSurface("ending1.gif")->setTransparentColor(); getSurface("ending2.gif")->setTransparentColor(); getSurface("ending3.gif")->setTransparentColor(); getSurface("ending4.gif")->setTransparentColor(); getSurface("ending5.gif")->setTransparentColor(); getSurface("standard.gif")->setTransparentColor(16); } // Carga las paletas void Resource::loadPalettes() { std::cout << "\n>> PALETTES" << std::endl; auto list = Asset::get()->getListByType(AssetType::PALETTE); palettes_.clear(); for (const auto &l : list) { auto name = getFileName(l); palettes_.emplace_back(ResourcePalette(name, readPalFile(l))); updateLoadingProgress(); } } // Carga los ficheros de texto void Resource::loadTextFiles() { std::cout << "\n>> TEXT FILES" << std::endl; auto list = Asset::get()->getListByType(AssetType::FONT); text_files_.clear(); for (const auto &l : list) { auto name = getFileName(l); text_files_.emplace_back(ResourceTextFile(name, loadTextFile(l))); updateLoadingProgress(); } } // Carga las animaciones void Resource::loadAnimations() { std::cout << "\n>> ANIMATIONS" << std::endl; auto list = Asset::get()->getListByType(AssetType::ANIMATION); animations_.clear(); for (const auto &l : list) { auto name = getFileName(l); animations_.emplace_back(ResourceAnimation(name, loadAnimationsFromFile(l))); updateLoadingProgress(); } } // Carga los mapas de tiles void Resource::loadTileMaps() { std::cout << "\n>> TILE MAPS" << std::endl; auto list = Asset::get()->getListByType(AssetType::TILEMAP); tile_maps_.clear(); for (const auto &l : list) { auto name = getFileName(l); tile_maps_.emplace_back(ResourceTileMap(name, loadRoomTileFile(l))); printWithDots("TileMap : ", name, "[ LOADED ]"); updateLoadingProgress(); } } // Carga las habitaciones void Resource::loadRooms() { std::cout << "\n>> ROOMS" << std::endl; auto list = Asset::get()->getListByType(AssetType::ROOM); rooms_.clear(); for (const auto &l : list) { auto name = getFileName(l); rooms_.emplace_back(ResourceRoom(name, std::make_shared(loadRoomFile(l)))); printWithDots("Room : ", name, "[ LOADED ]"); updateLoadingProgress(); } } void Resource::createText() { struct ResourceInfo { std::string key; // Identificador del recurso std::string textureFile; // Nombre del archivo de textura std::string textFile; // Nombre del archivo de texto // Constructor para facilitar la creación de objetos ResourceInfo ResourceInfo(const std::string &k, const std::string &tFile, const std::string &txtFile) : key(k), textureFile(tFile), textFile(txtFile) {} }; std::cout << "\n>> CREATING TEXT_OBJECTS" << std::endl; std::vector resources = { {"debug", "debug.gif", "debug.txt"}, {"gauntlet", "gauntlet.gif", "gauntlet.txt"}, {"smb2", "smb2.gif", "smb2.txt"}, {"subatomic", "subatomic.gif", "subatomic.txt"}, {"8bithud", "8bithud.gif", "8bithud.txt"}}; for (const auto &resource : resources) { texts_.emplace_back(ResourceText(resource.key, std::make_shared( getSurface(resource.textureFile), getTextFile(resource.textFile)))); printWithDots("Text : ", resource.key, "[ DONE ]"); } } // Vacía el vector de sonidos void Resource::clearSounds() { // Itera sobre el vector y libera los recursos asociados a cada JA_Sound_t for (auto &sound : sounds_) { if (sound.sound) { JA_DeleteSound(sound.sound); sound.sound = nullptr; } } sounds_.clear(); // Limpia el vector después de liberar todos los recursos } // Vacía el vector de musicas void Resource::clearMusics() { // Itera sobre el vector y libera los recursos asociados a cada JA_Music_t for (auto &music : musics_) { if (music.music) { JA_DeleteMusic(music.music); music.music = nullptr; } } musics_.clear(); // Limpia el vector después de liberar todos los recursos } // Calcula el numero de recursos para cargar void Resource::calculateTotal() { std::vector assetTypes = { AssetType::SOUND, AssetType::MUSIC, AssetType::BITMAP, AssetType::PALETTE, AssetType::FONT, AssetType::ANIMATION, AssetType::TILEMAP, AssetType::ROOM}; size_t total = 0; for (const auto &assetType : assetTypes) { auto list = Asset::get()->getListByType(assetType); total += list.size(); } count_ = ResourceCount(total, 0); } // Muestra el progreso de carga void Resource::renderProgress() { constexpr int X_PADDING = 10; constexpr int Y_PADDING = 10; constexpr int BAR_HEIGHT = 10; const int bar_position = options.game.height - BAR_HEIGHT - Y_PADDING; Screen::get()->start(); Screen::get()->clearSurface(static_cast(PaletteColor::BLACK)); auto surface = Screen::get()->getRendererSurface(); const int wired_bar_width = options.game.width - (X_PADDING * 2); SDL_Rect rect_wired = {X_PADDING, bar_position, wired_bar_width, X_PADDING}; surface->drawRectBorder(&rect_wired, static_cast(PaletteColor::WHITE)); const int full_bar_width = wired_bar_width * count_.getPercentage(); SDL_Rect rect_full = {X_PADDING, bar_position, full_bar_width, X_PADDING}; surface->fillRect(&rect_full, static_cast(PaletteColor::WHITE)); Screen::get()->render(); } // Comprueba los eventos de la pantalla de carga void Resource::checkEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: exit(0); break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) { exit(0); } break; } } } // Actualiza el progreso de carga void Resource::updateLoadingProgress() { count_.add(1); if (count_.loaded % 5 == 0 || count_.loaded == count_.total) { renderProgress(); } checkEvents(); }