pantalla de carrega no bloquejant

streaming de audio per evitar precárrega i descompresió a memoria
This commit is contained in:
2026-04-13 19:29:05 +02:00
parent 585c93054e
commit 9b8820ffa3
9 changed files with 587 additions and 261 deletions

View File

@@ -23,6 +23,7 @@
#include "game/gameplay/cheevos.hpp" // Para Cheevos
#include "game/options.hpp" // Para Options, options, OptionsVideo
#include "game/scene_manager.hpp" // Para SceneManager
#include "game/scenes/boot_loader.hpp" // Para BootLoader
#include "game/scenes/credits.hpp" // Para Credits
#include "game/scenes/ending.hpp" // Para Ending
#include "game/scenes/ending2.hpp" // Para Ending2
@@ -177,12 +178,12 @@ Director::Director() {
// Crea los objetos
Screen::init();
// Initialize resources (works for both release and development)
// Inicializa el singleton del cache sin disparar la carga. La carga real
// la hace Director::iterate() llamando a Cache::loadStep() en cada frame,
// de forma que la ventana, los eventos y la barra de progreso están vivos
// desde el primer tick.
Resource::Cache::init();
Notifier::init("", "8bithud");
RenderInfo::init();
Console::init("8bithud");
Screen::get()->setNotificationsEnabled(true);
Resource::Cache::get()->beginLoad();
// Special handling for gamecontrollerdb.txt - SDL needs filesystem path
#if defined(RELEASE_BUILD) && !defined(__EMSCRIPTEN__)
@@ -198,6 +199,22 @@ Director::Director() {
Input::get()->applyKeyboardBindingsFromOptions();
Input::get()->applyGamepadBindingsFromOptions();
std::cout << "\n"; // Fin de inicialización mínima de sistemas
// Construeix l'escena inicial (BootLoader). finishBoot() la canviarà a
// LOGO (o la que digui Debug) quan Cache::loadStep() complete la càrrega.
SceneManager::current = SceneManager::Scene::BOOT_LOADER;
switchToActiveScene();
}
// Inicialitzacions que depenen del cache poblat. Es crida des d'iterate()
// just quan Cache::loadStep() retorna true, amb la finestra i el bucle ja vius.
void Director::finishBoot() {
Notifier::init("", "8bithud");
RenderInfo::init();
Console::init("8bithud");
Screen::get()->setNotificationsEnabled(true);
#ifdef _DEBUG
Debug::init();
#ifdef __EMSCRIPTEN__
@@ -210,10 +227,11 @@ Director::Director() {
SceneManager::current = Debug::get()->getInitialScene();
#endif
MapEditor::init();
#else
// En release, pasamos a LOGO siempre tras la carga
SceneManager::current = SceneManager::Scene::LOGO;
#endif
std::cout << "\n"; // Fin de inicialización de sistemas
// Inicializa el sistema de localización (antes de Cheevos que usa textos traducidos)
#if defined(RELEASE_BUILD) && !defined(__EMSCRIPTEN__)
{
@@ -234,15 +252,17 @@ Director::Director() {
#else
Cheevos::init(Resource::List::get()->get("cheevos.bin"));
#endif
// Construeix la primera escena (LOGO per defecte, o la que digui Debug)
switchToActiveScene();
}
Director::~Director() {
// Guarda las opciones a un fichero
Options::saveToFile();
// Destruir l'escena activa ABANS dels singletons. Si no, el unique_ptr membre
// destrueix l'escena al final del destructor — quan Audio, Screen, Resource...
// ja són morts — i qualsevol accés en els seus destructors és un UAF.
active_scene_.reset();
// Destruye los singletones
Cheevos::destroy();
Locale::destroy();
@@ -356,6 +376,10 @@ void Director::switchToActiveScene() {
active_scene_.reset();
switch (SceneManager::current) {
case SceneManager::Scene::BOOT_LOADER:
active_scene_ = std::make_unique<BootLoader>();
break;
case SceneManager::Scene::LOGO:
active_scene_ = std::make_unique<Logo>();
break;
@@ -406,6 +430,26 @@ auto Director::iterate() -> SDL_AppResult {
return SDL_APP_SUCCESS;
}
// Fase de boot: anem cridant loadStep() fins que el cache estiga ple.
// Durant aquesta fase l'escena activa és BootLoader (una barra de progrés).
if (boot_loading_) {
try {
// Budget de 50ms: durant el boot el joc va a ~15-20 FPS, suficient
// per veure la barra avançar suau i processar events del WM/ESC,
// i evita el 50% d'ineficiència que provocaria un budget < vsync.
if (Resource::Cache::get()->loadStep(50 /*ms*/)) {
finishBoot();
boot_loading_ = false;
// finishBoot() ja ha fixat SceneManager::current a LOGO (o la que
// digui Debug). El canvi d'escena es fa just a sota.
}
} catch (const std::exception& e) {
std::cerr << "Fatal error during resource load: " << e.what() << '\n';
SceneManager::current = SceneManager::Scene::QUIT;
return SDL_APP_FAILURE;
}
}
// Si l'escena ha canviat (o s'ha demanat RESTART_CURRENT), canviar-la abans del frame
if (SceneManager::current != current_scene_ || SceneManager::current == SceneManager::Scene::RESTART_CURRENT) {
switchToActiveScene();

View File

@@ -22,11 +22,13 @@ class Director {
std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos
std::unique_ptr<Scene> active_scene_; // Escena activa
SceneManager::Scene current_scene_{SceneManager::Scene::LOGO}; // Tipus d'escena activa
std::unique_ptr<Scene> active_scene_; // Escena activa
SceneManager::Scene current_scene_{SceneManager::Scene::BOOT_LOADER}; // Tipus d'escena activa
bool boot_loading_{true}; // True mientras Cache::loadStep() no haya acabado
// --- Funciones ---
void createSystemFolder(const std::string& folder); // Crea la carpeta del sistema donde guardar datos
void setFileList(); // Carga la configuración de assets desde assets.yaml
void switchToActiveScene(); // Construeix l'escena segons SceneManager::current
void finishBoot(); // Inits que dependen del cache, ejecutado tras loadStep==done
};