From 3fc6795593c05b561c7e6923424b9b696b60a0e7 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 31 Mar 2026 07:14:58 +0200 Subject: [PATCH] decrementada la responsabilitat d'Screen i afegit PaletteManager --- CMakeLists.txt | 15 +-- Makefile | 57 +++++------ source/core/rendering/palette_manager.cpp | 104 +++++++++++++++++++ source/core/rendering/palette_manager.hpp | 37 +++++++ source/core/rendering/screen.cpp | 115 ++++------------------ source/core/rendering/screen.hpp | 55 +++++------ 6 files changed, 224 insertions(+), 159 deletions(-) create mode 100644 source/core/rendering/palette_manager.cpp create mode 100644 source/core/rendering/palette_manager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1441696..6bcfb99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,31 +34,32 @@ set(APP_SOURCES # Core - Input source/core/input/global_inputs.cpp - source/core/input/input.cpp source/core/input/input_types.cpp + source/core/input/input.cpp source/core/input/mouse.cpp # Core - Rendering source/core/rendering/gif.cpp + source/core/rendering/palette_manager.cpp source/core/rendering/pixel_reveal.cpp source/core/rendering/render_info.cpp source/core/rendering/screen.cpp - source/core/rendering/surface.cpp source/core/rendering/sprite/animated_sprite.cpp source/core/rendering/sprite/dissolve_sprite.cpp source/core/rendering/sprite/moving_sprite.cpp source/core/rendering/sprite/sprite.cpp + source/core/rendering/surface.cpp source/core/rendering/text.cpp # Core - Locale source/core/locale/locale.cpp # Core - Resources - source/core/resources/resource_list.cpp source/core/resources/resource_cache.cpp - source/core/resources/resource_pack.cpp - source/core/resources/resource_loader.cpp source/core/resources/resource_helper.cpp + source/core/resources/resource_list.cpp + source/core/resources/resource_loader.cpp + source/core/resources/resource_pack.cpp # Core - System source/core/system/director.cpp @@ -78,9 +79,9 @@ set(APP_SOURCES source/game/gameplay/enemy_manager.cpp source/game/gameplay/item_manager.cpp source/game/gameplay/item_tracker.cpp - source/game/gameplay/room.cpp source/game/gameplay/room_loader.cpp source/game/gameplay/room_tracker.cpp + source/game/gameplay/room.cpp source/game/gameplay/scoreboard.cpp source/game/gameplay/stats.cpp source/game/gameplay/tilemap_renderer.cpp @@ -89,8 +90,8 @@ set(APP_SOURCES source/game/scenes/credits.cpp source/game/scenes/ending.cpp source/game/scenes/ending2.cpp - source/game/scenes/game.cpp source/game/scenes/game_over.cpp + source/game/scenes/game.cpp source/game/scenes/loading_screen.cpp source/game/scenes/logo.cpp source/game/scenes/title.cpp diff --git a/Makefile b/Makefile index 7ce096c..cb3a557 100644 --- a/Makefile +++ b/Makefile @@ -84,57 +84,58 @@ LINUX_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-linux.tar.g APP_SOURCES := \ source/main.cpp \ source/core/audio/audio.cpp \ - source/core/input/input.cpp \ - source/core/input/input_types.cpp \ - source/core/input/mouse.cpp \ source/core/input/global_inputs.cpp \ - source/core/rendering/screen.cpp \ - source/core/rendering/surface.cpp \ - source/core/rendering/sprite/sprite.cpp \ - source/core/rendering/sprite/animated_sprite.cpp \ - source/core/rendering/sprite/moving_sprite.cpp \ - source/core/rendering/sprite/dissolve_sprite.cpp \ - source/core/rendering/text.cpp \ + source/core/input/input_types.cpp \ + source/core/input/input.cpp \ + source/core/input/mouse.cpp \ + source/core/locale/locale.cpp \ source/core/rendering/gif.cpp \ + source/core/rendering/palette_manager.cpp \ source/core/rendering/pixel_reveal.cpp \ source/core/rendering/render_info.cpp \ + source/core/rendering/screen.cpp \ source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp \ - source/core/locale/locale.cpp \ - source/core/resources/resource_list.cpp \ + source/core/rendering/sprite/animated_sprite.cpp \ + source/core/rendering/sprite/dissolve_sprite.cpp \ + source/core/rendering/sprite/moving_sprite.cpp \ + source/core/rendering/sprite/sprite.cpp \ + source/core/rendering/surface.cpp \ + source/core/rendering/text.cpp \ source/core/resources/resource_cache.cpp \ source/core/resources/resource_helper.cpp \ + source/core/resources/resource_list.cpp \ source/core/resources/resource_loader.cpp \ source/core/resources/resource_pack.cpp \ - source/core/system/director.cpp \ source/core/system/debug.cpp \ + source/core/system/director.cpp \ source/core/system/global_events.cpp \ - source/game/options.cpp \ - source/game/entities/player.cpp \ source/game/entities/enemy.cpp \ source/game/entities/item.cpp \ - source/game/gameplay/room.cpp \ + source/game/entities/player.cpp \ + source/game/gameplay/cheevos.cpp \ source/game/gameplay/collision_map.cpp \ source/game/gameplay/enemy_manager.cpp \ source/game/gameplay/item_manager.cpp \ - source/game/gameplay/room_loader.cpp \ - source/game/gameplay/tilemap_renderer.cpp \ - source/game/gameplay/scoreboard.cpp \ - source/game/gameplay/cheevos.cpp \ source/game/gameplay/item_tracker.cpp \ + source/game/gameplay/room_loader.cpp \ source/game/gameplay/room_tracker.cpp \ + source/game/gameplay/room.cpp \ + source/game/gameplay/scoreboard.cpp \ source/game/gameplay/stats.cpp \ - source/game/scenes/logo.cpp \ - source/game/scenes/loading_screen.cpp \ - source/game/scenes/title.cpp \ - source/game/scenes/game.cpp \ - source/game/scenes/game_over.cpp \ + source/game/gameplay/tilemap_renderer.cpp \ + source/game/options.cpp \ + source/game/scenes/credits.cpp \ source/game/scenes/ending.cpp \ source/game/scenes/ending2.cpp \ - source/game/scenes/credits.cpp \ - source/game/ui/notifier.cpp \ + source/game/scenes/game_over.cpp \ + source/game/scenes/game.cpp \ + source/game/scenes/loading_screen.cpp \ + source/game/scenes/logo.cpp \ + source/game/scenes/title.cpp \ source/game/ui/console.cpp \ - source/utils/utils.cpp \ + source/game/ui/notifier.cpp \ source/utils/delta_timer.cpp + source/utils/utils.cpp \ # All sources combined ALL_SOURCES := $(APP_SOURCES) diff --git a/source/core/rendering/palette_manager.cpp b/source/core/rendering/palette_manager.cpp new file mode 100644 index 0000000..9f91ced --- /dev/null +++ b/source/core/rendering/palette_manager.cpp @@ -0,0 +1,104 @@ +#include "core/rendering/palette_manager.hpp" + +#include +#include +#include + +#include "core/rendering/surface.hpp" +#include "core/resources/resource_cache.hpp" +#include "game/options.hpp" +#include "utils/utils.hpp" + +PaletteManager::PaletteManager( + std::vector raw_paths, + const std::string& initial_name, + std::shared_ptr game_surface, + std::shared_ptr border_surface, + OnChangeCallback on_change) + : palettes_(std::move(raw_paths)), + game_surface_(std::move(game_surface)), + border_surface_(std::move(border_surface)), + on_change_(std::move(on_change)) { + current_ = findIndex(initial_name); + + // Leer y aplicar paleta inicial directamente desde el archivo + // (Resource::Cache aún no está disponible en este punto del ciclo de vida) + const auto initial_palette = readPalFile(palettes_.at(current_)); + game_surface_->setPalette(initial_palette); + border_surface_->setPalette(initial_palette); + + // Procesar la lista: conservar solo los nombres de archivo (sin ruta) + processPathList(); +} + +void PaletteManager::next() { + if (++current_ == palettes_.size()) { + current_ = 0; + } + apply(); +} + +void PaletteManager::previous() { + current_ = (current_ > 0) ? current_ - 1 : palettes_.size() - 1; + apply(); +} + +auto PaletteManager::setByName(const std::string& name) -> bool { + const std::string upper_name = toUpper(name + ".pal"); + for (size_t i = 0; i < palettes_.size(); ++i) { + if (toUpper(palettes_[i]) == upper_name) { + current_ = i; + apply(); + return true; + } + } + return false; +} + +auto PaletteManager::getNames() const -> std::vector { + std::vector names; + names.reserve(palettes_.size()); + for (const auto& p : palettes_) { + std::string name = p; + const size_t pos = name.find(".pal"); + if (pos != std::string::npos) { name.erase(pos, 4); } + std::ranges::transform(name, name.begin(), ::toupper); + names.push_back(std::move(name)); + } + return names; +} + +auto PaletteManager::getCurrentName() const -> std::string { + std::string name = palettes_.at(current_); + const size_t pos = name.find(".pal"); + if (pos != std::string::npos) { name.erase(pos, 4); } + std::ranges::transform(name, name.begin(), ::toupper); + return name; +} + +void PaletteManager::apply() { + game_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_))); + border_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_))); + + Options::video.palette = getCurrentName(); + + if (on_change_) { + on_change_(); + } +} + +auto PaletteManager::findIndex(const std::string& name) const -> size_t { + const std::string upper_name = toUpper(name + ".pal"); + for (size_t i = 0; i < palettes_.size(); ++i) { + if (toUpper(getFileName(palettes_[i])) == upper_name) { + return i; + } + } + return 0; +} + +void PaletteManager::processPathList() { + for (auto& palette : palettes_) { + palette = getFileName(palette); + } +} diff --git a/source/core/rendering/palette_manager.hpp b/source/core/rendering/palette_manager.hpp new file mode 100644 index 0000000..fd86d5c --- /dev/null +++ b/source/core/rendering/palette_manager.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include + +class Surface; + +class PaletteManager { + public: + using OnChangeCallback = std::function; + + PaletteManager( + std::vector raw_paths, + const std::string& initial_name, + std::shared_ptr game_surface, + std::shared_ptr border_surface, + OnChangeCallback on_change = nullptr); + + void next(); // Avanza a la siguiente paleta + void previous(); // Retrocede a la paleta anterior + auto setByName(const std::string& name) -> bool; // Cambia a paleta por nombre; false si no existe + [[nodiscard]] auto getNames() const -> std::vector; // Nombres disponibles (mayúsculas, sin .pal) + [[nodiscard]] auto getCurrentName() const -> std::string; // Nombre de la paleta actual (mayúsculas, sin .pal) + + private: + void apply(); // Aplica la paleta actual a ambas surfaces + [[nodiscard]] auto findIndex(const std::string& name) const -> size_t; // Localiza paleta por nombre en el vector + void processPathList(); // Extrae nombres de archivo de las rutas completas + + std::vector palettes_; + size_t current_{0}; + std::shared_ptr game_surface_; + std::shared_ptr border_surface_; + OnChangeCallback on_change_; +}; diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index a424dc3..b2b7ff9 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -42,8 +42,7 @@ auto Screen::get() -> Screen* { } // Constructor -Screen::Screen() - : palettes_(Resource::List::get()->getListByType(Resource::List::Type::PALETTE)) { +Screen::Screen() { // Arranca SDL VIDEO, crea la ventana y el renderizador initSDLVideo(); if (Options::video.fullscreen) { SDL_HideCursor(); } @@ -55,7 +54,6 @@ Screen::Screen() // Ajusta los tamaños game_surface_dstrect_ = {.x = Options::video.border.width, .y = Options::video.border.height, .w = Options::game.width, .h = Options::game.height}; - current_palette_ = findPalette(Options::video.palette); // Define el color del borde para el modo de pantalla completa border_color_ = static_cast(PaletteColor::BLACK); @@ -76,19 +74,27 @@ Screen::Screen() } SDL_SetTextureScaleMode(border_texture_, SDL_SCALEMODE_NEAREST); - // Cargar la paleta una sola vez - auto initial_palette = readPalFile(palettes_.at(current_palette_)); - - // Crea la surface donde se dibujan los graficos del juego + // Crea las surfaces (PaletteManager aplicará la paleta inicial en su constructor) game_surface_ = std::make_shared(Options::game.width, Options::game.height); - game_surface_->setPalette(initial_palette); game_surface_->clear(static_cast(PaletteColor::BLACK)); - // Crea la surface para el borde de colores border_surface_ = std::make_shared(Options::game.width + (Options::video.border.width * 2), Options::game.height + (Options::video.border.height * 2)); - border_surface_->setPalette(initial_palette); border_surface_->clear(border_color_); + // Crea el gestor de paletas; aplica la paleta inicial a ambas surfaces + palette_manager_ = std::make_unique( + Resource::List::get()->getListByType(Resource::List::Type::PALETTE), + Options::video.palette, + game_surface_, + border_surface_, + [this]() { + // Actualizar caché ARGB del borde cuando cambia la paleta + if (border_is_solid_) { + border_surface_->toARGBBuffer(border_pixel_buffer_.data()); + border_argb_color_ = border_pixel_buffer_[0]; + } + }); + // Cachear el color ARGB inicial del borde (borde sólido por defecto) border_surface_->toARGBBuffer(border_pixel_buffer_.data()); border_argb_color_ = border_pixel_buffer_[0]; @@ -99,9 +105,6 @@ Screen::Screen() // Crea el objeto de texto para la pantalla de carga createText(); - // Extrae el nombre de las paletas desde su ruta - processPaletteList(); - // Renderizar una vez la textura vacía para que tenga contenido válido // antes de inicializar los shaders (evita pantalla negra) SDL_RenderTexture(renderer_, game_texture_, nullptr, nullptr); @@ -357,55 +360,10 @@ void Screen::setRendererSurface(const std::shared_ptr& surface) { } // Cambia la paleta -void Screen::nextPalette() { - ++current_palette_; - if (current_palette_ == static_cast(palettes_.size())) { - current_palette_ = 0; - } - - setPalete(); -} +void Screen::nextPalette() { palette_manager_->next(); } // Cambia la paleta -void Screen::previousPalette() { - if (current_palette_ > 0) { - --current_palette_; - } else { - current_palette_ = static_cast(palettes_.size() - 1); - } - - setPalete(); -} - -// Establece la paleta -void Screen::setPalete() { // NOLINT(readability-convert-member-functions-to-static) - game_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_palette_))); - border_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_palette_))); - - Options::video.palette = palettes_.at(current_palette_); - - // Eliminar ".gif" - size_t pos = Options::video.palette.find(".pal"); - if (pos != std::string::npos) { - Options::video.palette.erase(pos, 4); - } - - // Convertir a mayúsculas - std::ranges::transform(Options::video.palette, Options::video.palette.begin(), ::toupper); - - // Actualizar caché si el borde es sólido (la paleta cambia el valor ARGB del color) - if (border_is_solid_) { - border_surface_->toARGBBuffer(border_pixel_buffer_.data()); - border_argb_color_ = border_pixel_buffer_[0]; - } -} - -// Extrae los nombres de las paletas -void Screen::processPaletteList() { - for (auto& palette : palettes_) { - palette = getFileName(palette); - } -} +void Screen::previousPalette() { palette_manager_->previous(); } // Copia la surface a la textura void Screen::surfaceToTexture() { // NOLINT(readability-convert-member-functions-to-static) @@ -485,44 +443,11 @@ void Screen::renderOverlays() { if (Console::get() != nullptr) { Console::get()->render(); } // Console (encima) } -// Localiza la paleta dentro del vector de paletas -auto Screen::findPalette(const std::string& name) -> size_t { // NOLINT(readability-convert-member-functions-to-static) - std::string upper_name = toUpper(name + ".pal"); - - for (size_t i = 0; i < palettes_.size(); ++i) { - if (toUpper(getFileName(palettes_[i])) == upper_name) { - return i; - } - } - return static_cast(0); -} - // Cambia a una paleta por nombre (case-insensitive); devuelve false si no existe -bool Screen::setPaletteByName(const std::string& name) { - const std::string upper_name = toUpper(name + ".pal"); - for (size_t i = 0; i < palettes_.size(); ++i) { - if (toUpper(getFileName(palettes_[i])) == upper_name) { - current_palette_ = static_cast(i); - setPalete(); - return true; - } - } - return false; -} +auto Screen::setPaletteByName(const std::string& name) -> bool { return palette_manager_->setByName(name); } // Devuelve los nombres de paletas disponibles (mayúsculas, sin extensión .pal) -auto Screen::getPaletteNames() const -> std::vector { - std::vector names; - names.reserve(palettes_.size()); - for (const auto& p : palettes_) { - std::string name = p; - const size_t pos = name.find(".pal"); - if (pos != std::string::npos) { name.erase(pos, 4); } - std::ranges::transform(name, name.begin(), ::toupper); - names.push_back(std::move(name)); - } - return names; -} +auto Screen::getPaletteNames() const -> std::vector { return palette_manager_->getNames(); } // Limpia la game_surface_ void Screen::clearSurface(Uint8 index) { game_surface_->clear(index); } diff --git a/source/core/rendering/screen.hpp b/source/core/rendering/screen.hpp index dca9931..426d892 100644 --- a/source/core/rendering/screen.hpp +++ b/source/core/rendering/screen.hpp @@ -9,8 +9,9 @@ #include // Para std::pair #include // Para vector -#include "core/rendering/shader_backend.hpp" // Para Rendering::ShaderType, ShaderBackend -#include "utils/utils.hpp" // Para Color +#include "core/rendering/palette_manager.hpp" // Para PaletteManager +#include "core/rendering/shader_backend.hpp" // Para Rendering::ShaderType, ShaderBackend +#include "utils/utils.hpp" // Para Color class Surface; class Text; @@ -35,15 +36,15 @@ class Screen { void update(float delta_time); // Actualiza la lógica de la clase // Video y ventana - void setVideoMode(bool mode); // Establece el modo de video - void toggleVideoMode(); // Cambia entre pantalla completa y ventana - void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero - void toggleVSync(); // Alterna entre activar y desactivar el V-Sync - auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana - auto incWindowZoom() -> bool; // Aumenta el tamaño de la ventana + void setVideoMode(bool mode); // Establece el modo de video + void toggleVideoMode(); // Cambia entre pantalla completa y ventana + void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero + void toggleVSync(); // Alterna entre activar y desactivar el V-Sync + auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana + auto incWindowZoom() -> bool; // Aumenta el tamaño de la ventana auto setWindowZoom(int zoom) -> bool; // Establece zoom directo; false si fuera de [1, max_zoom] - void show(); // Muestra la ventana - void hide(); // Oculta la ventana + void show(); // Muestra la ventana + void hide(); // Oculta la ventana // Borde void setBorderColor(Uint8 color); // Cambia el color del borde @@ -55,8 +56,7 @@ class Screen { // Paletas y PostFX void nextPalette(); // Cambia a la siguiente paleta void previousPalette(); // Cambia a la paleta anterior - void setPalete(); // Establece la paleta actual - bool setPaletteByName(const std::string& name); // Cambia a paleta por nombre; false si no existe + auto setPaletteByName(const std::string& name) -> bool; // Cambia a paleta por nombre; false si no existe [[nodiscard]] auto getPaletteNames() const -> std::vector; // Nombres disponibles (mayúsculas, sin .pal) void toggleShaders(); // Activa/desactiva todos los shaders respetando current_shader void toggleSupersampling(); // Activa/desactiva el supersampling global @@ -120,20 +120,18 @@ class Screen { static Screen* screen; // Métodos privados - void renderNotifications() const; // Dibuja las notificaciones - void adjustWindowSize(); // Calcula el tamaño de la ventana - void adjustRenderLogicalSize(); // Ajusta el tamaño lógico del renderizador - void processPaletteList(); // Extrae los nombres de las paletas - void surfaceToTexture(); // Copia la surface a la textura - void textureToRenderer(); // Copia la textura al renderizador - void renderOverlays(); // Renderiza todos los overlays - auto findPalette(const std::string& name) -> size_t; // Localiza la paleta dentro del vector de paletas - void initShaders(); // Inicializa los shaders - void applyCurrentPostFXPreset(); // Aplica los parámetros del preset PostFX actual al backend - void applyCurrentCrtPiPreset(); // Aplica los parámetros del preset CrtPi actual al backend - void getDisplayInfo(); // Obtiene información sobre la pantalla - auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana - void createText(); // Crea el objeto de texto + void renderNotifications() const; // Dibuja las notificaciones + void adjustWindowSize(); // Calcula el tamaño de la ventana + void adjustRenderLogicalSize(); // Ajusta el tamaño lógico del renderizador + void surfaceToTexture(); // Copia la surface a la textura + void textureToRenderer(); // Copia la textura al renderizador + void renderOverlays(); // Renderiza todos los overlays + void initShaders(); // Inicializa los shaders + void applyCurrentPostFXPreset(); // Aplica los parámetros del preset PostFX actual al backend + void applyCurrentCrtPiPreset(); // Aplica los parámetros del preset CrtPi actual al backend + void getDisplayInfo(); // Obtiene información sobre la pantalla + auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana + void createText(); // Crea el objeto de texto // Constructor y destructor Screen(); @@ -167,9 +165,8 @@ class Screen { SDL_FRect game_surface_dstrect_; // Coordenadas donde se dibuja la textura del juego // Paletas y colores - Uint8 border_color_{0}; // Color del borde - std::vector palettes_; // Listado de ficheros de paleta disponibles - Uint8 current_palette_{0}; // Índice para el vector de paletas + Uint8 border_color_{0}; // Color del borde + std::unique_ptr palette_manager_; // Gestor de paletas de color // Estado y configuración bool notifications_enabled_{false}; // Indica si se muestran las notificaciones