// collision.hpp - Utilitats de detecció de colisiones // © 2026 JailDesigner #pragma once #include #include "core/entities/entity.hpp" #include "core/types.hpp" namespace Physics { // Comprobación genèrica de colisión entre dues entidades inline auto checkCollision(const Entities::Entity& a, const Entities::Entity& b, float amplifier = 1.0F) -> bool { // Comprovar si ambdós són col·lisionables if (!a.isCollidable() || !b.isCollidable()) { return false; } // Calcular radi combinat (con amplificador per hitbox generós) float suma_radis = (a.getCollisionRadius() + b.getCollisionRadius()) * amplifier; float suma_radis_sq = suma_radis * suma_radis; // Comprobación distancia al cuadrado (sin sqrt) const Vec2& pos_a = a.getCenter(); const Vec2& pos_b = b.getCenter(); float dx = pos_a.x - pos_b.x; float dy = pos_a.y - pos_b.y; float dist_sq = (dx * dx) + (dy * dy); return dist_sq <= suma_radis_sq; } // Swept collision: una entitat mòbil (radi r_a) s'ha desplaçat de p0 a p1 aquest // frame. Comprova si el segment expandit pel radi conjunt (r_a + radi de b, amb // amplificador) toca el cercle de l'entity b. Equival al check discrete quan // p0 == p1 (sense moviment). Evita tunneling a velocitats altes. inline auto checkCollisionSwept(const Vec2& p0, const Vec2& p1, float r_a, const Entities::Entity& b, float amplifier = 1.0F) -> bool { if (!b.isCollidable()) { return false; } const float SUM_R = (r_a + b.getCollisionRadius()) * amplifier; const float SUM_R_SQ = SUM_R * SUM_R; const Vec2& center_b = b.getCenter(); const float DX_SEG = p1.x - p0.x; const float DY_SEG = p1.y - p0.y; const float LEN_SQ = (DX_SEG * DX_SEG) + (DY_SEG * DY_SEG); // Degenerat: punt-cercle (frame de spawn, o entitat parada). if (LEN_SQ <= 0.0F) { const float DX = p0.x - center_b.x; const float DY = p0.y - center_b.y; return ((DX * DX) + (DY * DY)) <= SUM_R_SQ; } // Projecció del centre sobre la recta del segment, clamp a [0,1] per acotar al segment. const float T_RAW = (((center_b.x - p0.x) * DX_SEG) + ((center_b.y - p0.y) * DY_SEG)) / LEN_SQ; const float T_CLAMPED = std::clamp(T_RAW, 0.0F, 1.0F); const float CLOSEST_X = p0.x + (DX_SEG * T_CLAMPED); const float CLOSEST_Y = p0.y + (DY_SEG * T_CLAMPED); const float DX = CLOSEST_X - center_b.x; const float DY = CLOSEST_Y - center_b.y; return ((DX * DX) + (DY * DY)) <= SUM_R_SQ; } } // namespace Physics