afegits estils per a les notificacions (per a distinguir les de sistema de les dels logros)

This commit is contained in:
2025-11-16 20:19:30 +01:00
parent e4c10b6b75
commit 24a71395da
5 changed files with 77 additions and 45 deletions

View File

@@ -35,7 +35,7 @@ void handleQuit() {
} }
} else { } else {
// Si la notificación de salir no está activa, muestra la notificación // Si la notificación de salir no está activa, muestra la notificación
Notifier::get()->show({CODE}, Notifier::TextAlign::CENTER, 2000, -1, true, CODE); Notifier::get()->show({CODE}, Notifier::Style::DEFAULT, -1, true, CODE);
} }
} }
@@ -59,50 +59,50 @@ void handleSkipSection() {
void handleToggleBorder() { void handleToggleBorder() {
Screen::get()->toggleBorder(); Screen::get()->toggleBorder();
Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")}, Notifier::TextAlign::CENTER); Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")});
} }
void handleToggleVideoMode() { void handleToggleVideoMode() {
Screen::get()->toggleVideoMode(); Screen::get()->toggleVideoMode();
Notifier::get()->show({"FULLSCREEN " + std::string(static_cast<int>(Options::video.fullscreen) == 0 ? "DISABLED" : "ENABLED")}, Notifier::TextAlign::CENTER); Notifier::get()->show({"FULLSCREEN " + std::string(static_cast<int>(Options::video.fullscreen) == 0 ? "DISABLED" : "ENABLED")});
} }
void handleDecWindowZoom() { void handleDecWindowZoom() {
if (Screen::get()->decWindowZoom()) { if (Screen::get()->decWindowZoom()) {
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}, Notifier::TextAlign::CENTER); Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
} }
} }
void handleIncWindowZoom() { void handleIncWindowZoom() {
if (Screen::get()->incWindowZoom()) { if (Screen::get()->incWindowZoom()) {
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}, Notifier::TextAlign::CENTER); Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
} }
} }
void handleToggleShaders() { void handleToggleShaders() {
Screen::get()->toggleShaders(); Screen::get()->toggleShaders();
Notifier::get()->show({"SHADERS " + std::string(Options::video.shaders ? "ENABLED" : "DISABLED")}, Notifier::TextAlign::CENTER); Notifier::get()->show({"SHADERS " + std::string(Options::video.shaders ? "ENABLED" : "DISABLED")});
} }
void handleNextPalette() { void handleNextPalette() {
Screen::get()->nextPalette(); Screen::get()->nextPalette();
Notifier::get()->show({"PALETTE " + Options::video.palette}, Notifier::TextAlign::CENTER); Notifier::get()->show({"PALETTE " + Options::video.palette});
} }
void handlePreviousPalette() { void handlePreviousPalette() {
Screen::get()->previousPalette(); Screen::get()->previousPalette();
Notifier::get()->show({"PALETTE " + Options::video.palette}, Notifier::TextAlign::CENTER); Notifier::get()->show({"PALETTE " + Options::video.palette});
} }
void handleToggleIntegerScale() { void handleToggleIntegerScale() {
Screen::get()->toggleIntegerScale(); Screen::get()->toggleIntegerScale();
Screen::get()->setVideoMode(Options::video.fullscreen); Screen::get()->setVideoMode(Options::video.fullscreen);
Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")}, Notifier::TextAlign::CENTER); Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")});
} }
void handleToggleVSync() { void handleToggleVSync() {
Screen::get()->toggleVSync(); Screen::get()->toggleVSync();
Notifier::get()->show({"V-SYNC " + std::string(Options::video.vertical_sync ? "ENABLED" : "DISABLED")}, Notifier::TextAlign::CENTER); Notifier::get()->show({"V-SYNC " + std::string(Options::video.vertical_sync ? "ENABLED" : "DISABLED")});
} }
#ifdef _DEBUG #ifdef _DEBUG

View File

@@ -82,7 +82,7 @@ void Cheevos::unlock(int id) {
cheevos_list_.at(INDEX).completed = true; cheevos_list_.at(INDEX).completed = true;
// Mostrar notificación en la pantalla // Mostrar notificación en la pantalla
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", cheevos_list_.at(INDEX).caption}, Notifier::TextAlign::CENTER, Notifier::DURATION_CHEEVO /*, cheevos_list_.at(INDEX).icon*/); Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", cheevos_list_.at(INDEX).caption}, Notifier::Style::CHEEVO /*, cheevos_list_.at(INDEX).icon*/);
// Guardar el estado de los logros // Guardar el estado de los logros
saveToFile(); saveToFile();

View File

@@ -85,12 +85,12 @@ void Game::handleInput() {
if (Input::get()->checkAction(InputAction::TOGGLE_MUSIC, Input::DO_NOT_ALLOW_REPEAT)) { if (Input::get()->checkAction(InputAction::TOGGLE_MUSIC, Input::DO_NOT_ALLOW_REPEAT)) {
board_->music = !board_->music; board_->music = !board_->music;
board_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); board_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic();
Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")}, Notifier::TextAlign::CENTER); Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")});
} }
else if (Input::get()->checkAction(InputAction::PAUSE, Input::DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkAction(InputAction::PAUSE, Input::DO_NOT_ALLOW_REPEAT)) {
togglePause(); togglePause();
Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")}, Notifier::TextAlign::CENTER); Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")});
} }
GlobalInputs::handle(); GlobalInputs::handle();
@@ -223,7 +223,7 @@ void Game::handleDebugEvents(const SDL_Event& event) {
switch (event.key.key) { switch (event.key.key) {
case SDLK_F12: case SDLK_F12:
Debug::get()->toggleEnabled(); Debug::get()->toggleEnabled();
Notifier::get()->show({"DEBUG " + std::string(Debug::get()->isEnabled() ? "ENABLED" : "DISABLED")}, Notifier::TextAlign::CENTER); Notifier::get()->show({"DEBUG " + std::string(Debug::get()->isEnabled() ? "ENABLED" : "DISABLED")});
room_->redrawMap(); // Redibuja el tilemap para mostrar/ocultar líneas de colisión room_->redrawMap(); // Redibuja el tilemap para mostrar/ocultar líneas de colisión
Options::cheats.invincible = static_cast<Options::Cheat::State>(Debug::get()->isEnabled()); Options::cheats.invincible = static_cast<Options::Cheat::State>(Debug::get()->isEnabled());
player_->setColor(); player_->setColor();
@@ -252,7 +252,7 @@ void Game::handleDebugEvents(const SDL_Event& event) {
break; break;
case SDLK_7: case SDLK_7:
Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, Notifier::TextAlign::CENTER, Notifier::DURATION_CHEEVO, -1, false, "F7"); Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", "I LIKE MY MULTICOLOURED FRIENDS"}, Notifier::Style::CHEEVO, -1, false, "F7");
break; break;
default: default:

View File

@@ -21,6 +21,27 @@
// [SINGLETON] // [SINGLETON]
Notifier* Notifier::notifier = nullptr; Notifier* Notifier::notifier = nullptr;
// Definición de estilos predefinidos
const Notifier::Style Notifier::Style::DEFAULT = {
.bg_color = static_cast<Uint8>(PaletteColor::BLUE),
.border_color = static_cast<Uint8>(PaletteColor::CYAN),
.text_color = static_cast<Uint8>(PaletteColor::CYAN),
.shape = Notifier::Shape::SQUARED,
.text_align = Notifier::TextAlign::CENTER,
.duration = 2.0F,
.sound_file = "notify.wav",
.play_sound = false};
const Notifier::Style Notifier::Style::CHEEVO = {
.bg_color = static_cast<Uint8>(PaletteColor::MAGENTA),
.border_color = static_cast<Uint8>(PaletteColor::BRIGHT_MAGENTA),
.text_color = static_cast<Uint8>(PaletteColor::WHITE),
.shape = Notifier::Shape::SQUARED,
.text_align = Notifier::TextAlign::CENTER,
.duration = 4.0F,
.sound_file = "notify.wav",
.play_sound = true};
// [SINGLETON] Crearemos el objeto con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
void Notifier::init(const std::string& icon_file, const std::string& text) { void Notifier::init(const std::string& icon_file, const std::string& text) {
Notifier::notifier = new Notifier(icon_file, text); Notifier::notifier = new Notifier(icon_file, text);
@@ -41,7 +62,6 @@ Notifier::Notifier(const std::string& icon_file, const std::string& text)
: icon_surface_(!icon_file.empty() ? Resource::Cache::get()->getSurface(icon_file) : nullptr), : icon_surface_(!icon_file.empty() ? Resource::Cache::get()->getSurface(icon_file) : nullptr),
text_(Resource::Cache::get()->getText(text)), text_(Resource::Cache::get()->getText(text)),
delta_timer_(std::make_unique<DeltaTimer>()), delta_timer_(std::make_unique<DeltaTimer>()),
bg_color_(Options::notifications.color),
has_icons_(!icon_file.empty()) {} has_icons_(!icon_file.empty()) {}
// Dibuja las notificaciones por pantalla // Dibuja las notificaciones por pantalla
@@ -70,12 +90,12 @@ void Notifier::update(float delta_time) {
if (notification.rect.y >= notification.y) { if (notification.rect.y >= notification.y) {
notification.rect.y = notification.y; notification.rect.y = notification.y;
notification.state = Status::STAY; notification.state = Status::STAY;
notification.start_time = SDL_GetTicks(); notification.elapsed_time = 0.0f;
} }
break; break;
} }
case Status::STAY: { case Status::STAY: {
notification.elapsed_time = SDL_GetTicks() - notification.start_time; notification.elapsed_time += delta_time;
if (notification.elapsed_time >= notification.display_duration) { if (notification.elapsed_time >= notification.display_duration) {
notification.state = Status::VANISHING; notification.state = Status::VANISHING;
} }
@@ -115,7 +135,7 @@ void Notifier::clearFinishedNotifications() {
notifications_.erase(result.begin(), result.end()); notifications_.erase(result.begin(), result.end());
} }
void Notifier::show(std::vector<std::string> texts, TextAlign text_is, Uint32 display_duration, int icon, bool can_be_removed, const std::string& code) { void Notifier::show(std::vector<std::string> texts, const Style& style, int icon, bool can_be_removed, const std::string& code) {
// Si no hay texto, acaba // Si no hay texto, acaba
if (texts.empty()) { if (texts.empty()) {
return; return;
@@ -143,10 +163,10 @@ void Notifier::show(std::vector<std::string> texts, TextAlign text_is, Uint32 di
const auto PADDING_IN_H = TEXT_SIZE; const auto PADDING_IN_H = TEXT_SIZE;
const auto PADDING_IN_V = TEXT_SIZE / 2; const auto PADDING_IN_V = TEXT_SIZE / 2;
const int ICON_SPACE = icon >= 0 ? ICON_SIZE + PADDING_IN_H : 0; const int ICON_SPACE = icon >= 0 ? ICON_SIZE + PADDING_IN_H : 0;
text_is = ICON_SPACE > 0 ? TextAlign::LEFT : text_is; const TextAlign text_is = ICON_SPACE > 0 ? TextAlign::LEFT : style.text_align;
const float WIDTH = Options::game.width - (PADDING_OUT * 2); const float WIDTH = Options::game.width - (PADDING_OUT * 2);
const float HEIGHT = (TEXT_SIZE * texts.size()) + (PADDING_IN_V * 2); const float HEIGHT = (TEXT_SIZE * texts.size()) + (PADDING_IN_V * 2);
const auto SHAPE = Shape::SQUARED; const auto SHAPE = style.shape;
// Posición horizontal // Posición horizontal
float desp_h = ((Options::game.width / 2) - (WIDTH / 2)); float desp_h = ((Options::game.width / 2) - (WIDTH / 2));
@@ -170,7 +190,7 @@ void Notifier::show(std::vector<std::string> texts, TextAlign text_is, Uint32 di
n.travel_dist = TRAVEL_DIST; n.travel_dist = TRAVEL_DIST;
n.texts = texts; n.texts = texts;
n.shape = SHAPE; n.shape = SHAPE;
n.display_duration = display_duration; n.display_duration = style.duration;
const float Y_POS = OFFSET + -TRAVEL_DIST; const float Y_POS = OFFSET + -TRAVEL_DIST;
n.rect = {.x = desp_h, .y = Y_POS, .w = WIDTH, .h = HEIGHT}; n.rect = {.x = desp_h, .y = Y_POS, .w = WIDTH, .h = HEIGHT};
@@ -185,22 +205,22 @@ void Notifier::show(std::vector<std::string> texts, TextAlign text_is, Uint32 di
SDL_FRect rect; SDL_FRect rect;
if (SHAPE == Shape::ROUNDED) { if (SHAPE == Shape::ROUNDED) {
rect = {.x = 4, .y = 0, .w = WIDTH - (4 * 2), .h = HEIGHT}; rect = {.x = 4, .y = 0, .w = WIDTH - (4 * 2), .h = HEIGHT};
n.surface->fillRect(&rect, bg_color_); n.surface->fillRect(&rect, style.bg_color);
rect = {.x = 4 / 2, .y = 1, .w = WIDTH - 4, .h = HEIGHT - 2}; rect = {.x = 4 / 2, .y = 1, .w = WIDTH - 4, .h = HEIGHT - 2};
n.surface->fillRect(&rect, bg_color_); n.surface->fillRect(&rect, style.bg_color);
rect = {.x = 1, .y = 4 / 2, .w = WIDTH - 2, .h = HEIGHT - 4}; rect = {.x = 1, .y = 4 / 2, .w = WIDTH - 2, .h = HEIGHT - 4};
n.surface->fillRect(&rect, bg_color_); n.surface->fillRect(&rect, style.bg_color);
rect = {.x = 0, .y = 4, .w = WIDTH, .h = HEIGHT - (4 * 2)}; rect = {.x = 0, .y = 4, .w = WIDTH, .h = HEIGHT - (4 * 2)};
n.surface->fillRect(&rect, bg_color_); n.surface->fillRect(&rect, style.bg_color);
} }
else if (SHAPE == Shape::SQUARED) { else if (SHAPE == Shape::SQUARED) {
n.surface->clear(bg_color_); n.surface->clear(style.bg_color);
SDL_FRect squared_rect = {0, 0, n.surface->getWidth(), n.surface->getHeight()}; SDL_FRect squared_rect = {0, 0, n.surface->getWidth(), n.surface->getHeight()};
n.surface->drawRectBorder(&squared_rect, static_cast<Uint8>(PaletteColor::CYAN)); n.surface->drawRectBorder(&squared_rect, style.border_color);
} }
// Dibuja el icono de la notificación // Dibuja el icono de la notificación
@@ -212,7 +232,7 @@ void Notifier::show(std::vector<std::string> texts, TextAlign text_is, Uint32 di
} }
// Escribe el texto de la notificación // Escribe el texto de la notificación
const auto COLOR = static_cast<Uint8>(PaletteColor::WHITE); const auto COLOR = style.text_color;
int iterator = 0; int iterator = 0;
for (const auto& text : texts) { for (const auto& text : texts) {
switch (text_is) { switch (text_is) {
@@ -239,7 +259,9 @@ void Notifier::show(std::vector<std::string> texts, TextAlign text_is, Uint32 di
notifications_.emplace_back(n); notifications_.emplace_back(n);
// Reproduce el sonido de la notificación // Reproduce el sonido de la notificación
Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE); if (style.play_sound && !style.sound_file.empty()) {
Audio::get()->playSound(style.sound_file, Audio::Group::INTERFACE);
}
} }
// Indica si hay notificaciones activas // Indica si hay notificaciones activas

View File

@@ -12,16 +12,34 @@ class DeltaTimer; // lines 11-11
class Notifier { class Notifier {
public: public:
// Constantes
static constexpr Uint32 DURATION_DEFAULT = 2000;
static constexpr Uint32 DURATION_CHEEVO = 4000;
// Justificado para las notificaciones // Justificado para las notificaciones
enum class TextAlign { enum class TextAlign {
LEFT, LEFT,
CENTER, CENTER,
}; };
// Forma de las notificaciones
enum class Shape {
ROUNDED,
SQUARED,
};
// Estilo de notificación
struct Style {
Uint8 bg_color; // Color de fondo
Uint8 border_color; // Color del borde
Uint8 text_color; // Color del texto
Shape shape; // Forma (ROUNDED/SQUARED)
TextAlign text_align; // Alineación del texto
float duration; // Duración en segundos
std::string sound_file; // Archivo de sonido (vacío = sin sonido)
bool play_sound; // Si reproduce sonido
// Estilos predefinidos
static const Style DEFAULT;
static const Style CHEEVO;
};
// Gestión singleton // Gestión singleton
static void init(const std::string& icon_file, const std::string& text); // Inicialización static void init(const std::string& icon_file, const std::string& text); // Inicialización
static void destroy(); // Destrucción static void destroy(); // Destrucción
@@ -32,8 +50,7 @@ class Notifier {
void update(float delta_time); // Actualización lógica void update(float delta_time); // Actualización lógica
void show( void show(
std::vector<std::string> texts, std::vector<std::string> texts,
TextAlign text_is = TextAlign::LEFT, const Style& style = Style::DEFAULT,
Uint32 display_duration = DURATION_DEFAULT,
int icon = -1, int icon = -1,
bool can_be_removed = true, bool can_be_removed = true,
const std::string& code = std::string()); // Mostrar notificación const std::string& code = std::string()); // Mostrar notificación
@@ -51,11 +68,6 @@ class Notifier {
FINISHED, FINISHED,
}; };
enum class Shape {
ROUNDED,
SQUARED,
};
struct Notification { struct Notification {
std::shared_ptr<Surface> surface{nullptr}; std::shared_ptr<Surface> surface{nullptr};
std::shared_ptr<SurfaceSprite> sprite{nullptr}; std::shared_ptr<SurfaceSprite> sprite{nullptr};
@@ -68,9 +80,8 @@ class Notifier {
std::string code{}; std::string code{};
bool can_be_removed{true}; bool can_be_removed{true};
int height{0}; int height{0};
Uint32 start_time{0}; float elapsed_time{0.0f};
Uint32 elapsed_time{0}; float display_duration{0.0f};
Uint32 display_duration{0};
}; };
// Constantes // Constantes
@@ -93,7 +104,6 @@ class Notifier {
std::shared_ptr<Surface> icon_surface_; // Textura para los iconos std::shared_ptr<Surface> icon_surface_; // Textura para los iconos
std::shared_ptr<Text> text_; // Objeto para dibujar texto std::shared_ptr<Text> text_; // Objeto para dibujar texto
std::unique_ptr<DeltaTimer> delta_timer_; // Timer for frame-independent animations std::unique_ptr<DeltaTimer> delta_timer_; // Timer for frame-independent animations
Uint8 bg_color_{0}; // Color de fondo de las notificaciones
std::vector<Notification> notifications_; // Lista de notificaciones activas std::vector<Notification> notifications_; // Lista de notificaciones activas
bool stack_{false}; // Indica si las notificaciones se apilan bool stack_{false}; // Indica si las notificaciones se apilan
bool has_icons_{false}; // Indica si el notificador tiene textura para iconos bool has_icons_{false}; // Indica si el notificador tiene textura para iconos