diff --git a/source/core/audio/jail_audio.hpp b/source/core/audio/jail_audio.hpp index 63308e0..a6289ac 100644 --- a/source/core/audio/jail_audio.hpp +++ b/source/core/audio/jail_audio.hpp @@ -265,13 +265,13 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) { auto* music = new JA_Music_t(); music->ogg_data.assign(buffer, buffer + length); - int error = 0; + int vorbis_error = 0; music->vorbis = stb_vorbis_open_memory(music->ogg_data.data(), static_cast(length), - &error, + &vorbis_error, nullptr); if (!music->vorbis) { - std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << error << ")" << '\n'; + std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << vorbis_error << ")" << '\n'; delete music; return nullptr; } diff --git a/source/core/input/input.cpp b/source/core/input/input.cpp index cb7c967..597c373 100644 --- a/source/core/input/input.cpp +++ b/source/core/input/input.cpp @@ -4,6 +4,7 @@ #include // Para basic_ostream, operator<<, cout, cerr #include // Para shared_ptr, __shared_ptr_access, allocator, operator==, make_shared +#include // Para ranges::any_of #include // Para __find_if_fn, find_if #include // Para unordered_map, _Node_iterator, operator==, _Node_iterator_base, _Node_const_iterator #include // Para pair, move @@ -182,14 +183,10 @@ auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr& g // Obtenemos el número total de acciones posibles para iterar sobre ellas. // --- Comprobación del Teclado --- - if (check_keyboard) { - for (const auto& pair : keyboard_.bindings) { - // Simplemente leemos el estado pre-calculado por Input::update(). - // Ya no se llama a SDL_GetKeyboardState ni se modifica el estado '.active'. - if (pair.second.just_pressed) { - return true; // Se encontró una acción recién pulsada. - } - } + // Llegim l'estat pre-calculat per Input::update() (sense tornar a cridar SDL_GetKeyboardState). + if (check_keyboard && std::ranges::any_of(keyboard_.bindings, + [](const auto& pair) { return pair.second.just_pressed; })) { + return true; } // Si gamepad es nullptr pero hay mandos conectados, usar el primero @@ -199,15 +196,10 @@ auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr& g } // --- Comprobación del Mando --- - // Comprobamos si hay mandos y si el índice solicitado es válido. - if (active_gamepad != nullptr) { - // Iteramos sobre todas las acciones, no sobre el número de mandos. - for (const auto& pair : active_gamepad->bindings) { - // Leemos el estado pre-calculado para el mando y la acción específicos. - if (pair.second.just_pressed) { - return true; // Se encontró una acción recién pulsada en el mando. - } - } + // Iterem sobre totes les accions del mandos pre-calculades per Input::update(). + if (active_gamepad != nullptr && std::ranges::any_of(active_gamepad->bindings, + [](const auto& pair) { return pair.second.just_pressed; })) { + return true; } // Si llegamos hasta aquí, no se detectó ninguna nueva pulsación. @@ -216,22 +208,14 @@ auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr& g // Comprueba si hay algún botón pulsado auto Input::checkAnyButton(bool repeat) -> bool { // NOLINT(readability-convert-member-functions-to-static) - // Solo comprueba los botones definidos previamente - for (auto bi : BUTTON_INPUTS) { - // Comprueba el teclado + return std::ranges::any_of(BUTTON_INPUTS, [&](auto bi) { if (checkAction(bi, repeat, CHECK_KEYBOARD)) { return true; } - - // Comprueba los mandos - for (const auto& gamepad : gamepads_) { - if (checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gamepad)) { - return true; - } - } - } - - return false; + return std::ranges::any_of(gamepads_, [&](const auto& gamepad) { + return checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gamepad); + }); + }); } // Comprueba si hay algun mando conectado @@ -245,9 +229,9 @@ auto Input::getControllerName(const std::shared_ptr& gamepad) -> std::s // Obtiene la lista de nombres de mandos auto Input::getControllerNames() const -> std::vector { std::vector names; - for (const auto& gamepad : gamepads_) { - names.push_back(gamepad->name); - } + names.reserve(gamepads_.size()); + std::ranges::transform(gamepads_, std::back_inserter(names), + [](const auto& gamepad) { return gamepad->name; }); return names; } @@ -256,21 +240,15 @@ auto Input::getNumGamepads() const -> int { return gamepads_.size(); } // Obtiene el gamepad a partir de un event.id auto Input::getGamepad(SDL_JoystickID id) const -> std::shared_ptr { // NOLINT(readability-convert-member-functions-to-static) - for (const auto& gamepad : gamepads_) { - if (gamepad->instance_id == id) { - return gamepad; - } - } - return nullptr; + auto it = std::ranges::find_if(gamepads_, + [id](const auto& gamepad) { return gamepad->instance_id == id; }); + return (it != gamepads_.end()) ? *it : nullptr; } auto Input::getGamepadByName(const std::string& name) const -> std::shared_ptr { // NOLINT(readability-convert-member-functions-to-static) - for (const auto& gamepad : gamepads_) { - if (gamepad && gamepad->name == name) { - return gamepad; - } - } - return nullptr; + auto it = std::ranges::find_if(gamepads_, + [&name](const auto& gamepad) { return gamepad && gamepad->name == name; }); + return (it != gamepads_.end()) ? *it : nullptr; } // Obtiene el SDL_GamepadButton asignado a un action @@ -511,19 +489,14 @@ auto Input::findAvailableGamepadByName(const std::string& gamepad_name) -> std:: } // Buscar por nombre - for (const auto& gamepad : gamepads_) { - if (gamepad && gamepad->name == gamepad_name) { - return gamepad; - } + auto by_name = std::ranges::find_if(gamepads_, + [&gamepad_name](const auto& gamepad) { return gamepad && gamepad->name == gamepad_name; }); + if (by_name != gamepads_.end()) { + return *by_name; } // Si no se encuentra por nombre, devolver el primer gamepad válido - for (const auto& gamepad : gamepads_) { - if (gamepad) { - return gamepad; - } - } - - // Si llegamos aquí, no hay gamepads válidos - return nullptr; + auto first_valid = std::ranges::find_if(gamepads_, + [](const auto& gamepad) { return static_cast(gamepad); }); + return (first_valid != gamepads_.end()) ? *first_valid : nullptr; } \ No newline at end of file diff --git a/source/core/rendering/palette_manager.cpp b/source/core/rendering/palette_manager.cpp index fc1bdc4..2b2fe9e 100644 --- a/source/core/rendering/palette_manager.cpp +++ b/source/core/rendering/palette_manager.cpp @@ -120,9 +120,7 @@ namespace { } // Si quedan colores sin asignar, añadirlos al final - for (const auto& c : available) { - result.push_back(c); - } + std::ranges::copy(available, std::back_inserter(result)); Palette out{}; out.fill(0); diff --git a/source/core/rendering/surface.cpp b/source/core/rendering/surface.cpp index 7b040ed..a33263d 100644 --- a/source/core/rendering/surface.cpp +++ b/source/core/rendering/surface.cpp @@ -415,7 +415,7 @@ static auto computeFadeDensity(int screen_y, int fade_h, int canvas_height) -> f } // 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 { +void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, const SDL_FRect* src_rect) const { 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) : surface_data_->width; @@ -452,7 +452,7 @@ 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 { +void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, const SDL_FRect* src_rect) const { 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) : surface_data_->width; diff --git a/source/core/rendering/surface.hpp b/source/core/rendering/surface.hpp index 572847d..7cb3032 100644 --- a/source/core/rendering/surface.hpp +++ b/source/core/rendering/surface.hpp @@ -87,10 +87,10 @@ class Surface { void renderWithColorReplace(int x, int y, Uint8 source_color = 0, Uint8 target_color = 0, SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE) const; // Render amb dissolució als cantons superior/inferior (hash 2D, sense parpelleig) - void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect = nullptr) const; + void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, const SDL_FRect* src_rect = nullptr) const; // Idem però reemplaçant un color índex (per a sprites sobre fons del mateix color) - void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect = nullptr) const; + void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, const SDL_FRect* src_rect = nullptr) const; // Establece un color en la paleta void setColor(int index, Uint32 color); diff --git a/source/core/resources/resource_cache.cpp b/source/core/resources/resource_cache.cpp index 9ff6f80..7ccfd4f 100644 --- a/source/core/resources/resource_cache.cpp +++ b/source/core/resources/resource_cache.cpp @@ -362,13 +362,13 @@ namespace Resource { return rooms_; } - // Helper para lanzar errores de carga con formato consistente - [[noreturn]] void Cache::throwLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e) { // NOLINT(readability-convert-member-functions-to-static) + // Helper para registrar errores de carga con formato consistente. + // El rethrow es responsabilitat del catch que crida la funció. + void Cache::logLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e) { // NOLINT(readability-convert-member-functions-to-static) std::cerr << "\n[ ERROR ] Failed to load " << asset_type << ": " << getFileName(file_path) << '\n'; std::cerr << "[ ERROR ] Path: " << file_path << '\n'; std::cerr << "[ ERROR ] Reason: " << e.what() << '\n'; std::cerr << "[ ERROR ] Check config/assets.yaml configuration\n"; - throw; } // Lista fija de text objects. Compartida entre createText() y createOneText(i). @@ -415,7 +415,8 @@ namespace Resource { printWithDots("Sound : ", name, "[ LOADED ]"); updateLoadingProgress(); } catch (const std::exception& e) { - throwLoadError("SOUND", l, e); + logLoadError("SOUND", l, e); + throw; } } @@ -442,7 +443,8 @@ namespace Resource { printWithDots("Music : ", name, "[ LOADED ]"); updateLoadingProgress(); } catch (const std::exception& e) { - throwLoadError("MUSIC", l, e); + logLoadError("MUSIC", l, e); + throw; } } @@ -456,7 +458,8 @@ namespace Resource { surfaces_.back().surface->setTransparentColor(0); updateLoadingProgress(); } catch (const std::exception& e) { - throwLoadError("BITMAP", l, e); + logLoadError("BITMAP", l, e); + throw; } } @@ -480,7 +483,8 @@ namespace Resource { palettes_.emplace_back(ResourcePalette{.name = name, .palette = readPalFile(l)}); updateLoadingProgress(); } catch (const std::exception& e) { - throwLoadError("PALETTE", l, e); + logLoadError("PALETTE", l, e); + throw; } } @@ -493,7 +497,8 @@ namespace Resource { text_files_.emplace_back(TextFileResource{.name = name, .text_file = Text::loadTextFile(l)}); updateLoadingProgress(); } catch (const std::exception& e) { - throwLoadError("FONT", l, e); + logLoadError("FONT", l, e); + throw; } } @@ -513,7 +518,8 @@ namespace Resource { printWithDots("Animation : ", name, "[ LOADED ]"); updateLoadingProgress(); } catch (const std::exception& e) { - throwLoadError("ANIMATION", l, e); + logLoadError("ANIMATION", l, e); + throw; } } @@ -527,7 +533,8 @@ namespace Resource { printWithDots("Room : ", name, "[ LOADED ]"); updateLoadingProgress(); } catch (const std::exception& e) { - throwLoadError("ROOM", l, e); + logLoadError("ROOM", l, e); + throw; } } diff --git a/source/core/resources/resource_cache.hpp b/source/core/resources/resource_cache.hpp index 4a9a212..92f3826 100644 --- a/source/core/resources/resource_cache.hpp +++ b/source/core/resources/resource_cache.hpp @@ -100,7 +100,7 @@ namespace Resource { void setCurrentLoading(const std::string& name); // Desa el nom del recurs en curs // Helper para mensajes de error de carga - [[noreturn]] static void throwLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e); + static void logLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e); // Constructor y destructor Cache(); diff --git a/source/core/resources/resource_list.cpp b/source/core/resources/resource_list.cpp index 8beb464..7cf3cf2 100644 --- a/source/core/resources/resource_list.cpp +++ b/source/core/resources/resource_list.cpp @@ -75,11 +75,11 @@ namespace Resource { } // Buscar la última entrada con el mismo prefijo de ruta e insertar después - std::string entry = " - " + var_path + "\n"; auto last_pos = content.rfind(var_path.substr(0, var_path.rfind('/'))); if (last_pos != std::string::npos) { auto end_of_line = content.find('\n', last_pos); if (end_of_line != std::string::npos) { + std::string entry = " - " + var_path + "\n"; content.insert(end_of_line + 1, entry); } } diff --git a/source/core/resources/resource_pack.cpp b/source/core/resources/resource_pack.cpp index a2983fb..431120c 100644 --- a/source/core/resources/resource_pack.cpp +++ b/source/core/resources/resource_pack.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -14,11 +15,10 @@ namespace Resource { // Calculate CRC32 checksum for data verification auto Pack::calculateChecksum(const std::vector& data) -> uint32_t { // NOLINT(readability-convert-member-functions-to-static) - uint32_t checksum = 0x12345678; - for (unsigned char byte : data) { - checksum = ((checksum << 5) + checksum) + byte; - } - return checksum; + return std::accumulate(data.begin(), data.end(), uint32_t{0x12345678}, + [](uint32_t acc, unsigned char byte) -> uint32_t { + return ((acc << 5) + acc) + byte; + }); } // XOR encryption (symmetric - same function for encrypt/decrypt) diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 0d8eacf..0266ac6 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -45,21 +45,24 @@ #include #endif -// Constructor -Director::Director() { - std::cout << "Game start" << '\n'; - +namespace { + auto getExecutablePath() -> std::string { #ifdef __EMSCRIPTEN__ - // En Emscripten els assets estan al root del filesystem virtual (/data, /config) - executable_path_ = ""; + // En Emscripten els assets estan al root del filesystem virtual (/data, /config) + return ""; #else - // Obtiene la ruta del ejecutable - std::string base = SDL_GetBasePath(); - if (!base.empty() && base.back() == '/') { - base.pop_back(); - } - executable_path_ = base; + std::string base = SDL_GetBasePath(); + if (!base.empty() && base.back() == '/') { + base.pop_back(); + } + return base; #endif + } +} // namespace + +// Constructor +Director::Director() : executable_path_(getExecutablePath()) { + std::cout << "Game start" << '\n'; // Crea la carpeta del sistema donde guardar datos createSystemFolder("jailgames"); diff --git a/source/game/editor/editor_statusbar.cpp b/source/game/editor/editor_statusbar.cpp index 61a9325..e305ffd 100644 --- a/source/game/editor/editor_statusbar.cpp +++ b/source/game/editor/editor_statusbar.cpp @@ -15,13 +15,10 @@ // Constructor EditorStatusBar::EditorStatusBar(std::string room_number, std::string room_name) - : room_number_(std::move(room_number)), + : surface_(std::make_shared(Options::game.width, 6.0F * Tile::SIZE)), + surface_dest_{.x = 0, .y = Options::game.height - (6.0F * Tile::SIZE), .w = Options::game.width, .h = 6.0F * Tile::SIZE}, + room_number_(std::move(room_number)), room_name_(std::move(room_name)) { - const float SURFACE_WIDTH = Options::game.width; - constexpr float SURFACE_HEIGHT = 6.0F * Tile::SIZE; // 48 pixels, igual que el scoreboard - - surface_ = std::make_shared(SURFACE_WIDTH, SURFACE_HEIGHT); - surface_dest_ = {.x = 0, .y = Options::game.height - SURFACE_HEIGHT, .w = SURFACE_WIDTH, .h = SURFACE_HEIGHT}; } // Pinta la barra de estado en pantalla diff --git a/source/game/editor/map_editor.cpp b/source/game/editor/map_editor.cpp index 20d6015..401430f 100644 --- a/source/game/editor/map_editor.cpp +++ b/source/game/editor/map_editor.cpp @@ -876,7 +876,7 @@ void MapEditor::updateStatusBarInfo() { // NOLINT(readability-function-cognitiv const auto& e = room_data_.enemies[selected_enemy_]; std::string anim = e.animation_path; auto dot = anim.rfind('.'); - if (dot != std::string::npos) { anim = anim.substr(0, dot); } + if (dot != std::string::npos) { anim.resize(dot); } line2 = "enemy " + std::to_string(selected_enemy_) + ": " + anim + " " + e.color; line3 = "vx:" + std::to_string(static_cast(e.vx)) + @@ -1278,7 +1278,7 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { // // Comprobar que no hay ya una room en esa dirección if (!direction.empty()) { - std::string* existing = nullptr; + const std::string* existing = nullptr; if (direction == "UP") { existing = &room_data_.upper_room; } else if (direction == "DOWN") { @@ -1294,7 +1294,7 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { // } // Encontrar el primer número libre (reutiliza huecos) - auto& rooms = Resource::Cache::get()->getRooms(); + const auto& rooms = Resource::Cache::get()->getRooms(); std::set used; for (const auto& r : rooms) { try { @@ -1425,11 +1425,11 @@ auto MapEditor::deleteRoom() -> std::string { // NOLINT(readability-function-co if (target == "0") { // Buscar la primera room que no sea esta - for (const auto& r : Resource::Cache::get()->getRooms()) { - if (r.name != deleted_name) { - target = r.name; - break; - } + const auto& rooms = Resource::Cache::get()->getRooms(); + auto it = std::ranges::find_if(rooms, + [&deleted_name](const auto& r) { return r.name != deleted_name; }); + if (it != rooms.end()) { + target = it->name; } } if (target == "0") { return "Cannot delete: no other room to navigate to"; } diff --git a/source/game/editor/mini_map.cpp b/source/game/editor/mini_map.cpp index ea2c2be..adaae4d 100644 --- a/source/game/editor/mini_map.cpp +++ b/source/game/editor/mini_map.cpp @@ -79,7 +79,7 @@ void MiniMap::buildTileColorTable(const std::string& tileset_name) { // Posiciona las rooms en un grid usando BFS desde las conexiones void MiniMap::layoutRooms() { - auto& rooms = Resource::Cache::get()->getRooms(); + const auto& rooms = Resource::Cache::get()->getRooms(); if (rooms.empty()) { return; } // Mapa de nombre → Room::Data diff --git a/source/game/gameplay/cheevos.cpp b/source/game/gameplay/cheevos.cpp index cf36a6a..c82bfc0 100644 --- a/source/game/gameplay/cheevos.cpp +++ b/source/game/gameplay/cheevos.cpp @@ -45,7 +45,7 @@ Cheevos::~Cheevos() { // Inicializa los logros void Cheevos::init() { // NOLINT(readability-convert-member-functions-to-static) cheevos_list_.clear(); - auto* loc = Locale::get(); + const auto* loc = Locale::get(); cheevos_list_.emplace_back(Achievement{.id = 1, .caption = loc->get("achievements.c1"), .description = loc->get("achievements.d1"), .icon = 2}); cheevos_list_.emplace_back(Achievement{.id = 2, .caption = loc->get("achievements.c2"), .description = loc->get("achievements.d2"), .icon = 2}); cheevos_list_.emplace_back(Achievement{.id = 3, .caption = loc->get("achievements.c3"), .description = loc->get("achievements.d3"), .icon = 2}); diff --git a/source/game/gameplay/collision_map.cpp b/source/game/gameplay/collision_map.cpp index bd9dfe8..2789f43 100644 --- a/source/game/gameplay/collision_map.cpp +++ b/source/game/gameplay/collision_map.cpp @@ -108,32 +108,23 @@ auto CollisionMap::getSlopeHeight(SDL_FPoint p, Tile slope) -> int { // Comprueba las colisiones con paredes derechas auto CollisionMap::checkRightSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static) - for (const auto& s : right_walls_) { - if (checkCollision(s, rect)) { - return s.x; - } - } - return Collision::NONE; + auto it = std::ranges::find_if(right_walls_, + [&rect](const auto& s) { return checkCollision(s, rect); }); + return (it != right_walls_.end()) ? it->x : Collision::NONE; } // Comprueba las colisiones con paredes izquierdas auto CollisionMap::checkLeftSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static) - for (const auto& s : left_walls_) { - if (checkCollision(s, rect)) { - return s.x; - } - } - return Collision::NONE; + auto it = std::ranges::find_if(left_walls_, + [&rect](const auto& s) { return checkCollision(s, rect); }); + return (it != left_walls_.end()) ? it->x : Collision::NONE; } // Comprueba las colisiones con techos auto CollisionMap::checkTopSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static) - for (const auto& s : top_floors_) { - if (checkCollision(s, rect)) { - return s.y; - } - } - return Collision::NONE; + auto it = std::ranges::find_if(top_floors_, + [&rect](const auto& s) { return checkCollision(s, rect); }); + return (it != top_floors_.end()) ? it->y : Collision::NONE; } // Comprueba las colisiones punto con techos @@ -145,22 +136,16 @@ auto CollisionMap::checkTopSurfaces(const SDL_FPoint& p) -> bool { // Comprueba las colisiones con suelos auto CollisionMap::checkBottomSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static) - for (const auto& s : bottom_floors_) { - if (checkCollision(s, rect)) { - return s.y; - } - } - return Collision::NONE; + auto it = std::ranges::find_if(bottom_floors_, + [&rect](const auto& s) { return checkCollision(s, rect); }); + return (it != bottom_floors_.end()) ? it->y : Collision::NONE; } // Comprueba las colisiones con conveyor belts auto CollisionMap::checkAutoSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static) - for (const auto& s : conveyor_belt_floors_) { - if (checkCollision(s, rect)) { - return s.y; - } - } - return Collision::NONE; + auto it = std::ranges::find_if(conveyor_belt_floors_, + [&rect](const auto& s) { return checkCollision(s, rect); }); + return (it != conveyor_belt_floors_.end()) ? it->y : Collision::NONE; } // Comprueba las colisiones punto con conveyor belts @@ -208,18 +193,16 @@ auto CollisionMap::checkRightSlopes(const SDL_FPoint& p) -> bool { // Obtiene puntero a slope en un punto (prioriza left_slopes_ sobre right_slopes_) auto CollisionMap::getSlopeAtPoint(const SDL_FPoint& p) const -> const LineDiagonal* { // NOLINT(readability-convert-member-functions-to-static) - // Primero busca en rampas izquierdas - for (const auto& slope : left_slopes_) { - if (checkCollision(p, slope)) { - return &slope; - } + auto pred = [&p](const auto& slope) { return static_cast(checkCollision(p, slope)); }; + + auto left_it = std::ranges::find_if(left_slopes_, pred); + if (left_it != left_slopes_.end()) { + return &(*left_it); } - // Luego busca en rampas derechas - for (const auto& slope : right_slopes_) { - if (checkCollision(p, slope)) { - return &slope; - } + auto right_it = std::ranges::find_if(right_slopes_, pred); + if (right_it != right_slopes_.end()) { + return &(*right_it); } // No hay colisión con ninguna slope diff --git a/source/game/gameplay/room_loader.cpp b/source/game/gameplay/room_loader.cpp index 0410662..8afef58 100644 --- a/source/game/gameplay/room_loader.cpp +++ b/source/game/gameplay/room_loader.cpp @@ -44,9 +44,7 @@ auto RoomLoader::flattenTilemap(const std::vector>& tilemap_2d) tilemap_flat.reserve(512); // 16 rows × 32 cols for (const auto& row : tilemap_2d) { - for (int tile : row) { - tilemap_flat.push_back(tile); - } + std::ranges::copy(row, std::back_inserter(tilemap_flat)); } return tilemap_flat; @@ -135,12 +133,9 @@ void RoomLoader::parseTilemap(const fkyaml::node& yaml, Room::Data& room, const for (const auto& row_node : tilemap_node) { std::vector row; row.reserve(32); - - for (const auto& tile_node : row_node) { - row.push_back(tile_node.get_value()); - } - - tilemap_2d.push_back(row); + std::ranges::transform(row_node, std::back_inserter(row), + [](const auto& tile_node) { return tile_node.template get_value(); }); + tilemap_2d.push_back(std::move(row)); } // Convert to 1D flat array diff --git a/source/game/gameplay/scoreboard.cpp b/source/game/gameplay/scoreboard.cpp index f0c8f61..8f74f47 100644 --- a/source/game/gameplay/scoreboard.cpp +++ b/source/game/gameplay/scoreboard.cpp @@ -36,9 +36,9 @@ Scoreboard::Scoreboard(std::shared_ptr data) // Inicializa el vector de colores const std::vector COLORS = {"blue", "magenta", "green", "cyan", "yellow", "white", "bright_blue", "bright_magenta", "bright_green", "bright_cyan", "bright_yellow", "bright_white"}; - for (const auto& color : COLORS) { - color_.push_back(stringToColor(color)); - } + color_.reserve(COLORS.size()); + std::ranges::transform(COLORS, std::back_inserter(color_), + [](const auto& color) { return stringToColor(color); }); } // Pinta el objeto en pantalla diff --git a/source/game/gameplay/tilemap_renderer.cpp b/source/game/gameplay/tilemap_renderer.cpp index 1b21658..a42534b 100644 --- a/source/game/gameplay/tilemap_renderer.cpp +++ b/source/game/gameplay/tilemap_renderer.cpp @@ -15,9 +15,8 @@ TilemapRenderer::TilemapRenderer(std::vector tile_map, int tile_set_width, tile_set_width_(tile_set_width), tileset_surface_(std::move(tileset_surface)), bg_color_(std::move(bg_color)), - conveyor_belt_direction_(conveyor_belt_direction) { - // Crear la surface del mapa - map_surface_ = std::make_shared(PlayArea::WIDTH, PlayArea::HEIGHT); + conveyor_belt_direction_(conveyor_belt_direction), + map_surface_(std::make_shared(PlayArea::WIDTH, PlayArea::HEIGHT)) { } // Inicializa el renderizador diff --git a/source/game/scenes/credits.cpp b/source/game/scenes/credits.cpp index 0feac46..74f89c2 100644 --- a/source/game/scenes/credits.cpp +++ b/source/game/scenes/credits.cpp @@ -50,7 +50,7 @@ void Credits::handleInput() { // Inicializa los textos void Credits::iniTexts() { // NOLINT(readability-convert-member-functions-to-static) - auto* loc = Locale::get(); + const auto* loc = Locale::get(); texts_.clear(); texts_.push_back({.label = "", .color = static_cast(PaletteColor::WHITE)}); diff --git a/source/game/scenes/ending.cpp b/source/game/scenes/ending.cpp index d09a499..2a85237 100644 --- a/source/game/scenes/ending.cpp +++ b/source/game/scenes/ending.cpp @@ -172,7 +172,7 @@ void Ending::updateState(float delta_time) { void Ending::iniTexts() { // NOLINT(readability-convert-member-functions-to-static) // Vector con los textos (traducidos según el idioma activo) std::vector texts; - auto* loc = Locale::get(); + const auto* loc = Locale::get(); // Escena #0 texts.push_back({.caption = loc->get("ending.t0"), .pos = 32}); diff --git a/source/game/scenes/ending2.cpp b/source/game/scenes/ending2.cpp index 507adb9..6c84815 100644 --- a/source/game/scenes/ending2.cpp +++ b/source/game/scenes/ending2.cpp @@ -31,9 +31,9 @@ Ending2::Ending2() // Inicializa el vector de colores const std::vector COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"}; - for (const auto& color : COLORS) { - colors_.push_back(stringToColor(color)); - } + colors_.reserve(COLORS.size()); + std::ranges::transform(COLORS, std::back_inserter(colors_), + [](const auto& color) { return stringToColor(color); }); Screen::get()->setBorderColor(static_cast(PaletteColor::BLACK)); // Cambia el color del borde iniSpriteList(); // Inicializa la lista de sprites diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 0fc72d9..b53d68d 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -3,6 +3,7 @@ #include #include // Para std::sqrt, std::min +#include // Para std::accumulate #include #include // Para vector @@ -865,14 +866,9 @@ auto Game::checkEndGame() -> bool { // Obtiene la cantidad total de items que hay en el mapeado del juego auto Game::getTotalItems() -> int { - int items = 0; - auto rooms = Resource::Cache::get()->getRooms(); - - for (const auto& room : rooms) { - items += room.room->items.size(); - } - - return items; + const auto& rooms = Resource::Cache::get()->getRooms(); + return static_cast(std::accumulate(rooms.begin(), rooms.end(), size_t{0}, + [](size_t acc, const auto& room) { return acc + room.room->items.size(); })); } // Pone el juego en pausa diff --git a/source/game/scenes/game_over.cpp b/source/game/scenes/game_over.cpp index 6b74d96..5fa8075 100644 --- a/source/game/scenes/game_over.cpp +++ b/source/game/scenes/game_over.cpp @@ -38,9 +38,9 @@ GameOver::GameOver() // Inicializa el vector de colores (de brillante a oscuro para fade) const std::vector COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"}; - for (const auto& color : COLORS) { - colors_.push_back(stringToColor(color)); - } + colors_.reserve(COLORS.size()); + std::ranges::transform(COLORS, std::back_inserter(colors_), + [](const auto& color) { return stringToColor(color); }); color_ = colors_.back(); // Empieza en black } @@ -68,7 +68,7 @@ void GameOver::render() { auto text = Resource::Cache::get()->getText("smb2"); // Escribe el texto de GAME OVER - auto* loc = Locale::get(); + const auto* loc = Locale::get(); text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GameCanvas::CENTER_X, TEXT_Y, loc->get("game_over.title"), 1, color_); // NOLINT(readability-static-accessed-through-instance) // Dibuja los sprites (ya posicionados en el constructor, solo ajustamos Y) diff --git a/source/game/scenes/logo.cpp b/source/game/scenes/logo.cpp index e8cc14b..39dd017 100644 --- a/source/game/scenes/logo.cpp +++ b/source/game/scenes/logo.cpp @@ -259,9 +259,8 @@ void Logo::initColors() { // NOLINT(readability-convert-member-functions-to-sta static_cast(PaletteColor::CYAN), static_cast(PaletteColor::YELLOW), static_cast(PaletteColor::BRIGHT_WHITE)}; - for (const auto& color : COLORS) { - color_.push_back(color); - } + color_.reserve(COLORS.size()); + std::ranges::copy(COLORS, std::back_inserter(color_)); } // Crea los sprites de cada linea diff --git a/source/game/scenes/title.cpp b/source/game/scenes/title.cpp index cb38d8f..7910bac 100644 --- a/source/game/scenes/title.cpp +++ b/source/game/scenes/title.cpp @@ -544,7 +544,7 @@ void Title::renderMainMenu() { const int TOTAL_HEIGHT = 3 * SPACING; // 3 espacios entre 4 items const int START_Y = MENU_CENTER_Y - (TOTAL_HEIGHT / 2); - auto* loc = Locale::get(); + const auto* loc = Locale::get(); menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.menu.play"), 1, COLOR); menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + SPACING, loc->get("title.menu.keyboard"), 1, COLOR); menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y + (2 * SPACING), loc->get("title.menu.joystick"), 1, COLOR); @@ -652,19 +652,6 @@ auto Title::isKeyDuplicate(SDL_Scancode scancode, int current_step) -> bool { / } // Retorna el nombre de la accion para el paso actual -auto Title::getActionName(int step) -> std::string { // NOLINT(readability-convert-member-functions-to-static) - switch (step) { - case 0: - return "LEFT"; - case 1: - return "RIGHT"; - case 2: - return "JUMP"; - default: - return "UNKNOWN"; - } -} - // Aplica y guarda las teclas redefinidas void Title::applyKeyboardRemap() { // NOLINT(readability-convert-member-functions-to-static) // Guardar las nuevas teclas en Options::controls @@ -696,7 +683,7 @@ void Title::renderKeyboardRemap() const { const int START_Y = MENU_CENTER_Y - (2 * TEXT_SIZE); // Centrado aproximado // Mensaje principal: "PRESS KEY FOR [ACTION]" o "KEYS DEFINED" si completado - auto* loc = Locale::get(); + const auto* loc = Locale::get(); if (remap_step_ >= 3) { menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.keys.defined"), 1, COLOR); } else { @@ -744,7 +731,7 @@ void Title::renderJoystickRemap() const { const int START_Y = MENU_CENTER_Y - (2 * TEXT_SIZE); // Centrado aproximado // Mensaje principal: "PRESS BUTTON FOR [ACTION]" o "BUTTONS DEFINED" si completado - auto* loc = Locale::get(); + const auto* loc = Locale::get(); if (remap_step_ >= 3) { menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PlayArea::CENTER_X, START_Y, loc->get("title.buttons.defined"), 1, COLOR); } else { diff --git a/source/game/scenes/title.hpp b/source/game/scenes/title.hpp index 5fc1211..23ecde5 100644 --- a/source/game/scenes/title.hpp +++ b/source/game/scenes/title.hpp @@ -88,7 +88,6 @@ class Title : public Scene { auto isButtonDuplicate(int button, int current_step) -> bool; // Valida si un boton esta duplicado void applyKeyboardRemap(); // Aplica y guarda las teclas redefinidas void applyJoystickRemap(); // Aplica y guarda los botones del gamepad redefinidos - static auto getActionName(int step) -> std::string; // Retorna el nombre de la accion (LEFT/RIGHT/JUMP) static auto getButtonName(int button) -> std::string; // Retorna el nombre amigable del boton del gamepad void createCheevosTexture(); // Crea y rellena la surface para mostrar los logros void resetCheevosScroll(); // Resetea el scroll de la lista de logros diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index c264a30..221256e 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -3,6 +3,7 @@ #include #include // Para ranges::transform +#include // Para std::accumulate #include // Para toupper #include // Para std::istringstream #include // Para string @@ -181,8 +182,8 @@ void Console::update(float delta_time) { // NOLINT(readability-function-cogniti // Efecto typewriter: revelar letras una a una (solo cuando ACTIVE) if (status_ == Status::ACTIVE) { - int total_chars = 0; - for (const auto& line : msg_lines_) { total_chars += static_cast(line.size()); } + const int total_chars = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, + [](int acc, const auto& line) { return acc + static_cast(line.size()); }); if (typewriter_chars_ < total_chars) { typewriter_timer_ += delta_time; while (typewriter_timer_ >= TYPEWRITER_CHAR_DELAY && typewriter_chars_ < total_chars) { @@ -337,11 +338,9 @@ void Console::handleEvent(const SDL_Event& event) { // NOLINT(readability-funct const size_t SPACE_POS = upper.rfind(' '); if (SPACE_POS == std::string::npos) { // Modo comando: ciclar keywords visibles que empiecen por el prefijo - for (const auto& kw : registry_.getVisibleKeywords()) { - if (upper.empty() || kw.starts_with(upper)) { - tab_matches_.emplace_back(kw); - } - } + const auto KEYWORDS = registry_.getVisibleKeywords(); + std::ranges::copy_if(KEYWORDS, std::back_inserter(tab_matches_), + [&upper](const auto& kw) { return upper.empty() || kw.starts_with(upper); }); } else { const std::string BASE_CMD = upper.substr(0, SPACE_POS); const std::string SUB_PREFIX = upper.substr(SPACE_POS + 1); @@ -357,7 +356,8 @@ void Console::handleEvent(const SDL_Event& event) { // NOLINT(readability-funct if (tab_matches_.empty()) { break; } tab_index_ = (tab_index_ + 1) % static_cast(tab_matches_.size()); std::string result = tab_matches_[static_cast(tab_index_)]; - for (char& c : result) { c = static_cast(std::tolower(static_cast(c))); } + std::ranges::transform(result, result.begin(), + [](char c) { return static_cast(std::tolower(static_cast(c))); }); input_line_ = result; break; } @@ -403,9 +403,8 @@ void Console::processCommand() { // Typewriter: instantáneo si el comando lo requiere, letra a letra si no if (instant) { - int total = 0; - for (const auto& l : msg_lines_) { total += static_cast(l.size()); } - typewriter_chars_ = total; + typewriter_chars_ = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, + [](int acc, const auto& l) { return acc + static_cast(l.size()); }); } else { typewriter_chars_ = 0; } diff --git a/source/game/ui/console_commands.cpp b/source/game/ui/console_commands.cpp index 9e56794..4117314 100644 --- a/source/game/ui/console_commands.cpp +++ b/source/game/ui/console_commands.cpp @@ -32,7 +32,7 @@ // Toggle genérico para comandos booleanos ON/OFF (reemplaza macro BOOL_TOGGLE_CMD) static auto boolToggle( const std::string& label, - bool& option, + const bool& option, const std::function& toggle_fn, const std::vector& args) -> std::string { if (args.empty()) { @@ -836,13 +836,12 @@ static auto cmdCheat(const std::vector& args) -> std::string { // if (args.size() < 2 || args[1] != "LIVES") { return "usage: cheat infinite lives [on|off]"; } auto& cheat = Options::cheats.infinite_lives; using State = Options::Cheat::State; - const std::vector REST(args.begin() + 2, args.end()); - if (REST.empty()) { + if (args.size() == 2) { cheat = (cheat == State::ENABLED) ? State::DISABLED : State::ENABLED; - } else if (REST[0] == "ON") { + } else if (args[2] == "ON") { if (cheat == State::ENABLED) { return "Infinite lives already ON"; } cheat = State::ENABLED; - } else if (REST[0] == "OFF") { + } else if (args[2] == "OFF") { if (cheat == State::DISABLED) { return "Infinite lives already OFF"; } cheat = State::DISABLED; } else { @@ -1013,9 +1012,9 @@ void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cogni dynamic_providers_["PALETTE"] = []() -> std::vector { std::vector result = {"NEXT", "PREV", "SORT", "DEFAULT"}; if (Screen::get() != nullptr) { - for (const auto& name : Screen::get()->getPaletteNames()) { - result.push_back(toUpper(name)); - } + const auto NAMES = Screen::get()->getPaletteNames(); + std::ranges::transform(NAMES, std::back_inserter(result), + [](const auto& name) { return toUpper(name); }); } return result; }; @@ -1024,10 +1023,11 @@ void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cogni dynamic_providers_["SHADER PRESET"] = []() -> std::vector { std::vector result = {"NEXT", "PREV"}; const bool IS_CRTPI = Options::video.shader.current_shader == Rendering::ShaderType::CRTPI; + auto upper_name = [](const auto& p) { return toUpper(p.name); }; if (IS_CRTPI) { - for (const auto& p : Options::crtpi_presets) { result.push_back(toUpper(p.name)); } + std::ranges::transform(Options::crtpi_presets, std::back_inserter(result), upper_name); } else { - for (const auto& p : Options::postfx_presets) { result.push_back(toUpper(p.name)); } + std::ranges::transform(Options::postfx_presets, std::back_inserter(result), upper_name); } return result; }; @@ -1068,7 +1068,7 @@ void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cogni if (path.find("enemies") == std::string::npos) { continue; } std::string name = getFileName(path); auto dot = name.rfind('.'); - if (dot != std::string::npos) { name = name.substr(0, dot); } + if (dot != std::string::npos) { name.resize(dot); } result.push_back(toUpper(name)); } return result; @@ -1082,7 +1082,7 @@ void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cogni if (path.find("tilesets") == std::string::npos) { continue; } std::string name = getFileName(path); auto dot = name.rfind('.'); - if (dot != std::string::npos) { name = name.substr(0, dot); } + if (dot != std::string::npos) { name.resize(dot); } result.push_back(toUpper(name)); } return result; @@ -1120,7 +1120,8 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit if (cat_node.contains("scope")) { const auto& scope_node = cat_node["scope"]; if (scope_node.is_sequence()) { - for (const auto& s : scope_node) { cat_scopes.push_back(s.get_value()); } + std::ranges::transform(scope_node, std::back_inserter(cat_scopes), + [](const auto& s) { return s.template get_value(); }); } else { cat_scopes.push_back(scope_node.get_value()); } @@ -1161,9 +1162,8 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit for (auto it = completions_node.begin(); it != completions_node.end(); ++it) { auto path = it.key().get_value(); std::vector opts; - for (const auto& opt : *it) { - opts.push_back(opt.get_value()); - } + std::ranges::transform(*it, std::back_inserter(opts), + [](const auto& opt) { return opt.template get_value(); }); def.completions[path] = std::move(opts); } } @@ -1182,9 +1182,8 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit for (auto it = extras_completions.begin(); it != extras_completions.end(); ++it) { auto path = it.key().get_value(); std::vector opts; - for (const auto& opt : *it) { - opts.push_back(opt.get_value()); - } + std::ranges::transform(*it, std::back_inserter(opts), + [](const auto& opt) { return opt.template get_value(); }); def.completions[path] = std::move(opts); } } @@ -1237,10 +1236,9 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit } auto CommandRegistry::findCommand(const std::string& keyword) const -> const CommandDef* { - for (const auto& cmd : commands_) { - if (cmd.keyword == keyword) { return &cmd; } - } - return nullptr; + auto it = std::ranges::find_if(commands_, + [&keyword](const auto& cmd) { return cmd.keyword == keyword; }); + return (it != commands_.end()) ? &(*it) : nullptr; } auto CommandRegistry::execute(const std::string& keyword, const std::vector& args) const -> std::string { @@ -1331,7 +1329,7 @@ auto CommandRegistry::getCompletions(const std::string& path) const -> std::vect if (!active_scope_.empty()) { std::string root = path; auto space = root.find(' '); - if (space != std::string::npos) { root = root.substr(0, space); } + if (space != std::string::npos) { root.resize(space); } const auto* cmd = findCommand(root); if (cmd != nullptr && !isCommandVisible(*cmd)) { return {}; } } diff --git a/source/game/ui/notifier.cpp b/source/game/ui/notifier.cpp index a58af8c..acc2fc6 100644 --- a/source/game/ui/notifier.cpp +++ b/source/game/ui/notifier.cpp @@ -306,8 +306,7 @@ auto Notifier::getVisibleHeight() const -> int { auto Notifier::getCodes() -> std::vector { std::vector codes; codes.reserve(notifications_.size()); - for (const auto& notification : notifications_) { - codes.emplace_back(notification.code); - } + std::ranges::transform(notifications_, std::back_inserter(codes), + [](const auto& notification) { return notification.code; }); return codes; } \ No newline at end of file