#pragma once #include #include namespace Levels { // Font de veritat de la progressió de sales del joc. Carrega // `data/maps/levels.yaml` a la primera crida a `get()` i exposa l'estat // "on sóc ara" + les operacions per moure'm. La GameScene, l'Editor i // els salts de debug consulten aquest singleton; ningú no manté el seu // propi índex de progressió. // // Meyers singleton: la destrucció estàtica només toca std::string i // std::vector, així que és segura sense ordenació explícita. class LevelManager { public: static auto get() -> LevelManager&; LevelManager(const LevelManager&) = delete; LevelManager(LevelManager&&) = delete; auto operator=(const LevelManager&) -> LevelManager& = delete; auto operator=(LevelManager&&) -> LevelManager& = delete; // Una entrada del `levels.yaml`. `file` és la ruta relativa al data // root (mateixa convenció que la resta de YAML del joc); pyramid i // room són purament informatius (logs i text d'intro). struct Entry { int pyramid{0}; int room{0}; std::string file; }; // Ruta del nivell actualment apuntat. Sempre vàlida un cop carregat // l'índex (entries_ no pot estar buit). Pensada per a `Map::loadFrom`, // `EntityManager::reload` i l'Editor. [[nodiscard]] auto currentPath() const -> const std::string&; [[nodiscard]] auto currentPyramid() const -> int; [[nodiscard]] auto currentRoom() const -> int; // "P1-R3" — útil per a logs i el text d'intro de sala. [[nodiscard]] auto currentLabel() const -> std::string; // Posició dins de la seqüència. `count()` és el total de sales // carregades del YAML (no necessàriament 30: si afegeixes/treus // entrades de `levels.yaml`, el manager s'adapta). [[nodiscard]] auto index() const -> int; [[nodiscard]] auto count() const -> int; // Avança al següent nivell. Retorna true si avança, false si ja // estava a l'últim. NO fa loop — la GameScene decideix la política // (loop a la primera, fi de joc, etc.) segons el context. auto advance() -> bool; // Torna al primer nivell. void restart(); // Salta a un índex concret. Clamp als bordes [0, count()-1]. // Pensat per als hotkeys debug. void setIndex(int new_index); // Posiciona l'índex a la primera entrada que coincideix amb // (pyramid, room). Retorna true si trobada; si no, l'índex no // es modifica i el caller decideix què fer (típicament ignorar i // arrencar des de la primera sala). Pensat per al // `debug.yaml.starting_level` i per a futures lookups per coords. auto setStartingPoint(int pyramid, int room) -> bool; private: LevelManager(); ~LevelManager() = default; // Carrega `data/maps/levels.yaml` via `Resource::Helper::loadFile`. // Si manca, és invàlid o té la seqüència buida, llança — no té sentit // continuar sense progressió de sales. void loadIndex(); std::vector entries_; int index_{0}; }; } // namespace Levels