From 254ef3d11c5d9c4d972b0acb2b9f634578c03f66 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Wed, 26 Nov 2025 12:26:19 +0100 Subject: [PATCH] arreglos en updateColliderPoints() --- source/game/entities/player.cpp | 49 +++++++++++++++++++++++++++------ source/game/entities/player.hpp | 11 ++++---- source/game/scenes/game.cpp | 1 + 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index 6735a90..ebb51b7 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -339,16 +339,49 @@ void Player::setColor(Uint8 color) { } // Actualiza los puntos de colisión +// Sistema dinámico que adapta el número de puntos al tamaño del sprite +// Para sprites más grandes que los tiles (8px), genera puntos adicionales +// evitando que se atraviesen tiles al haber huecos entre colliders void Player::updateColliderPoints() { const SDL_FRect RECT = getRect(); - collider_points_[0] = {.x = RECT.x, .y = RECT.y}; - collider_points_[1] = {.x = RECT.x + 7, .y = RECT.y}; - collider_points_[2] = {.x = RECT.x + 7, .y = RECT.y + 7}; - collider_points_[3] = {.x = RECT.x, .y = RECT.y + 7}; - collider_points_[4] = {.x = RECT.x, .y = RECT.y + 8}; - collider_points_[5] = {.x = RECT.x + 7, .y = RECT.y + 8}; - collider_points_[6] = {.x = RECT.x + 7, .y = RECT.y + 15}; - collider_points_[7] = {.x = RECT.x, .y = RECT.y + 15}; + + // Calcular cuántos puntos necesitamos por cada dimensión + // Regla: un punto cada ~7px (menos que Tile::SIZE=8px) para garantizar detección + // Como mínimo 2 puntos por borde (esquinas) + constexpr int MAX_SPACING = 7; // Máxima distancia entre puntos (menor que tile size de 8px) + + const int points_per_width = std::max(2, (WIDTH / MAX_SPACING) + 1); + const int points_per_height = std::max(2, (HEIGHT / MAX_SPACING) + 1); + + // Limpiar y reservar espacio para los nuevos puntos + collider_points_.clear(); + collider_points_.reserve(2 * points_per_width + 2 * points_per_height - 4); // Perímetro sin duplicar esquinas + + // Generar puntos distribuidos uniformemente por el perímetro del rectángulo + + // Borde superior (izquierda a derecha) + for (int i = 0; i < points_per_width; ++i) { + const float offset = (WIDTH - 1) * static_cast(i) / static_cast(points_per_width - 1); + collider_points_.push_back({.x = RECT.x + offset, .y = RECT.y}); + } + + // Borde derecho (arriba a abajo, sin repetir esquina superior derecha) + for (int i = 1; i < points_per_height; ++i) { + const float offset = (HEIGHT - 1) * static_cast(i) / static_cast(points_per_height - 1); + collider_points_.push_back({.x = RECT.x + WIDTH - 1, .y = RECT.y + offset}); + } + + // Borde inferior (derecha a izquierda, sin repetir esquina inferior derecha) + for (int i = 1; i < points_per_width; ++i) { + const float offset = (WIDTH - 1) * static_cast(points_per_width - 1 - i) / static_cast(points_per_width - 1); + collider_points_.push_back({.x = RECT.x + offset, .y = RECT.y + HEIGHT - 1}); + } + + // Borde izquierdo (abajo a arriba, sin repetir esquinas) + for (int i = 1; i < points_per_height - 1; ++i) { + const float offset = (HEIGHT - 1) * static_cast(points_per_height - 1 - i) / static_cast(points_per_height - 1); + collider_points_.push_back({.x = RECT.x, .y = RECT.y + offset}); + } } // Actualiza los puntos de los pies diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index f7c7e27..c5239e1 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -7,6 +7,7 @@ #include // Para shared_ptr, __shared_ptr_access #include // Para string #include +#include // Para vector #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "game/gameplay/room.hpp" @@ -64,6 +65,7 @@ class Player { //[[nodiscard]] auto isAlive() const -> bool { return is_alive_ || (Options::cheats.invincible == Options::Cheat::State::ENABLED); } // Comprueba si el jugador esta vivo [[nodiscard]] auto isAlive() const -> bool { return is_alive_; } // Comprueba si el jugador esta vivo void setPaused(bool value) { is_paused_ = value; } // Pone el jugador en modo pausa + auto handleKillingTiles() -> bool; // Comprueba que el jugador no toque ningun tile de los que matan #ifdef _DEBUG // --- Funciones de debug --- @@ -107,10 +109,10 @@ class Player { State previous_state_ = State::ON_GROUND; // Estado previo en el que se encontraba el jugador // --- Variables de colisión --- - SDL_FRect collider_box_{}; // Caja de colisión con los enemigos u objetos - std::array collider_points_{}; // Puntos de colisión con el mapa - SDL_FPoint under_left_foot_ = {0.0F, 0.0F}; // El punto bajo la esquina inferior izquierda del jugador - SDL_FPoint under_right_foot_ = {0.0F, 0.0F}; // El punto bajo la esquina inferior derecha del jugador + SDL_FRect collider_box_{}; // Caja de colisión con los enemigos u objetos + std::vector collider_points_{}; // Puntos de colisión con el mapa (dinámico, se adapta al tamaño del sprite) + SDL_FPoint under_left_foot_ = {0.0F, 0.0F}; // El punto bajo la esquina inferior izquierda del jugador + SDL_FPoint under_right_foot_ = {0.0F, 0.0F}; // El punto bajo la esquina inferior derecha del jugador // --- Variables de juego --- bool is_alive_ = true; // Indica si el jugador esta vivo o no @@ -167,7 +169,6 @@ class Player { // --- Funciones de finalización --- void animate(float delta_time); // Establece la animación del jugador auto handleBorders() -> Room::Border; // Comprueba si se halla en alguno de los cuatro bordes - auto handleKillingTiles() -> bool; // Comprueba que el jugador no toque ningun tile de los que matan void updateVelocity(float delta_time); // Calcula la velocidad en x con aceleración void markAsDead(); // Marca al jugador como muerto }; \ No newline at end of file diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 61de0d3..fdaac1f 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -175,6 +175,7 @@ void Game::updatePlaying(float delta_time) { handlePlayerIsOnBorder(); handlePlayerAndItemsCollisions(); handlePlayerAndEnemiesCollisions(); + player_->handleKillingTiles(); handleIfPlayerIsAlive(); break;