diff --git a/source/game/gameplay/tile_collider.cpp b/source/game/gameplay/tile_collider.cpp index fcfbe2e..ba6b50b 100644 --- a/source/game/gameplay/tile_collider.cpp +++ b/source/game/gameplay/tile_collider.cpp @@ -98,46 +98,41 @@ auto TileCollider::checkCeiling(float x, float y, float w) const -> float { // WALL: bloquea si los pies estaban por encima (como PASSABLE). // PASSABLE: solo si los pies estaban por encima del borde superior del tile. // SLOPE: siempre bloquea (las slopes son sólidas, como muros en diagonal). -// NOLINTNEXTLINE(readability-function-cognitive-complexity) + +// Calcula la y del suelo per a un tile concret. Retorna Collision::NONE si el tile +// no actua com a suelo en aquest cas (segons el tipus i el rang del moviment). +auto TileCollider::floorYForTile(Tile tile, int col, int row, float x, float w, float foot_y_current, float foot_y_new) const -> float { + if (tile == Tile::WALL || tile == Tile::PASSABLE) { + const float TILE_TOP = toPixel(row); + // WALL/PASSABLE només compten si els peus estaven per damunt abans del moviment + return (foot_y_current <= TILE_TOP) ? TILE_TOP : Collision::NONE; + } + if (tile == Tile::SLOPE_L || tile == Tile::SLOPE_R) { + const float CHECK_X = (tile == Tile::SLOPE_L) ? x : x + w - 1; + const float SLOPE_Y = getSlopeY(col, row, CHECK_X); + // Slopes són sòlides: aterrar sempre que els peus arriben a la superfície + return (foot_y_new >= SLOPE_Y) ? SLOPE_Y : Collision::NONE; + } + return Collision::NONE; +} + auto TileCollider::checkFloor(float x, float foot_y_current, float w, float foot_y_new) const -> FloorHit { - int start_row = toTile(static_cast(foot_y_current)); - int end_row = toTile(static_cast(foot_y_new)); - int left_col = toTile(static_cast(x)); - int right_col = toTile(static_cast(x + w - 1)); + const int START_ROW = toTile(static_cast(foot_y_current)); + const int END_ROW = toTile(static_cast(foot_y_new)); + const int LEFT_COL = toTile(static_cast(x)); + const int RIGHT_COL = toTile(static_cast(x + w - 1)); FloorHit best; - - for (int row = start_row; row <= end_row; ++row) { - for (int col = left_col; col <= right_col; ++col) { - auto tile = getTileAt(col, row); - float floor_y = Collision::NONE; - - if (tile == Tile::WALL) { - float tile_top = toPixel(row); - if (foot_y_current <= tile_top) { - floor_y = tile_top; - } - } else if (tile == Tile::PASSABLE) { - float tile_top = toPixel(row); - // Solo cuenta como suelo si los pies estaban por encima antes del movimiento - if (foot_y_current <= tile_top) { - floor_y = tile_top; - } - } else if (tile == Tile::SLOPE_L || tile == Tile::SLOPE_R) { - float check_x = (tile == Tile::SLOPE_L) ? x : x + w - 1; - float slope_y = getSlopeY(col, row, check_x); - // Slopes son sólidas: aterrizar siempre que los pies lleguen a la superficie - if (foot_y_new >= slope_y) { - floor_y = slope_y; - } - } - - if (floor_y != Collision::NONE && (best.y == Collision::NONE || floor_y < best.y)) { - best = {.y = floor_y, .type = tile, .tile_x = col, .tile_y = row}; + for (int row = START_ROW; row <= END_ROW; ++row) { + for (int col = LEFT_COL; col <= RIGHT_COL; ++col) { + const auto TILE = getTileAt(col, row); + const float FLOOR_Y = floorYForTile(TILE, col, row, x, w, foot_y_current, foot_y_new); + if (FLOOR_Y == Collision::NONE) { continue; } + if (best.y == Collision::NONE || FLOOR_Y < best.y) { + best = {.y = FLOOR_Y, .type = TILE, .tile_x = col, .tile_y = row}; } } } - return best; } @@ -196,7 +191,7 @@ auto TileCollider::isInsideAnySlope(float x, float foot_y, float w) const -> boo // Busca una slope directamente debajo del jugador (para transición ground→slope). // Escanea la fila de los pies Y la fila superior: las slopes en escalera siempre // tienen el tile de entrada una fila arriba del suelo desde el que se accede. -// NOLINTNEXTLINE(readability-function-cognitive-complexity) + auto TileCollider::checkSlopeBelow(float x, float foot_y, float w) const -> SlopeInfo { int foot_row = toTile(static_cast(foot_y)); int left_col = toTile(static_cast(x)); diff --git a/source/game/gameplay/tile_collider.hpp b/source/game/gameplay/tile_collider.hpp index 454956f..25ccced 100644 --- a/source/game/gameplay/tile_collider.hpp +++ b/source/game/gameplay/tile_collider.hpp @@ -70,4 +70,7 @@ class TileCollider { int border_px_; // Offset en píxeles (CollisionBorder::PX) const std::vector& tile_map_; + + // Calcula la y del suelo per a un tile concret (helper de checkFloor) + [[nodiscard]] auto floorYForTile(Tile tile, int col, int row, float x, float w, float foot_y_current, float foot_y_new) const -> float; };