Files
aee/source/core/rendering/overlay.cpp

120 lines
3.8 KiB
C++

#include "core/rendering/overlay.hpp"
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include "core/rendering/text.hpp"
namespace Overlay {
static std::unique_ptr<Text> 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<Notification> 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<Text>("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<float>(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<int>(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