diff --git a/CMakeLists.txt b/CMakeLists.txt index cc5c904..d695686 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,6 +216,7 @@ list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX ".*/external/.*") # Para clang-tidy, también excluir jail_audio.hpp set(CLANG_TIDY_SOURCES ${ALL_SOURCE_FILES}) list(FILTER CLANG_TIDY_SOURCES EXCLUDE REGEX ".*jail_audio\\.hpp$") +list(FILTER CLANG_TIDY_SOURCES EXCLUDE REGEX ".*_spv\\.h$") # Targets de clang-tidy if(CLANG_TIDY_EXE) diff --git a/source/core/input/global_inputs.cpp b/source/core/input/global_inputs.cpp index 2d5b510..11cb7ff 100644 --- a/source/core/input/global_inputs.cpp +++ b/source/core/input/global_inputs.cpp @@ -161,7 +161,7 @@ auto getPressedAction() -> InputAction { } } if (Input::get()->checkAction(InputAction::TOGGLE_POSTFX, Input::DO_NOT_ALLOW_REPEAT)) { - if (Options::video.postfx && (SDL_GetModState() & SDL_KMOD_SHIFT)) { + if (Options::video.postfx && ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0U)) { return InputAction::NEXT_POSTFX_PRESET; } return InputAction::TOGGLE_POSTFX; @@ -197,7 +197,7 @@ void handle() { if (Options::kiosk.enabled) { SDL_Keymod mod = SDL_GetModState(); const bool* ks = SDL_GetKeyboardState(nullptr); - if ((mod & SDL_KMOD_CTRL) && (mod & SDL_KMOD_SHIFT) && (mod & SDL_KMOD_ALT) && ks[SDL_SCANCODE_Q]) { + if (((mod & SDL_KMOD_CTRL) != 0U) && ((mod & SDL_KMOD_SHIFT) != 0U) && ((mod & SDL_KMOD_ALT) != 0U) && ks[SDL_SCANCODE_Q]) { SceneManager::current = SceneManager::Scene::QUIT; return; } diff --git a/source/core/rendering/pixel_reveal.cpp b/source/core/rendering/pixel_reveal.cpp index 41e3c3a..c34ebb1 100644 --- a/source/core/rendering/pixel_reveal.cpp +++ b/source/core/rendering/pixel_reveal.cpp @@ -1,6 +1,6 @@ #include "core/rendering/pixel_reveal.hpp" -#include // Para min +#include // Para min, ranges::all_of #include // Para iota #include // Para queue (BFS en modo ORDERED) #include // Para mt19937, shuffle @@ -30,7 +30,7 @@ PixelReveal::PixelReveal(int width, int height, float pixels_per_second, float s std::vector offsets; offsets.push_back(0); std::queue> bq; - bq.push({0, num_steps_}); + bq.emplace(0, num_steps_); while (static_cast(offsets.size()) < num_steps_) { auto [lo, hi] = bq.front(); bq.pop(); @@ -39,14 +39,14 @@ PixelReveal::PixelReveal(int width, int height, float pixels_per_second, float s } const int MID = (lo + hi) / 2; offsets.push_back(MID); - bq.push({lo, MID}); - bq.push({MID, hi}); + bq.emplace(lo, MID); + bq.emplace(MID, hi); } // Genera el orden: para cada offset, todas las columnas col = offset, offset+N, offset+2N, ... std::vector ordered_cols; ordered_cols.reserve(width_); - for (const int off : offsets) { - for (int col = off; col < width_; col += num_steps_) { + for (const int OFF : offsets) { + for (int col = OFF; col < width_; col += num_steps_) { ordered_cols.push_back(col); } } @@ -105,11 +105,6 @@ void PixelReveal::render(int dst_x, int dst_y) const { } // Indica si el revelado ha completado todas las filas -bool PixelReveal::isComplete() const { - for (const int step : row_step_) { - if (step < num_steps_) { - return false; - } - } - return true; +auto PixelReveal::isComplete() const -> bool { + return std::ranges::all_of(row_step_, [this](int s) { return s >= num_steps_; }); } diff --git a/source/core/rendering/pixel_reveal.hpp b/source/core/rendering/pixel_reveal.hpp index 76ce0de..e90f8ae 100644 --- a/source/core/rendering/pixel_reveal.hpp +++ b/source/core/rendering/pixel_reveal.hpp @@ -26,7 +26,7 @@ class PixelReveal { void render(int dst_x, int dst_y) const; // Indica si el revelado ha completado todas las filas - [[nodiscard]] bool isComplete() const; + [[nodiscard]] auto isComplete() const -> bool; private: std::shared_ptr cover_surface_; // Máscara negra que se va haciendo transparente diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 5c683be..7b48e49 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -392,7 +392,7 @@ auto Screen::findPalette(const std::string& name) -> size_t { } // Muestra información por pantalla -void Screen::renderInfo() { +void Screen::renderInfo() const { if (show_debug_info_ && (Resource::Cache::get() != nullptr)) { auto text = Resource::Cache::get()->getText("smb2"); auto color = static_cast(PaletteColor::YELLOW); @@ -459,7 +459,7 @@ auto loadData(const std::string& filepath) -> std::vector { void Screen::applyCurrentPostFXPreset() { if (shader_backend_ && !Options::postfx_presets.empty()) { const auto& p = Options::postfx_presets[static_cast(Options::current_postfx_preset)]; - Rendering::PostFXParams params{p.vignette, p.scanlines, p.chroma, p.mask, p.gamma, p.curvature, p.bleeding}; + Rendering::PostFXParams params{.vignette = p.vignette, .scanlines = p.scanlines, .chroma = p.chroma, .mask = p.mask, .gamma = p.gamma, .curvature = p.curvature, .bleeding = p.bleeding}; shader_backend_->setPostFXParams(params); } } diff --git a/source/core/rendering/screen.hpp b/source/core/rendering/screen.hpp index 8404265..31d33f4 100644 --- a/source/core/rendering/screen.hpp +++ b/source/core/rendering/screen.hpp @@ -116,7 +116,7 @@ class Screen { 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 actual al backend - void renderInfo(); // Muestra información por pantalla + void renderInfo() const; // Muestra información por pantalla 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 diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp index 3a94aac..c8feb7c 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -412,15 +412,15 @@ void SDL3GPUShader::render() { float vw = 0.0F; float vh = 0.0F; if (integer_scale_) { - const int scale = std::max(1, std::min(static_cast(sw) / tex_width_, static_cast(sh) / tex_height_)); - vw = static_cast(tex_width_ * scale); - vh = static_cast(tex_height_ * scale); + const int SCALE = std::max(1, std::min(static_cast(sw) / tex_width_, static_cast(sh) / tex_height_)); + vw = static_cast(tex_width_ * SCALE); + vh = static_cast(tex_height_ * SCALE); } else { - const float scale = std::min( + const float SCALE = std::min( static_cast(sw) / static_cast(tex_width_), static_cast(sh) / static_cast(tex_height_)); - vw = static_cast(tex_width_) * scale; - vh = static_cast(tex_height_) * scale; + vw = static_cast(tex_width_) * SCALE; + vh = static_cast(tex_height_) * SCALE; } vx = std::floor((static_cast(sw) - vw) * 0.5F); vy = std::floor((static_cast(sh) - vh) * 0.5F); diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp index 855b104..e87ecc1 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -40,7 +40,7 @@ class SDL3GPUShader : public ShaderBackend { void render() override; void setTextureSize(float width, float height) override {} - void cleanup() override; // Libera pipeline/texturas pero mantiene el device vivo + void cleanup() final; // Libera pipeline/texturas pero mantiene el device vivo void destroy(); // Limpieza completa (device + swapchain); llamar solo al cerrar [[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; } diff --git a/source/core/rendering/surface.cpp b/source/core/rendering/surface.cpp index 3c7fd52..32c12cb 100644 --- a/source/core/rendering/surface.cpp +++ b/source/core/rendering/surface.cpp @@ -430,19 +430,30 @@ void Surface::renderWithColorReplace(int x, int y, Uint8 source_color, Uint8 tar // Hash 2D estable per a dithering sense flickering static auto pixelThreshold(int col, int row) -> float { - auto h = static_cast(col) * 2246822519U ^ static_cast(row) * 2654435761U; + auto h = (static_cast(col) * 2246822519U) ^ (static_cast(row) * 2654435761U); h ^= (h >> 13); h *= 1274126177U; h ^= (h >> 16); return static_cast(h & 0xFFFFU) / 65536.0F; } +// Calcula la densidad de fade para un pixel en posición screen_y +static auto computeFadeDensity(int screen_y, int fade_h, int canvas_height) -> float { + if (screen_y < fade_h) { + return static_cast(fade_h - screen_y) / static_cast(fade_h); + } + if (screen_y >= canvas_height - fade_h) { + return static_cast(screen_y - (canvas_height - fade_h)) / static_cast(fade_h); + } + return 0.0F; +} + // Render amb dissolució als cantons superior/inferior (hash 2D, sense parpelleig) void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect) { - const int SX = src_rect ? static_cast(src_rect->x) : 0; - const int SY = src_rect ? static_cast(src_rect->y) : 0; - const int SW = src_rect ? static_cast(src_rect->w) : static_cast(surface_data_->width); - const int SH = src_rect ? static_cast(src_rect->h) : static_cast(surface_data_->height); + const int SX = (src_rect != nullptr) ? static_cast(src_rect->x) : 0; + const int SY = (src_rect != nullptr) ? static_cast(src_rect->y) : 0; + const int SW = (src_rect != nullptr) ? static_cast(src_rect->w) : static_cast(surface_data_->width); + const int SH = (src_rect != nullptr) ? static_cast(src_rect->h) : static_cast(surface_data_->height); auto surface_data_dest = Screen::get()->getRendererSurface()->getSurfaceData(); @@ -452,12 +463,7 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height continue; } - float density = 0.0F; - if (SCREEN_Y < fade_h) { - density = static_cast(fade_h - SCREEN_Y) / static_cast(fade_h); - } else if (SCREEN_Y >= canvas_height - fade_h) { - density = static_cast(SCREEN_Y - (canvas_height - fade_h)) / static_cast(fade_h); - } + const float DENSITY = computeFadeDensity(SCREEN_Y, fade_h, canvas_height); for (int col = 0; col < SW; col++) { const int SCREEN_X = x + col; @@ -465,12 +471,12 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height continue; } - const Uint8 COLOR = surface_data_->data[(SY + row) * static_cast(surface_data_->width) + (SX + col)]; + const Uint8 COLOR = surface_data_->data[((SY + row) * static_cast(surface_data_->width)) + (SX + col)]; if (static_cast(COLOR) == transparent_color_) { continue; } - if (pixelThreshold(col, row) < density) { + if (pixelThreshold(col, row) < DENSITY) { continue; // Pixel tapat per la zona de fade } @@ -481,10 +487,10 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height // Idem però reemplaçant un color índex void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect) { - const int SX = src_rect ? static_cast(src_rect->x) : 0; - const int SY = src_rect ? static_cast(src_rect->y) : 0; - const int SW = src_rect ? static_cast(src_rect->w) : static_cast(surface_data_->width); - const int SH = src_rect ? static_cast(src_rect->h) : static_cast(surface_data_->height); + const int SX = (src_rect != nullptr) ? static_cast(src_rect->x) : 0; + const int SY = (src_rect != nullptr) ? static_cast(src_rect->y) : 0; + const int SW = (src_rect != nullptr) ? static_cast(src_rect->w) : static_cast(surface_data_->width); + const int SH = (src_rect != nullptr) ? static_cast(src_rect->h) : static_cast(surface_data_->height); auto surface_data_dest = Screen::get()->getRendererSurface()->getSurfaceData(); @@ -494,12 +500,7 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height continue; } - float density = 0.0F; - if (SCREEN_Y < fade_h) { - density = static_cast(fade_h - SCREEN_Y) / static_cast(fade_h); - } else if (SCREEN_Y >= canvas_height - fade_h) { - density = static_cast(SCREEN_Y - (canvas_height - fade_h)) / static_cast(fade_h); - } + const float DENSITY = computeFadeDensity(SCREEN_Y, fade_h, canvas_height); for (int col = 0; col < SW; col++) { const int SCREEN_X = x + col; @@ -507,12 +508,12 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height continue; } - const Uint8 COLOR = surface_data_->data[(SY + row) * static_cast(surface_data_->width) + (SX + col)]; + const Uint8 COLOR = surface_data_->data[((SY + row) * static_cast(surface_data_->width)) + (SX + col)]; if (static_cast(COLOR) == transparent_color_) { continue; } - if (pixelThreshold(col, row) < density) { + if (pixelThreshold(col, row) < DENSITY) { continue; // Pixel tapat per la zona de fade } diff --git a/source/core/rendering/surface_animated_sprite.cpp b/source/core/rendering/surface_animated_sprite.cpp index 53e589a..df911da 100644 --- a/source/core/rendering/surface_animated_sprite.cpp +++ b/source/core/rendering/surface_animated_sprite.cpp @@ -219,7 +219,7 @@ SurfaceAnimatedSprite::SurfaceAnimatedSprite(std::shared_ptr surface, S : SurfaceMovingSprite(std::move(surface), pos) { // animations_ queda buit (protegit per el guard de animate()) if (surface_) { - clip_ = {0, 0, static_cast(surface_->getWidth()), static_cast(surface_->getHeight())}; + clip_ = {.x = 0, .y = 0, .w = surface_->getWidth(), .h = surface_->getHeight()}; } } @@ -239,7 +239,7 @@ auto SurfaceAnimatedSprite::getIndex(const std::string& name) -> int { // Calcula el frame correspondiente a la animación (time-based) void SurfaceAnimatedSprite::animate(float delta_time) { - if (animations_.empty()) return; + if (animations_.empty()) { return; } if (animations_[current_animation_].speed <= 0.0F) { return; } diff --git a/source/core/rendering/surface_dissolve_sprite.cpp b/source/core/rendering/surface_dissolve_sprite.cpp index b204265..6b357c7 100644 --- a/source/core/rendering/surface_dissolve_sprite.cpp +++ b/source/core/rendering/surface_dissolve_sprite.cpp @@ -7,7 +7,7 @@ // Hash 2D estable per a dithering (rank aleatori per posició de píxel) static auto pixelRank(int col, int row) -> float { - auto h = static_cast(col) * 2246822519U ^ static_cast(row) * 2654435761U; + auto h = (static_cast(col) * 2246822519U) ^ (static_cast(row) * 2654435761U); h ^= (h >> 13); h *= 1274126177U; h ^= (h >> 16); @@ -28,7 +28,7 @@ auto SurfaceDissolveSprite::computePixelRank(int col, int row, int frame_h, Diss y_factor = static_cast(frame_h - 1 - row) / static_cast(frame_h); } - return y_factor * 0.7F + RANDOM * 0.3F; + return (y_factor * 0.7F) + (RANDOM * 0.3F); } // Constructor per a surface directa (sense AnimationResource) @@ -92,14 +92,14 @@ void SurfaceDissolveSprite::rebuildDisplaySurface() { // Copia píxels filtrats per progress_ for (int row = 0; row < SH; ++row) { for (int col = 0; col < SW; ++col) { - const Uint8 COLOR = src_data->data[(SY + row) * SRC_W + (SX + col)]; + const Uint8 COLOR = src_data->data[((SY + row) * SRC_W) + (SX + col)]; if (COLOR == TRANSPARENT) { continue; } const float RANK = computePixelRank(col, row, SH, direction_); if (RANK >= progress_) { const Uint8 OUT = (COLOR == source_color_) ? target_color_ : COLOR; - dst_data->data[(SY + row) * DST_W + (SX + col)] = OUT; + dst_data->data[((SY + row) * DST_W) + (SX + col)] = OUT; } } } diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index a98f868..bcb3c9b 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -908,11 +908,7 @@ auto Player::getProjection(Direction direction, float displacement) -> SDL_FRect // Marca al jugador como muerto void Player::markAsDead() { - if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { - is_alive_ = true; // No puede morir - } else { - is_alive_ = false; // Muere - } + is_alive_ = (Options::cheats.invincible == Options::Cheat::State::ENABLED); } #ifdef _DEBUG diff --git a/source/game/gameplay/collision_map.cpp b/source/game/gameplay/collision_map.cpp index a4127a3..694c800 100644 --- a/source/game/gameplay/collision_map.cpp +++ b/source/game/gameplay/collision_map.cpp @@ -29,9 +29,9 @@ void CollisionMap::initializeSurfaces() { // Devuelve el tipo de tile que hay en ese pixel auto CollisionMap::getTile(SDL_FPoint point) const -> Tile { - const int row = static_cast(point.y / TILE_SIZE); - const int col = static_cast(point.x / TILE_SIZE); - const int POS = row * MAP_WIDTH + col; + const int ROW = static_cast(point.y / TILE_SIZE); + const int COL = static_cast(point.x / TILE_SIZE); + const int POS = (ROW * MAP_WIDTH) + COL; return getTile(POS); } diff --git a/source/game/options.cpp b/source/game/options.cpp index 7bda299..4339528 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -654,6 +654,13 @@ void setPostFXFile(const std::string& path) { postfx_file_path = path; } +// Helper: extrae un campo float de un nodo YAML si existe, ignorando errores de conversión +static void parseFloatField(const fkyaml::node& node, const std::string& key, float& target) { + if (node.contains(key)) { + try { target = node[key].get_value(); } catch (...) {} + } +} + // Carga los presets de PostFX desde el fichero auto loadPostFXFromFile() -> bool { postfx_presets.clear(); @@ -675,47 +682,18 @@ auto loadPostFXFromFile() -> bool { if (yaml.contains("presets")) { const auto& presets = yaml["presets"]; - for (size_t i = 0; i < presets.size(); ++i) { - const auto& p = presets[i]; + for (const auto& p : presets) { PostFXPreset preset; if (p.contains("name")) { preset.name = p["name"].get_value(); } - if (p.contains("vignette")) { - try { - preset.vignette = p["vignette"].get_value(); - } catch (...) {} - } - if (p.contains("scanlines")) { - try { - preset.scanlines = p["scanlines"].get_value(); - } catch (...) {} - } - if (p.contains("chroma")) { - try { - preset.chroma = p["chroma"].get_value(); - } catch (...) {} - } - if (p.contains("mask")) { - try { - preset.mask = p["mask"].get_value(); - } catch (...) {} - } - if (p.contains("gamma")) { - try { - preset.gamma = p["gamma"].get_value(); - } catch (...) {} - } - if (p.contains("curvature")) { - try { - preset.curvature = p["curvature"].get_value(); - } catch (...) {} - } - if (p.contains("bleeding")) { - try { - preset.bleeding = p["bleeding"].get_value(); - } catch (...) {} - } + parseFloatField(p, "vignette", preset.vignette); + parseFloatField(p, "scanlines", preset.scanlines); + parseFloatField(p, "chroma", preset.chroma); + parseFloatField(p, "mask", preset.mask); + parseFloatField(p, "gamma", preset.gamma); + parseFloatField(p, "curvature", preset.curvature); + parseFloatField(p, "bleeding", preset.bleeding); postfx_presets.push_back(preset); } } diff --git a/source/game/scenes/ending.cpp b/source/game/scenes/ending.cpp index 834010f..40b3612 100644 --- a/source/game/scenes/ending.cpp +++ b/source/game/scenes/ending.cpp @@ -111,6 +111,17 @@ void Ending::transitionToState(State new_state) { } } +// Lógica de fade común a los estados SCENE_N +void Ending::handleSceneFadeout(float scene_duration, float delta_time) { + if (state_time_ >= scene_duration - FADEOUT_START_OFFSET) { + fadeout_time_ += delta_time; + if (!scene_cover_) { + scene_cover_ = std::make_unique(Options::game.width, Options::game.height, COVER_PIXELS_PER_SECOND, STEP_DURATION, COVER_STEPS, true); + } + scene_cover_->update(fadeout_time_); + } +} + // Actualiza la máquina de estados void Ending::updateState(float delta_time) { state_time_ += delta_time; @@ -125,57 +136,27 @@ void Ending::updateState(float delta_time) { case State::SCENE_0: checkChangeScene(); - if (state_time_ >= SCENE_0_DURATION - FADEOUT_START_OFFSET) { - fadeout_time_ += delta_time; - if (!scene_cover_) { - scene_cover_ = std::make_unique(Options::game.width, Options::game.height, COVER_PIXELS_PER_SECOND, STEP_DURATION, COVER_STEPS, true); - } - scene_cover_->update(fadeout_time_); - } + handleSceneFadeout(SCENE_0_DURATION, delta_time); break; case State::SCENE_1: checkChangeScene(); - if (state_time_ >= SCENE_1_DURATION - FADEOUT_START_OFFSET) { - fadeout_time_ += delta_time; - if (!scene_cover_) { - scene_cover_ = std::make_unique(Options::game.width, Options::game.height, COVER_PIXELS_PER_SECOND, STEP_DURATION, COVER_STEPS, true); - } - scene_cover_->update(fadeout_time_); - } + handleSceneFadeout(SCENE_1_DURATION, delta_time); break; case State::SCENE_2: checkChangeScene(); - if (state_time_ >= SCENE_2_DURATION - FADEOUT_START_OFFSET) { - fadeout_time_ += delta_time; - if (!scene_cover_) { - scene_cover_ = std::make_unique(Options::game.width, Options::game.height, COVER_PIXELS_PER_SECOND, STEP_DURATION, COVER_STEPS, true); - } - scene_cover_->update(fadeout_time_); - } + handleSceneFadeout(SCENE_2_DURATION, delta_time); break; case State::SCENE_3: checkChangeScene(); - if (state_time_ >= SCENE_3_DURATION - FADEOUT_START_OFFSET) { - fadeout_time_ += delta_time; - if (!scene_cover_) { - scene_cover_ = std::make_unique(Options::game.width, Options::game.height, COVER_PIXELS_PER_SECOND, STEP_DURATION, COVER_STEPS, true); - } - scene_cover_->update(fadeout_time_); - } + handleSceneFadeout(SCENE_3_DURATION, delta_time); break; case State::SCENE_4: checkChangeScene(); - if (state_time_ >= SCENE_4_DURATION - FADEOUT_START_OFFSET) { - fadeout_time_ += delta_time; - if (!scene_cover_) { - scene_cover_ = std::make_unique(Options::game.width, Options::game.height, COVER_PIXELS_PER_SECOND, STEP_DURATION, COVER_STEPS, true); - } - scene_cover_->update(fadeout_time_); - } + handleSceneFadeout(SCENE_4_DURATION, delta_time); break; case State::ENDING: diff --git a/source/game/scenes/ending.hpp b/source/game/scenes/ending.hpp index 36130dc..3036630 100644 --- a/source/game/scenes/ending.hpp +++ b/source/game/scenes/ending.hpp @@ -82,8 +82,9 @@ class Ending { void iniTexts(); // Inicializa los textos void iniPics(); // Inicializa las imágenes void iniScenes(); // Inicializa las escenas - void updateState(float delta_time); // Actualiza la máquina de estados - void transitionToState(State new_state); // Transición entre estados + void updateState(float delta_time); // Actualiza la máquina de estados + void handleSceneFadeout(float scene_duration, float delta_time); // Lógica de fade común a los estados SCENE_N + void transitionToState(State new_state); // Transición entre estados void updateSpriteCovers(); // Actualiza las cortinillas de los elementos void checkChangeScene(); // Comprueba si se ha de cambiar de escena void updateMusicVolume() const; // Actualiza el volumen de la música diff --git a/source/game/scenes/ending2.cpp b/source/game/scenes/ending2.cpp index de759e2..4e4ddd7 100644 --- a/source/game/scenes/ending2.cpp +++ b/source/game/scenes/ending2.cpp @@ -285,7 +285,7 @@ void Ending2::updateSprites(float delta) { const float Y = sprite->getPosY(); const float H = sprite->getHeight(); - const float CANVAS_H = static_cast(Options::game.height); + const auto CANVAS_H = Options::game.height; // Checkpoint inferior: sprite entra per baix → generar de dalt a baix if (Y > static_cast(ENTRY_EXIT_PADDING) && Y <= CANVAS_H - H - ENTRY_EXIT_PADDING && sprite->getProgress() >= 1.0F && sprite->isTransitionDone()) { @@ -306,7 +306,7 @@ void Ending2::updateTextSprites(float delta) { const float Y = sprite->getPosY(); const float H = sprite->getHeight(); - const float CANVAS_H = static_cast(Options::game.height); + const auto CANVAS_H = Options::game.height; if (Y > static_cast(ENTRY_EXIT_PADDING) && Y <= CANVAS_H - H - ENTRY_EXIT_PADDING && sprite->getProgress() >= 1.0F && sprite->isTransitionDone()) { sprite->startGenerate(TRANSITION_DURATION_MS, DissolveDirection::UP); @@ -325,7 +325,7 @@ void Ending2::updateTexts(float delta) { const float Y = sprite->getPosY(); const float H = sprite->getHeight(); - const float CANVAS_H = static_cast(Options::game.height); + const auto CANVAS_H = Options::game.height; // Checkpoint inferior: text entra per baix → generar de dalt a baix if (Y > static_cast(ENTRY_EXIT_PADDING) && Y <= CANVAS_H - H - ENTRY_EXIT_PADDING && sprite->getProgress() >= 1.0F && sprite->isTransitionDone()) { diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index bed6922..25d78b2 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -366,6 +366,13 @@ void Game::renderPostFadeEnding() { } #ifdef _DEBUG +// Helper: alterna un cheat y muestra notificación con su estado +static void toggleCheat(Options::Cheat::State& cheat, const std::string& label) { + cheat = (cheat == Options::Cheat::State::ENABLED) ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED; + const bool ENABLED = (cheat == Options::Cheat::State::ENABLED); + Notifier::get()->show({label + (ENABLED ? " ENABLED" : " DISABLED")}, Notifier::Style::DEFAULT, -1, true); +} + // Pasa la información de debug void Game::updateDebugInfo() { // Debug::get()->add("X = " + std::to_string(static_cast(player_->x_)) + ", Y = " + std::to_string(static_cast(player_->y_))); @@ -437,20 +444,17 @@ void Game::handleDebugEvents(const SDL_Event& event) { break; case SDLK_1: - Options::cheats.infinite_lives = Options::cheats.infinite_lives == Options::Cheat::State::ENABLED ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED; - Notifier::get()->show({std::string("INFINITE LIVES ") + (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED ? "ENABLED" : "DISABLED")}, Notifier::Style::DEFAULT, -1, true); + toggleCheat(Options::cheats.infinite_lives, "INFINITE LIVES"); player_->setColor(); break; case SDLK_2: - Options::cheats.invincible = Options::cheats.invincible == Options::Cheat::State::ENABLED ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED; - Notifier::get()->show({std::string("INVINCIBLE ") + (Options::cheats.invincible == Options::Cheat::State::ENABLED ? "ENABLED" : "DISABLED")}, Notifier::Style::DEFAULT, -1, true); + toggleCheat(Options::cheats.invincible, "INVINCIBLE"); player_->setColor(); break; case SDLK_3: - Options::cheats.jail_is_open = Options::cheats.jail_is_open == Options::Cheat::State::ENABLED ? Options::Cheat::State::DISABLED : Options::Cheat::State::ENABLED; - Notifier::get()->show({std::string("JAIL IS OPEN ") + (Options::cheats.jail_is_open == Options::Cheat::State::ENABLED ? "ENABLED" : "DISABLED")}, Notifier::Style::DEFAULT, -1, true); + toggleCheat(Options::cheats.jail_is_open, "JAIL IS OPEN"); break; case SDLK_7: @@ -506,7 +510,7 @@ void Game::handleDebugMouseDrag(float delta_time) { // Calcular distancia al objetivo float dx = game_x - player_x; float dy = game_y - player_y; - float distance = std::sqrt(dx * dx + dy * dy); + float distance = std::sqrt((dx * dx) + (dy * dy)); // Constantes de velocidad con ease-in (aceleración progresiva) constexpr float DRAG_SPEED_MIN = 30.0F; // Velocidad inicial (pixels/segundo) @@ -517,13 +521,13 @@ void Game::handleDebugMouseDrag(float delta_time) { if (!debug_dragging_player_) { debug_drag_speed_ = DRAG_SPEED_MIN; // Iniciar con velocidad mínima } - debug_drag_speed_ = std::min(DRAG_SPEED_MAX, debug_drag_speed_ + DRAG_ACCELERATION * delta_time); + debug_drag_speed_ = std::min(DRAG_SPEED_MAX, debug_drag_speed_ + (DRAG_ACCELERATION * delta_time)); if (distance > 1.0F) { // Calcular el movimiento con la velocidad actual float move_factor = std::min(1.0F, debug_drag_speed_ * delta_time / distance); - float new_x = player_x + dx * move_factor; - float new_y = player_y + dy * move_factor; + float new_x = player_x + (dx * move_factor); + float new_y = player_y + (dy * move_factor); // Mover el jugador hacia la posición del cursor player_->setDebugPosition(new_x, new_y); diff --git a/source/game/scenes/game.hpp b/source/game/scenes/game.hpp index 739d550..ec301c5 100644 --- a/source/game/scenes/game.hpp +++ b/source/game/scenes/game.hpp @@ -66,10 +66,10 @@ class Game { void updateFadeToEnding(float delta_time); // Actualiza el juego en estado FADE_TO_ENDING void updatePostFadeEnding(float delta_time); // Actualiza el juego en estado POST_FADE_ENDING void renderPlaying(); // Renderiza el juego en estado PLAYING (directo a pantalla) - void renderBlackScreen(); // Renderiza el juego en estado BLACK_SCREEN (pantalla negra) - void renderGameOver(); // Renderiza el juego en estado GAME_OVER (pantalla negra) + static void renderBlackScreen(); // Renderiza el juego en estado BLACK_SCREEN (pantalla negra) + static void renderGameOver(); // Renderiza el juego en estado GAME_OVER (pantalla negra) void renderFadeToEnding(); // Renderiza el juego en estado FADE_TO_ENDING (via backbuffer) - void renderPostFadeEnding(); // Renderiza el juego en estado POST_FADE_ENDING (pantalla negra) + static void renderPostFadeEnding(); // Renderiza el juego en estado POST_FADE_ENDING (pantalla negra) auto changeRoom(const std::string& room_path) -> bool; // Cambia de habitación void handleInput(); // Comprueba el teclado void checkPlayerIsOnBorder(); // Comprueba si el jugador esta en el borde de la pantalla y actua