#include "core/rendering/effects/shadow.hpp" #include #include #include "core/resources/resource_cache.hpp" namespace Effects::Shadow { void render(int center_x, int feet_y, float height_factor) { // Lookup únic al primer ús: la Surface viu a Cache durant tota la // sessió, així evitem la cerca lineal a cada frame. static const auto SURFACE = Resource::Cache::get().getSurface(CACHE_KEY); const int FRAME_COUNT = SURFACE->getWidth() / FRAME_SIZE; if (FRAME_COUNT <= 0) { return; } // Mapping a bandes uniformes: factor 0 → últim (gran), factor 1 → // primer (petit). Per a 3 fotogrames: [0, 1/3) → 2, [1/3, 2/3) → 1, // [2/3, 1] → 0. Generalitza a qualsevol nombre de fotogrames per // si afegim mides intermèdies. const float CLAMPED = std::clamp(height_factor, 0.0F, 1.0F); int frame_index = static_cast((1.0F - CLAMPED) * static_cast(FRAME_COUNT)); frame_index = std::clamp(frame_index, 0, FRAME_COUNT - 1); SDL_FRect clip{ static_cast(frame_index * FRAME_SIZE), 0.0F, static_cast(FRAME_SIZE), static_cast(FRAME_SIZE), }; // Ancoratge: vora inferior del fotograma a `feet_y` — així el // quadrat 16x16 del sprite encaixa exactament al 16x16 inferior // d'una entitat 16x16/16x32 centrada en `center_x`. const int X = center_x - (FRAME_SIZE / 2); const int Y = feet_y - FRAME_SIZE; SURFACE->render(X, Y, &clip); } } // namespace Effects::Shadow