#include "core/rendering/overlay.hpp" #include #include #include #include #include "core/rendering/text.hpp" namespace Overlay { static std::unique_ptr font_; // --- Notificacions amb animació --- enum class Status { RISING, STAY, VANISHING, FINISHED }; struct Notification { std::string message; Status status{Status::RISING}; float y_offset{0.0F}; // 0 = fora de pantalla, 1 = posició final float timer{0.0F}; float duration{2.0F}; }; static std::vector notifications_; static Uint32 last_ticks_ = 0; static constexpr float SLIDE_SPEED = 4.0F; // velocitat d'animació (unitats/segon) static constexpr int BAR_HEIGHT = 12; // alçada de la barra static constexpr int TEXT_Y_OFFSET = 2; // offset del text dins la barra static constexpr Uint32 BG_COLOR = 0xFF1A1A2E; // fons blau fosc static constexpr Uint32 TEXT_COLOR = 0xFF00FFFF; // cyan static constexpr int SCREEN_W = 320; static constexpr int SCREEN_H = 200; void init() { font_ = std::make_unique("fonts/8bithud.fnt", "fonts/8bithud.gif"); last_ticks_ = SDL_GetTicks(); } void destroy() { font_.reset(); notifications_.clear(); } static void drawBar(Uint32* pixel_data, int y, int h, Uint32 color) { for (int row = y; row < y + h; row++) { if (row < 0 || row >= SCREEN_H) continue; for (int col = 0; col < SCREEN_W; col++) { pixel_data[col + row * SCREEN_W] = color; } } } void render(Uint32* pixel_data) { if (!font_ || !pixel_data) return; // Calcula delta time Uint32 now = SDL_GetTicks(); float dt = static_cast(now - last_ticks_) / 1000.0F; last_ticks_ = now; // Actualitza i pinta cada notificació for (auto& notif : notifications_) { switch (notif.status) { case Status::RISING: notif.y_offset += SLIDE_SPEED * dt; if (notif.y_offset >= 1.0F) { notif.y_offset = 1.0F; notif.status = Status::STAY; notif.timer = 0.0F; } break; case Status::STAY: notif.timer += dt; if (notif.timer >= notif.duration) { notif.status = Status::VANISHING; } break; case Status::VANISHING: notif.y_offset -= SLIDE_SPEED * dt; if (notif.y_offset <= 0.0F) { notif.status = Status::FINISHED; } break; case Status::FINISHED: break; } if (notif.status == Status::FINISHED) continue; // Posició: puja des de sota la pantalla int bar_y = SCREEN_H - static_cast(notif.y_offset * BAR_HEIGHT); // Pinta fons drawBar(pixel_data, bar_y, BAR_HEIGHT, BG_COLOR); // Pinta text centrat font_->drawCentered(pixel_data, bar_y + TEXT_Y_OFFSET, notif.message.c_str(), TEXT_COLOR); } // Elimina les acabades notifications_.erase( std::remove_if(notifications_.begin(), notifications_.end(), [](const Notification& n) { return n.status == Status::FINISHED; }), notifications_.end()); } void showNotification(const char* text, float duration_seconds) { // Si ja hi ha una notificació, la reemplaça (no apilem) notifications_.clear(); notifications_.push_back({text, Status::RISING, 0.0F, 0.0F, duration_seconds}); } } // namespace Overlay