From d0773748835dd631dd6ee2a58651ad0345bc6d73 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Wed, 24 Sep 2025 18:08:50 +0200 Subject: [PATCH] migrat a deltaTime screen.cpp i notifier.cpp --- DELTATIME_MIGRATION_PLAN.md | 81 ------------------ TODO_DELTATIME.md | 11 --- deltatime_cleanup_plan.md | 79 ----------------- development_guidelines.md | 43 ++++++++++ game_cpp_repair_plan.md | 136 ------------------------------ source/balloon_manager.cpp | 2 +- source/director.cpp | 2 +- source/game_logo.cpp | 7 +- source/screen.cpp | 10 +-- source/screen.h | 97 +++++++++++---------- source/sections/credits.cpp | 18 ++-- source/sections/game.cpp | 20 ++--- source/sections/hiscore_table.cpp | 7 +- source/sections/instructions.cpp | 17 ++-- source/sections/intro.cpp | 6 +- source/sections/logo.cpp | 7 +- source/sections/title.cpp | 7 +- source/ui/notifier.cpp | 59 +++++++------ source/ui/notifier.h | 20 +++-- 19 files changed, 192 insertions(+), 437 deletions(-) delete mode 100644 DELTATIME_MIGRATION_PLAN.md delete mode 100644 TODO_DELTATIME.md delete mode 100644 deltatime_cleanup_plan.md create mode 100644 development_guidelines.md delete mode 100644 game_cpp_repair_plan.md diff --git a/DELTATIME_MIGRATION_PLAN.md b/DELTATIME_MIGRATION_PLAN.md deleted file mode 100644 index 8f6100a..0000000 --- a/DELTATIME_MIGRATION_PLAN.md +++ /dev/null @@ -1,81 +0,0 @@ -# Plan de Migración DeltaTime - Eliminación de frameFactor - -## Problema Identificado -Se están usando `frameFactor` conversions en 7 archivos, lo que indica una migración incompleta a deltaTime. -El patrón `float frameFactor = deltaTime / (1000.0f / 60.0f)` simula frames de 60fps en lugar de usar tiempo real. - -## Archivos Afectados y Estado -1. **balloon.cpp** - 9 ocurrencias en métodos: moveX(), moveY(), updateState(), updateCreation() -2. **balloon_manager.cpp** - 2 ocurrencias en updateBalloonDeployment() -3. **bullet.cpp** - 3 ocurrencias en move() -4. **item.cpp** - 6 ocurrencias en move() -5. **moving_sprite.cpp** - 5 ocurrencias en move() -6. **tabe.cpp** - 5 ocurrencias en update() y updateHitEffect() -7. **credits.cpp** - 3 ocurrencias en update() y handleFadeOut() - -## Estrategia de Migración - -### Opción A: Velocidades ya en pixels/segundo -Si las velocidades están definidas en pixels/segundo: -```cpp -// ANTES (incorrecto) -float frameFactor = deltaTime / (1000.0f / 60.0f); -pos_x_ += vel_x_ * frameFactor; - -// DESPUÉS (correcto) -pos_x_ += vel_x_ * (deltaTime / 1000.0f); // deltaTime en ms -> segundos -``` - -### Opción B: Velocidades en pixels/frame (legacy) -Si las velocidades están en pixels/frame (sistema legacy): -```cpp -// ANTES (incorrecto con deltaTime) -float frameFactor = deltaTime / (1000.0f / 60.0f); -pos_x_ += vel_x_ * frameFactor; - -// OPCIÓN 1: Convertir velocidades a pixels/segundo -static constexpr float VEL_X_PER_SECOND = VEL_X_PER_FRAME * 60.0f; -pos_x_ += VEL_X_PER_SECOND * (deltaTime / 1000.0f); - -// OPCIÓN 2: Mantener frame-factor pero mejorar claridad -pos_x_ += vel_x_ * (deltaTime / FRAME_TIME_MS); // donde FRAME_TIME_MS = 16.67f -``` - -## Plan de Ejecución - -### Fase 1: Análisis de Velocidades -- [ ] Revisar definiciones de velocidades en cada clase -- [ ] Determinar si están en pixels/frame o pixels/segundo -- [ ] Identificar constantes que necesitan conversión - -### Fase 2: Migración por Archivo -- [x] **balloon.cpp**: Migrar velocidades x/y y contadores ✅ -- [x] **balloon_manager.cpp**: Migrar balloon_deploy_counter_ ✅ -- [x] **bullet.cpp**: Migrar velocidades de bala ✅ (VEL_Y: -3.0F→-0.18F, VEL_X: ±2.0F→±0.12F) -- [x] **item.cpp**: Migrar física de ítems ✅ (vel_x: ±1.0F→±0.06F, vel_y: -4.0F→-0.24F, accel_y: 0.2F→0.012F) -- [ ] **moving_sprite.cpp**: Migrar sistema base de movimiento -- [ ] **tabe.cpp**: Migrar movimiento y efectos -- [ ] **credits.cpp**: Migrar contadores de timing - -### Fase 3: Verificación -- [ ] Compilar y probar cada archivo migrado -- [ ] Verificar que el comportamiento se mantiene consistente -- [ ] Eliminar todas las referencias a frameFactor -- [ ] Actualizar comentarios para reflejar unidades correctas - -## Criterios de Éxito -1. ✅ Cero ocurrencias de "frameFactor" en el código -2. ✅ Todas las velocidades claramente documentadas (pixels/segundo vs pixels/frame) -3. ✅ Comportamiento del juego idéntico al anterior -4. ✅ Código más limpio y mantenible - -## Notas Importantes -- El frameFactor actual simula 60fps: `deltaTime / 16.67ms` -- Esto significa que las velocidades actuales están en "pixels per 16.67ms" -- Para verdadero deltaTime, necesitamos convertir a "pixels per second" o usar factor de frame explícito -- Mantener constantes claras para evitar números mágicos - -## Estado: En Progreso -- Análisis iniciado -- Plan documentado -- Próximo paso: Análisis de velocidades en cada archivo \ No newline at end of file diff --git a/TODO_DELTATIME.md b/TODO_DELTATIME.md deleted file mode 100644 index 6bf6291..0000000 --- a/TODO_DELTATIME.md +++ /dev/null @@ -1,11 +0,0 @@ -# TODO: Migración a deltaTime - -## Tareas pendientes - -- [ ] Repasar screen y notifier para ser compatibles con el plan de migración a deltaTime -- [ ] Ver que el param de aparición del tabe está en minutos y pasarlo a segundos (para estandarizar) -- [ ] Repasar toda la carpeta ui/ para ver si el menú de servicio es compatible con el plan de migración a deltaTime - -## Tareas completadas - -- [x] Corregir problema en sections/title.cpp - contador nunca acababa porque comparaba segundos con milisegundos (línea 396) \ No newline at end of file diff --git a/deltatime_cleanup_plan.md b/deltatime_cleanup_plan.md deleted file mode 100644 index 7e06b3d..0000000 --- a/deltatime_cleanup_plan.md +++ /dev/null @@ -1,79 +0,0 @@ -# Plan de Limpieza Post-Migración DeltaTime - -## Estado Actual -✅ Migración básica completada: bullet.cpp, item.cpp, moving_sprite.cpp, game_logo.cpp -✅ Magic numbers convertidos a constantes en game_logo.cpp - -## Tareas Pendientes - -### 1. Eliminar Contadores Frame-Based -- [ ] Buscar todos los contadores que usen lógica frame-based -- [ ] Convertir a timers basados en deltaTime -- [ ] Eliminar variables como `counter_`, `frame_counter_`, etc. -- [ ] Patrón: `if (counter-- <= 0)` → `if (timer >= DURATION_MS)` -- [ ] **IMPORTANTE**: Todos los contadores han de ser crecientes, de cero hasta llegar a la constante que define su tope - -### 2. Revisar Inicializaciones de Aceleraciones MovingSprite -- [ ] Buscar todas las llamadas a `setAccelX()`, `setAccelY()` -- [ ] Buscar asignaciones directas a `ax_`, `ay_` -- [ ] Convertir de `pixels/frame²` a `pixels/ms²` -- [ ] Factor de conversión: `valor_original / (16.67)²` - -### 3. Problema Detectado: Demo - Creación Incorrecta de Globos -- [ ] Investigar cómo se crean los globos en modo demo -- [ ] Verificar si usan timing frame-based obsoleto -- [ ] Corregir la lógica de creación para deltaTime - -### 4. Búsqueda de Patrones Problemáticos -- [ ] Buscar `frameFactor` residual -- [ ] Buscar `1000.0f / 60.0f` hardcodeado -- [ ] Buscar `16.67f` hardcodeado -- [ ] Buscar comentarios con "frame" o "60fps" -- [ ] Localizar magic numbers y convertirlos a constantes con nombres descriptivos -- [ ] **IMPORTANTE**: Modificar speed en ficheros .ani - está en frames, hay que pasarlo a milisegundos (multiplicar speed por 1000/60 = 16.67) -- [ ] **SmartSprite**: Revisar inicialización de SmartSprites en el código - cambiar setFinishedCounter() a setFinishedDelay() y convertir valores de frames a milisegundos - -### 5. Cambio de Unidades de Tiempo en sections/* -- [ ] Cambiar el cálculo de deltatime en source/sections/* para que devuelva segundos (float) en lugar de milisegundos -- [ ] Cambiar velocidades de pixeles/ms a pixeles/segundos para evitar valores absurdamente pequeños -- [ ] Cambiar aceleraciones de pixeles/ms² a pixeles/segundos² -- [ ] Actualizar todas las constantes de tiempo en archivos de sections - -### 6. Archivos Prioritarios a Revisar -- [ ] **player.cpp** - puede tener aceleraciones -- [ ] **balloon.cpp** - contadores de estado -- [ ] **stage.cpp** - timers de nivel -- [ ] **credits.cpp** - efectos de texto -- [ ] **tabe.cpp** - movimiento del protagonista -- [ ] **sections/*.cpp** - transiciones y efectos - -### 7. Validación Final -- [ ] Compilar sin warnings -- [ ] Probar gameplay normal -- [ ] Probar modo demo -- [ ] Verificar que no hay saltos de velocidad -- [ ] Confirmar que el timing es consistente en diferentes framerates - -## Comandos Útiles de Búsqueda -```bash -# Buscar contadores frame-based -rg "counter.*--|\+\+.*counter|counter.*\+\+|--.*counter" - -# Buscar inicializaciones de aceleración -rg "setAccel|\.ax.*=|\.ay.*=" - -# Buscar hardcoded framerates -rg "60\.0|16\.67|1000\.0.*60" -``` - -## DECISIÓN IMPORTANTE: TODO EL CÓDIGO USA SEGUNDOS -- **CAMBIO DE PLAN**: Todo el código del juego debe usar deltaTime en segundos (float) -- **NO** debe haber soporte para frames, milisegundos y segundos simultáneamente -- **SOLO SEGUNDOS** en todo el codebase -- Velocidades en `pixels/segundos`, aceleraciones en `pixels/segundos²` -- Todos los contadores deben ser crecientes (0 → constante_tope) -- Eliminar todos los métodos duales (updateS, setSpeedS, etc.) - solo una versión -- Convertir completamente: path_sprite.cpp, writer.cpp, tiled_bg.cpp, etc. -- Documentar las conversiones en comentarios -- Crear constantes para valores repetidos -- Evitar números mágicos \ No newline at end of file diff --git a/development_guidelines.md b/development_guidelines.md new file mode 100644 index 0000000..1f67463 --- /dev/null +++ b/development_guidelines.md @@ -0,0 +1,43 @@ +# Directrices de Desarrollo - Coffee Crisis Arcade Edition + +## Directrices Principales Confirmadas + +### 1. **Sistema Temporal** +- **TODO migrado de frame based a time based** +- **Delta time en segundos (float)** +- **Unidades de tiempo: SOLO segundos** (no frames, no milisegundos) + +### 2. **Contadores y Timers** +- **CRECIENTES**: para sistemas con múltiples eventos temporales (timeline) + - Patrón: `elapsed_time += deltaTime; if (elapsed_time >= EVENT_TIME) { /* acción */ }` +- **DECRECIENTES**: para contadores con diferentes valores de inicialización + - Patrón: `timer -= deltaTime; if (timer <= 0.0f) { /* acción */ timer = DURATION; }` + +### 3. **Números Mágicos** +- **Definidos en constantes** +- **Preferencia**: cabecera de la clase +- **Excepción**: si es algo local a un método específico + +## Problemas Pendientes de Reparación (game.cpp) + +### ❌ PENDIENTES +1. **param.fade.post_duration_ms verification** (líneas 89, 1671) +2. **setRotateSpeed verification** (línea 797) +3. **TOTAL_DEMO_DATA - 200 magic number** (línea 1669) +4. **Comprehensive magic number search** - Buscar 100, 150, 200, 250, 300, 400, 500, 1000 + +### 4. **Velocidades y Aceleraciones** +- **Velocidades**: pixels/segundo +- **Aceleraciones**: pixels/segundo² + +### 5. **Documentación de Conversiones** +- **Comentarios explicativos** en cambios críticos de timing +- Documentar conversiones frame→tiempo en el código + +### 6. **Patrón de Constantes** +- Crear constantes para valores repetidos (evitar duplicación) +- Nombres descriptivos para constantes de tiempo + +--- + +**Estado**: Directrices completas confirmadas \ No newline at end of file diff --git a/game_cpp_repair_plan.md b/game_cpp_repair_plan.md deleted file mode 100644 index 772767c..0000000 --- a/game_cpp_repair_plan.md +++ /dev/null @@ -1,136 +0,0 @@ -# Plan de Reparación: game.cpp - Limpieza DeltaTime - -## Estado Actual -✅ `calculateDeltaTime()` convertido a segundos -✅ Constantes de tiempo convertidas de `_MS` a `_S` -✅ Eliminados hardcoded `1000.0f / 60.0f` -✅ `throwCoffee()` velocidades convertidas a pixels/segundo -✅ Frame-based counter en `updateGameStateShowingGetReadyMessage()` convertido a timer con flag - -## Problemas Detectados Pendientes - -### ✅ COMPLETADO -1. **Valores hardcoded frame-based (60, 16.67, 1000/60)** - Solo quedan las conversiones correctas -2. **SmartSprite setFinishedDelay() calls** - Correcto (0.0F está bien) -3. **Velocidades y aceleraciones** - Todas convertidas correctamente -4. **Timer variables** - Todas usan deltaTime correctamente - -### ❌ PENDIENTES DE REPARAR - -#### ✅ **SOLUCIONADO: Balas no se mueven** -- **Síntoma**: Las balas se crean pero no avanzan en pantalla -- **Causa encontrada**: Velocidades en `bullet.h` seguían en pixels/ms pero `calculateDeltaTime()` ahora devuelve segundos -- **Solución aplicada**: - - `VEL_Y = -0.18F` → `VEL_Y = -180.0F` (pixels/segundo) - - `VEL_X_LEFT = -0.12F` → `VEL_X_LEFT = -120.0F` (pixels/segundo) - - `VEL_X_RIGHT = 0.12F` → `VEL_X_RIGHT = 120.0F` (pixels/segundo) - - Actualizado comentario en `bullet.cpp`: "pixels/ms" → "pixels/segundo" - -#### ✅ **SOLUCIONADO: Contadores frame-based (++ o -- operations)** -- **Problema**: `demo_.counter++` en líneas 1665, 1691 -- **Ubicación**: `updateDemo()` y `updateRecording()` -- **Contexto**: `demo_.counter` indexa un vector con datos de teclas por frame (ej: 2000 frames = 2000 entradas) -- **Solución aplicada**: Acumulador de tiempo que se incrementa cada 16.67ms (1/60 segundos) -- **Implementación**: - ```cpp - // updateDemo() - static float demo_frame_timer = 0.0f; - demo_frame_timer += calculateDeltaTime(); - if (demo_frame_timer >= 0.01667f && demo_.counter < TOTAL_DEMO_DATA) { - demo_.counter++; - demo_frame_timer -= 0.01667f; // Mantener precisión acumulada - } - - // updateRecording() - static float recording_frame_timer = 0.0f; - recording_frame_timer += calculateDeltaTime(); - if (recording_frame_timer >= 0.01667f && demo_.counter < TOTAL_DEMO_DATA) { - demo_.counter++; - recording_frame_timer -= 0.01667f; // Mantener precisión acumulada - } - ``` - -#### 6. **Fade duration values (milisegundos vs segundos)** -- **Problema 1**: `fade_out_->setPostDuration(500);` línea 234 -- **Problema 2**: `fade_out_->setPostDuration(param.fade.post_duration_ms);` líneas 89, 1671 -- **Solución**: Verificar si `param.fade.post_duration_ms` debe ser convertido a segundos - -### NUEVOS PROBLEMAS A AÑADIR - -#### 7. **Verificar param.fade estructura** -- Revisar si `param.fade.post_duration_ms` debe ser convertido a segundos -- Verificar todas las propiedades de `param.fade` relacionadas con tiempo - -#### 8. **Revisar constantes TOTAL_DEMO_DATA** -- **Problema**: `TOTAL_DEMO_DATA - 200` en línea 1669 -- **Detalle**: 200 frames hardcoded, debería ser tiempo en segundos - -#### 9. **Buscar más magic numbers relacionados con tiempo** -- Buscar números como 100, 150, 200, 500 que puedan ser frames -- Verificar contexto de cada uno - -#### 10. **Revisar setRotateSpeed() values** -- **Problema**: `setRotateSpeed(10)` línea 797 -- **Verificar**: Si debe ser convertido de rotaciones/frame a rotaciones/segundo - -#### ✅ **VERIFICADO: SDL_Delay() calls** -- **Problema**: `SDL_Delay(param.game.hit_stop_ms);` línea 847 -- **Ubicación**: `handlePlayerCollision()` -- **Contexto**: Pausa el juego al recibir daño (hitStop effect) -- **Resultado**: `param.game.hit_stop_ms` está configurado explícitamente en milisegundos en archivos .txt -- **Conclusión**: Correcto, `SDL_Delay()` espera milisegundos y `hit_stop_ms` ya está en milisegundos - -#### ✅ **VERIFICADO: Cooldown de disparos en frames** -- **Problema**: `handleFireInput()` líneas 1312-1314 -- **Detalle**: `POWERUP_COOLDOWN = 5`, `AUTOFIRE_COOLDOWN = 10`, `NORMAL_COOLDOWN = 7` -- **Contexto**: Son frames de cooldown, se pasan a `player->startFiringSystem(cant_fire_counter)` -- **Resultado**: `startFiringSystem()` convierte internamente frames a segundos con: `fire_cooldown_timer_ = static_cast(cooldown_frames) / 60.0f;` -- **Conclusión**: No necesita cambios, la conversión ya está implementada correctamente - -#### 12. **Revisar paths y PathSprite durations** -- **Problema**: En `initPaths()` líneas 1024, 1025, 1036, 1037, 1049, 1050, 1062, 1063 -- **Detalle**: `createPath(..., 80, ...), 20);` - Los números 80 y 20 son frames -- **Ejemplo**: `paths_.emplace_back(createPath(X0, X1, PathType::HORIZONTAL, Y, 80, easeOutQuint), 20);` -- **Investigar**: Si createPath espera segundos o milisegundos -- **Conversión**: 80 frames = 80/60 = 1.33s, 20 frames = 20/60 = 0.33s -- **Verificar**: Documentación de createPath() y PathSprite para unidades correctas - -## Herramientas de Búsqueda Útiles - -```bash -# Buscar magic numbers de tiempo -rg "\b(100|150|200|250|300|400|500|1000)\b" --context=2 - -# Buscar más frame-based operations -rg "setRotateSpeed|SDL_Delay|createPath.*[0-9]+" - -# Buscar estructuras param que mencionen tiempo -rg "param\..*\.(duration|time|delay|ms|frames)" - -# Buscar comentarios con "frame" or "60fps" -rg "(frame|60fps|milliseconds)" --ignore-case -``` - -## Prioridad de Reparación - -### ✅ COMPLETADAS -1. ✅ **CRÍTICA**: Las balas no se desplazan - **SOLUCIONADO**: Velocidades convertidas de pixels/ms a pixels/segundo -2. ✅ **ALTA**: demo_.counter system - **SOLUCIONADO**: Implementados acumuladores de tiempo -3. ✅ **ALTA**: Fade durations hardcoded - **SOLUCIONADO**: Convertidos a segundos -4. ✅ **ALTA**: initPaths() frame values - **SOLUCIONADO**: Convertidos a segundos -5. ✅ **MEDIA**: Cooldown de disparos - **VERIFICADO**: Ya convierte internamente frames a segundos -6. ✅ **BAJA**: SDL_Delay investigation - **VERIFICADO**: Correcto, usa milisegundos - -### ❌ PENDIENTES -7. **MEDIA**: param.fade.post_duration_ms verification (líneas 89, 1671) -8. **MEDIA**: TOTAL_DEMO_DATA - 200 magic number (línea 1669) - Nota: No necesita cambios, lógica correcta -9. **BAJA**: setRotateSpeed verification (línea 797) -10. **BAJA**: Comprehensive magic number search - -## Notas Importantes - -- **TODOS los contadores deben ser crecientes** (0 → constante_tope) -- **SOLO SEGUNDOS** en todo el codebase, NO frames ni milisegundos simultáneos -- **Documentar conversiones** con comentarios explicativos -- **Crear constantes** para valores repetidos -- **Evitar números mágicos** sin contexto \ No newline at end of file diff --git a/source/balloon_manager.cpp b/source/balloon_manager.cpp index 7d8a0fa..5e0c6ec 100644 --- a/source/balloon_manager.cpp +++ b/source/balloon_manager.cpp @@ -337,7 +337,7 @@ auto BalloonManager::destroyAllBalloons() -> int { } balloon_deploy_counter_ = DEFAULT_BALLOON_DEPLOY_DELAY; - Screen::get()->flash(Colors::FLASH, 3); + Screen::get()->flash(Colors::FLASH, 0.05F); Screen::get()->shake(); return score; diff --git a/source/director.cpp b/source/director.cpp index 3dc6a53..31055e2 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -42,7 +42,7 @@ Director::Director(int argc, std::span argv) { Section::name = Section::Name::GAME; Section::options = Section::Options::GAME_PLAY_1P; #elif _DEBUG - Section::name = Section::Name::LOGO; + Section::name = Section::Name::GAME; Section::options = Section::Options::GAME_PLAY_1P; #else // NORMAL GAME Section::name = Section::Name::LOGO; diff --git a/source/game_logo.cpp b/source/game_logo.cpp index bcfaf6b..b7779c5 100644 --- a/source/game_logo.cpp +++ b/source/game_logo.cpp @@ -15,8 +15,9 @@ #include "texture.h" // Para Texture constexpr int ZOOM_FACTOR = 5; -constexpr int FLASH_DELAY = 3; -constexpr int FLASH_LENGTH = FLASH_DELAY + 3; +constexpr float FLASH_DELAY_S = 0.05f; // 3 frames → 0.05s +constexpr float FLASH_DURATION_S = 0.1f; // 6 frames → 0.1s (3 + 3) +constexpr Color FLASH_COLOR = Color(0xFF, 0xFF, 0xFF); // Color blanco para el flash // Constructor GameLogo::GameLogo(int x, int y) @@ -242,7 +243,7 @@ void GameLogo::finishArcadeEditionMoving() { void GameLogo::playTitleEffects() { Audio::get()->playSound("title.wav"); - Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGTH, FLASH_DELAY); + Screen::get()->flash(FLASH_COLOR, FLASH_DURATION_S, FLASH_DELAY_S); Screen::get()->shake(); } diff --git a/source/screen.cpp b/source/screen.cpp index e80f554..a070fd7 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -155,16 +155,16 @@ auto Screen::incWindowSize() -> bool { return false; } -// Actualiza la lógica de la clase -void Screen::update() { +// Recibe deltaTime de las secciones y actualiza la lógica +void Screen::update(float delta_time) { fps_.calculate(SDL_GetTicks()); - shake_effect_.update(src_rect_, dst_rect_); - flash_effect_.update(); + shake_effect_.update(src_rect_, dst_rect_, delta_time); + flash_effect_.update(delta_time); if (service_menu_ != nullptr) { service_menu_->update(); } if (notifier_ != nullptr) { - notifier_->update(); + notifier_->update(delta_time); } Mouse::updateCursorVisibility(); } diff --git a/source/screen.h b/source/screen.h index 71f6dbd..bda2c39 100644 --- a/source/screen.h +++ b/source/screen.h @@ -21,7 +21,7 @@ class Screen { static auto get() -> Screen *; // Obtiene el puntero al objeto Screen // --- Métodos principales --- - void update(); // Actualiza la lógica de la clase + void update(float delta_time); // Recibe deltaTime de las secciones y actualiza la lógica void coreUpdate(); // Actualiza los elementos mínimos void clean(Color color = Color(0x00, 0x00, 0x00)); // Limpia la pantalla void start(); // Prepara para empezar a dibujar en la textura de juego @@ -38,8 +38,8 @@ class Screen { void initShaders(); // Inicializa los shaders // --- Efectos visuales --- - void shake(int desp = 2, int delay = 3, int length = 8) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay, length); } // Agita la pantalla - void flash(Color color, int length = 10, int delay = 0) { flash_effect_ = FlashEffect(true, length, delay, color); } // Pone la pantalla de color + void shake(int desp = 2, float delay_s = 0.05f, float duration_s = 0.133f) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay_s, duration_s); } // Agita la pantalla (tiempo en segundos) + void flash(Color color, float duration_s = 0.167f, float delay_s = 0.0f) { flash_effect_ = FlashEffect(true, duration_s, delay_s, color); } // Pone la pantalla de color (tiempo en segundos) void toggleShaders(); // Alterna entre activar y desactivar los shaders void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero void toggleVSync(); // Alterna entre activar y desactivar el V-Sync @@ -82,48 +82,55 @@ class Screen { } }; - // Efecto de flash en pantalla: pinta la pantalla de un color durante unos frames + // Efecto de flash en pantalla: pinta la pantalla de un color durante un tiempo struct FlashEffect { - bool enabled; // Indica si el efecto está activo - int length; // Duración total del efecto en frames - int delay; // Retraso antes de mostrar el flash - int counter; // Contador de frames restantes - Color color; // Color del flash + bool enabled; // Indica si el efecto está activo + float duration_s; // Duración total del efecto en segundos + float delay_s; // Retraso antes de mostrar el flash en segundos + float timer_s; // Timer en segundos (contador decreciente) + Color color; // Color del flash - explicit FlashEffect(bool enabled = false, int length = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF)) + explicit FlashEffect(bool enabled = false, float duration_s = 0.0f, float delay_s = 0.0f, Color color = Color(0xFF, 0xFF, 0xFF)) : enabled(enabled), - length(length), - delay(delay), - counter(length), + duration_s(duration_s), + delay_s(delay_s), + timer_s(duration_s), color(color) {} - void update() { (enabled && counter > 0) ? counter-- : static_cast(enabled = false); } - [[nodiscard]] auto isRendarable() const -> bool { return enabled && counter < length - delay; } + void update(float delta_time) { + if (enabled && timer_s > 0.0f) { + timer_s -= delta_time; + if (timer_s <= 0.0f) { + enabled = false; + } + } + } + [[nodiscard]] auto isRendarable() const -> bool { return enabled && timer_s < duration_s - delay_s; } }; // Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor struct ShakeEffect { - int desp; // Desplazamiento máximo de la sacudida (en píxeles) - int delay; // Frames entre cada movimiento de sacudida - int counter; // Contador de frames para el siguiente movimiento - int length; // Duración total del efecto en frames - int remaining; // Frames restantes de sacudida - int original_pos; // Posición original de la imagen (x) - int original_width; // Ancho original de la imagen - bool enabled; // Indica si el efecto está activo + int desp; // Desplazamiento máximo de la sacudida (en píxeles) + float delay_s; // Segundos entre cada movimiento de sacudida + float counter_s; // Timer para el siguiente movimiento (decreciente) + float duration_s; // Duración total del efecto en segundos + float remaining_s; // Tiempo restante de sacudida + int original_pos; // Posición original de la imagen (x) + int original_width; // Ancho original de la imagen + bool enabled; // Indica si el efecto está activo - explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int orig_pos = 0, int orig_width = 800) + explicit ShakeEffect(bool en = false, int dp = 2, float dl_s = 0.05f, float cnt_s = 0.0f, float len_s = 0.133f, float rem_s = 0.0f, int orig_pos = 0, int orig_width = 800) : desp(dp), - delay(dl), - counter(cnt), - length(len), - remaining(rem), + delay_s(dl_s), + counter_s(cnt_s), + duration_s(len_s), + remaining_s(rem_s), original_pos(orig_pos), original_width(orig_width), enabled(en) {} // Activa el efecto de sacudida y guarda la posición y tamaño originales - void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, int new_delay = -1, int new_length = -1) { + void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, float new_delay_s = -1.0f, float new_duration_s = -1.0f) { if (!enabled) { enabled = true; original_pos = src_rect.x; @@ -133,33 +140,35 @@ class Screen { if (new_desp != -1) { desp = new_desp; } - if (new_delay != -1) { - delay = new_delay; + if (new_delay_s >= 0.0f) { + delay_s = new_delay_s; } - if (new_length != -1) { - length = new_length; + if (new_duration_s >= 0.0f) { + duration_s = new_duration_s; } src_rect.w -= desp; dst_rect.w = src_rect.w; } - remaining = length; - counter = delay; + remaining_s = duration_s; + counter_s = delay_s; } // Actualiza el estado del efecto de sacudida - void update(SDL_FRect &src_rect, SDL_FRect &dst_rect) { + void update(SDL_FRect &src_rect, SDL_FRect &dst_rect, float delta_time) { if (enabled) { - if (counter > 0) { - counter--; - } else { - counter = delay; - const auto SRC_DESP = (remaining % 2 == 0) ? 0 : desp; - const auto DST_DESP = (remaining % 2 == 1) ? 0 : desp; + counter_s -= delta_time; + if (counter_s <= 0.0f) { + counter_s = delay_s; + // Alternar desplazamiento basado en tiempo restante + const bool SHAKE_LEFT = static_cast(remaining_s * 30.0f) % 2 == 0; // ~30 cambios por segundo + const auto SRC_DESP = SHAKE_LEFT ? 0 : desp; + const auto DST_DESP = SHAKE_LEFT ? desp : 0; src_rect.x = original_pos + SRC_DESP; dst_rect.x = original_pos + DST_DESP; - remaining--; - if (remaining == -1) { + + remaining_s -= delay_s; + if (remaining_s <= 0.0f) { enabled = false; src_rect.x = original_pos; src_rect.w = original_width; diff --git a/source/sections/credits.cpp b/source/sections/credits.cpp index e9e1a15..5ae2785 100644 --- a/source/sections/credits.cpp +++ b/source/sections/credits.cpp @@ -105,6 +105,10 @@ void Credits::update(float deltaTime) { const float multiplier = want_to_pass_ ? 4.0f : 1.0f; const float adjusted_delta_time = deltaTime * multiplier; + static auto *screen = Screen::get(); + screen->update(deltaTime); // Actualiza el objeto screen + Audio::update(); // Actualiza el objeto audio + tiled_bg_->update(adjusted_delta_time); cycleColors(); balloon_manager_->update(adjusted_delta_time); @@ -117,9 +121,7 @@ void Credits::update(float deltaTime) { const float frameFactor = adjusted_delta_time * 60.0f; counter_ += frameFactor; - Screen::get()->update(); fillCanvas(); - Audio::update(); } // Dibuja Credits::en patalla @@ -290,7 +292,7 @@ void Credits::fillCanvas() { // Actualiza el destino de los rectangulos de las texturas (time-based) void Credits::updateTextureDstRects(float deltaTime) { - constexpr float TEXTURE_UPDATE_INTERVAL_S = 10.0f / 60.0f; // ~0.167s (cada 10 frames) + constexpr float TEXTURE_UPDATE_INTERVAL_S = 10.0f / 60.0f; // ~0.167s (cada 10 frames) static float texture_accumulator = 0.0f; texture_accumulator += deltaTime; @@ -327,8 +329,8 @@ void Credits::updateTextureDstRects(float deltaTime) { void Credits::throwBalloons(float deltaTime) { constexpr int SPEED = 200; const std::vector SETS = {0, 63, 25, 67, 17, 75, 13, 50}; - constexpr float BALLOON_INTERVAL_S = SPEED / 60.0f; // ~3.33s (cada 200 frames) - constexpr float POWERBALL_INTERVAL_S = (SPEED * 4) / 60.0f; // ~13.33s (cada 800 frames) + constexpr float BALLOON_INTERVAL_S = SPEED / 60.0f; // ~3.33s (cada 200 frames) + constexpr float POWERBALL_INTERVAL_S = (SPEED * 4) / 60.0f; // ~13.33s (cada 800 frames) if (counter_ > ((SETS.size() - 1) * SPEED) * 3) { return; @@ -422,7 +424,7 @@ void Credits::initPlayers() { // Actualiza los rectangulos negros (time-based) void Credits::updateBlackRects(float deltaTime) { static float current_step_ = static_cast(steps_); - constexpr float BLACK_RECT_INTERVAL_S = 4.0f / 60.0f; // ~0.067s (cada 4 frames) + constexpr float BLACK_RECT_INTERVAL_S = 4.0f / 60.0f; // ~0.067s (cada 4 frames) static float black_rect_accumulator = 0.0f; if (top_black_rect_.h != param.game.game_area.center_y - 1 && bottom_black_rect_.y != param.game.game_area.center_y + 1) { @@ -485,12 +487,12 @@ void Credits::updateAllFades(float deltaTime) { updateRedRect(); } - fade_in_->update(); // Fade ya usa tiempo interno + fade_in_->update(); // Fade ya usa tiempo interno if (fade_in_->hasEnded()) { Audio::get()->playMusic("credits.ogg"); } - fade_out_->update(); // Fade ya usa tiempo interno + fade_out_->update(); // Fade ya usa tiempo interno if (fade_out_->hasEnded()) { Section::name = Section::Name::HI_SCORE_TABLE; } diff --git a/source/sections/game.cpp b/source/sections/game.cpp index a269a10..9688bc6 100644 --- a/source/sections/game.cpp +++ b/source/sections/game.cpp @@ -282,7 +282,7 @@ void Game::updateStage() { // Efectos de cambio de fase playSound("stage_change.wav"); balloon_manager_->resetBalloonSpeed(); - screen_->flash(Colors::FLASH, 3); + screen_->flash(Colors::FLASH, 0.05F); screen_->shake(); // Obtener datos de la nueva fase @@ -635,7 +635,7 @@ void Game::updateItems(float deltaTime) { item->update(deltaTime); if (item->isOnFloor()) { playSound("title.wav"); - screen_->shake(1, 2, 4); + screen_->shake(1, 0.033f, 0.067f); // desp=1, delay=0.033s, length=0.067s } } } @@ -784,7 +784,7 @@ void Game::throwCoffee(int x, int y) { smart_sprites_.back()->setWidth(param.game.item_size); smart_sprites_.back()->setHeight(param.game.item_size); smart_sprites_.back()->setVelX((-1.0F + ((rand() % 5) * 0.5F)) * 60.0f); // Convertir a pixels/segundo - smart_sprites_.back()->setVelY(-4.0F * 60.0f); // Convertir a pixels/segundo + smart_sprites_.back()->setVelY(-4.0F * 60.0f); // Convertir a pixels/segundo smart_sprites_.back()->setAccelX(0.0F); smart_sprites_.back()->setAccelY(0.2F * 60.0f * 60.0f); // Convertir a pixels/segundo² (0.2 × 60²) smart_sprites_.back()->setDestX(x + (smart_sprites_.back()->getVelX() * 50)); @@ -859,9 +859,9 @@ void Game::handlePlayerCollision(std::shared_ptr &player, std::shared_pt // Actualiza el estado del tiempo detenido void Game::updateTimeStopped(float deltaTime) { - static constexpr float WARNING_THRESHOLD_S = 2.0f; // 120 frames a 60fps → segundos - static constexpr float CLOCK_SOUND_INTERVAL_S = 0.5f; // 30 frames a 60fps → segundos - static constexpr float COLOR_FLASH_INTERVAL_S = 0.25f; // 15 frames a 60fps → segundos + static constexpr float WARNING_THRESHOLD_S = 2.0f; // 120 frames a 60fps → segundos + static constexpr float CLOCK_SOUND_INTERVAL_S = 0.5f; // 30 frames a 60fps → segundos + static constexpr float COLOR_FLASH_INTERVAL_S = 0.25f; // 15 frames a 60fps → segundos if (time_stopped_timer_ > 0) { time_stopped_timer_ -= deltaTime; @@ -895,7 +895,8 @@ void Game::updateTimeStopped(float deltaTime) { // Actualiza toda la lógica del juego void Game::update(float deltaTime) { - screen_->update(); + screen_->update(deltaTime); // Actualiza el objeto screen + Audio::update(); // Actualiza el objeto audio updateDemo(); #ifdef RECORDING @@ -903,8 +904,6 @@ void Game::update(float deltaTime) { #endif updateGameStates(deltaTime); fillCanvas(); - - Audio::update(); } // Dibuja el juego @@ -1735,9 +1734,6 @@ void Game::updateGameStateEnteringPlayer(float deltaTime) { // Actualiza las variables durante dicho estado void Game::updateGameStateShowingGetReadyMessage(float deltaTime) { updateGameStatePlaying(deltaTime); - if (path_sprites_.empty()) { - setState(State::PLAYING); - } // Reproducir música después de ~1.67 segundos (100 frames a 60fps) static bool music_started = false; diff --git a/source/sections/hiscore_table.cpp b/source/sections/hiscore_table.cpp index 5caf681..6c13634 100644 --- a/source/sections/hiscore_table.cpp +++ b/source/sections/hiscore_table.cpp @@ -55,15 +55,16 @@ HiScoreTable::~HiScoreTable() { // Actualiza las variables void HiScoreTable::update(float delta_time) { elapsed_time_ += delta_time; // Incrementa el tiempo transcurrido - Screen::get()->update(); // Actualiza el objeto screen + + static auto *screen = Screen::get(); + screen->update(delta_time); // Actualiza el objeto screen + Audio::update(); // Actualiza el objeto audio updateSprites(delta_time); // Actualiza las posiciones de los sprites de texto background_->update(delta_time); // Actualiza el fondo updateFade(delta_time); // Gestiona el fade updateCounter(); // Gestiona el contador y sus eventos fillTexture(); // Dibuja los sprites en la textura - - Audio::update(); } // Pinta en pantalla diff --git a/source/sections/instructions.cpp b/source/sections/instructions.cpp index 3bc1c9b..6286640 100644 --- a/source/sections/instructions.cpp +++ b/source/sections/instructions.cpp @@ -205,16 +205,17 @@ void Instructions::fillBackbuffer() { // Actualiza las variables void Instructions::update(float delta_time) { - elapsed_time_ += delta_time; // Incrementa el tiempo transcurrido - Screen::get()->update(); // Actualiza el objeto screen + elapsed_time_ += delta_time; // Incrementa el tiempo transcurrido - updateSprites(); // Actualiza los sprites - updateBackbuffer(delta_time); // Gestiona la textura con los graficos - tiled_bg_->update(delta_time); // Actualiza el mosaico de fondo - fade_->update(delta_time); // Actualiza el objeto "fade" - fillBackbuffer(); // Rellena el backbuffer + static auto *screen = Screen::get(); + screen->update(delta_time); // Actualiza el objeto screen + Audio::update(); // Actualiza el objeto audio - Audio::update(); + updateSprites(); // Actualiza los sprites + updateBackbuffer(delta_time); // Gestiona la textura con los graficos + tiled_bg_->update(delta_time); // Actualiza el mosaico de fondo + fade_->update(delta_time); // Actualiza el objeto "fade" + fillBackbuffer(); // Rellena el backbuffer } // Pinta en pantalla diff --git a/source/sections/intro.cpp b/source/sections/intro.cpp index 5659f11..40f0b78 100644 --- a/source/sections/intro.cpp +++ b/source/sections/intro.cpp @@ -208,7 +208,9 @@ void Intro::switchText(int from_index, int to_index) { // Actualiza las variables del objeto void Intro::update(float delta_time) { - Screen::get()->update(); // Actualiza el objeto screen + static auto *screen = Screen::get(); + screen->update(delta_time); // Actualiza el objeto screen + Audio::update(); // Actualiza el objeto Aud tiled_bg_->update(delta_time); // Actualiza el fondo @@ -223,8 +225,6 @@ void Intro::update(float delta_time) { updatePostState(); break; } - - Audio::update(); } // Dibuja el objeto en pantalla diff --git a/source/sections/logo.cpp b/source/sections/logo.cpp index 988651e..9ce4607 100644 --- a/source/sections/logo.cpp +++ b/source/sections/logo.cpp @@ -138,10 +138,11 @@ void Logo::updateTextureColors(float delta_time) { // Actualiza las variables void Logo::update(float delta_time) { - elapsed_time_s_ += delta_time; // Acumula el tiempo transcurrido + elapsed_time_s_ += delta_time; // Acumula el tiempo transcurrido - Screen::get()->update(); // Actualiza el objeto screen - Audio::update(); // Actualiza el objeto audio + static auto *screen = Screen::get(); + screen->update(delta_time); // Actualiza el objeto screen + Audio::update(); // Actualiza el objeto audio handleSound(); // Maneja la reproducción del sonido updateTextureColors(delta_time); // Actualiza los colores de las texturas diff --git a/source/sections/title.cpp b/source/sections/title.cpp index 846fab9..f04f784 100644 --- a/source/sections/title.cpp +++ b/source/sections/title.cpp @@ -80,7 +80,10 @@ Title::~Title() { // Actualiza las variables del objeto void Title::update(float deltaTime) { - Screen::get()->update(); + static auto* screen = Screen::get(); + screen->update(deltaTime); // Actualiza el objeto screen + Audio::update(); // Actualiza el objeto audio + updateFade(); updateState(deltaTime); updateStartPrompt(deltaTime); @@ -88,8 +91,6 @@ void Title::update(float deltaTime) { for (auto& player : players_) { player->update(deltaTime); } - - Audio::update(); } // Calcula el tiempo transcurrido desde el último frame diff --git a/source/ui/notifier.cpp b/source/ui/notifier.cpp index bcae930..9164018 100644 --- a/source/ui/notifier.cpp +++ b/source/ui/notifier.cpp @@ -2,7 +2,7 @@ #include // Para SDL_RenderFillRect, SDL_FRect, SDL_RenderClear -#include // Para remove_if +#include // Para remove_if, min #include // Para basic_string, string #include #include // Para vector @@ -32,7 +32,6 @@ Notifier::Notifier(const std::string& icon_file, std::shared_ptr text) icon_texture_(!icon_file.empty() ? std::make_unique(renderer_, icon_file) : nullptr), text_(std::move(text)), bg_color_(param.notification.color), - wait_time_(150), stack_(false), has_icons_(!icon_file.empty()) {} @@ -43,13 +42,13 @@ void Notifier::render() { } } -// Actualiza el estado de las notificaiones -void Notifier::update() { +// Actualiza el estado de las notificaciones +void Notifier::update(float delta_time) { for (int i = 0; i < (int)notifications_.size(); ++i) { if (!shouldProcessNotification(i)) { break; } - processNotification(i); + processNotification(i, delta_time); } clearFinishedNotifications(); } @@ -59,52 +58,54 @@ auto Notifier::shouldProcessNotification(int index) const -> bool { return index <= 0 || notifications_[index - 1].state != State::RISING; } -void Notifier::processNotification(int index) { +void Notifier::processNotification(int index, float delta_time) { auto& notification = notifications_[index]; - notification.counter++; + notification.timer += delta_time; playNotificationSoundIfNeeded(notification); - updateNotificationState(index); + updateNotificationState(index, delta_time); notification.sprite->setPosition(notification.rect); } void Notifier::playNotificationSoundIfNeeded(const Notification& notification) { - // Hace sonar la notificación en el primer frame - if (notification.counter == 1 && + // Hace sonar la notificación al inicio + if (notification.timer <= 0.016f && param.notification.sound && notification.state == State::RISING) { Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE); } } -void Notifier::updateNotificationState(int index) { +void Notifier::updateNotificationState(int index, float delta_time) { auto& notification = notifications_[index]; switch (notification.state) { case State::RISING: - handleRisingState(index); + handleRisingState(index, delta_time); break; case State::STAY: handleStayState(index); break; case State::VANISHING: - handleVanishingState(index); + handleVanishingState(index, delta_time); break; default: break; } } -void Notifier::handleRisingState(int index) { +void Notifier::handleRisingState(int index, float delta_time) { auto& notification = notifications_[index]; - const float STEP = (float)notification.counter / notification.travel_dist; - const int ALPHA = 255 * STEP; + const float PIXELS_TO_MOVE = ANIMATION_SPEED_PX_PER_S * delta_time; + const float PROGRESS = notification.timer * ANIMATION_SPEED_PX_PER_S / notification.travel_dist; + const int ALPHA = static_cast(255 * std::min(PROGRESS, 1.0f)); - moveNotificationVertically(notification, param.notification.pos_v == Position::TOP ? 1 : -1); + moveNotificationVertically(notification, param.notification.pos_v == Position::TOP ? PIXELS_TO_MOVE : -PIXELS_TO_MOVE); notification.texture->setAlpha(ALPHA); - if (notification.rect.y == notification.y) { + if ((param.notification.pos_v == Position::TOP && notification.rect.y >= notification.y) || + (param.notification.pos_v == Position::BOTTOM && notification.rect.y <= notification.y)) { transitionToStayState(index); } } @@ -112,35 +113,37 @@ void Notifier::handleRisingState(int index) { void Notifier::handleStayState(int index) { auto& notification = notifications_[index]; - if (notification.counter == wait_time_) { + if (notification.timer >= STAY_DURATION_S) { notification.state = State::VANISHING; - notification.counter = 0; + notification.timer = 0.0f; } } -void Notifier::handleVanishingState(int index) { +void Notifier::handleVanishingState(int index, float delta_time) { auto& notification = notifications_[index]; - const float STEP = notification.counter / (float)notification.travel_dist; - const int ALPHA = 255 * (1 - STEP); + const float PIXELS_TO_MOVE = ANIMATION_SPEED_PX_PER_S * delta_time; + const float PROGRESS = notification.timer * ANIMATION_SPEED_PX_PER_S / notification.travel_dist; + const int ALPHA = static_cast(255 * (1 - std::min(PROGRESS, 1.0f))); - moveNotificationVertically(notification, param.notification.pos_v == Position::TOP ? -1 : 1); + moveNotificationVertically(notification, param.notification.pos_v == Position::TOP ? -PIXELS_TO_MOVE : PIXELS_TO_MOVE); notification.texture->setAlpha(ALPHA); - if (notification.rect.y == notification.y - notification.travel_dist) { + if (PROGRESS >= 1.0f) { notification.state = State::FINISHED; } } -void Notifier::moveNotificationVertically(Notification& notification, int direction) { - notification.rect.y += direction; +void Notifier::moveNotificationVertically(Notification& notification, float pixels_to_move) { + notification.rect.y += pixels_to_move; } void Notifier::transitionToStayState(int index) { auto& notification = notifications_[index]; notification.state = State::STAY; notification.texture->setAlpha(255); - notification.counter = 0; + notification.rect.y = static_cast(notification.y); // Asegurar posición exacta + notification.timer = 0.0f; } // Elimina las notificaciones finalizadas diff --git a/source/ui/notifier.h b/source/ui/notifier.h index b8d775d..f424f2c 100644 --- a/source/ui/notifier.h +++ b/source/ui/notifier.h @@ -32,7 +32,7 @@ class Notifier { // --- Métodos principales --- void render(); // Dibuja las notificaciones por pantalla - void update(); // Actualiza el estado de las notificaciones + void update(float delta_time); // Actualiza el estado de las notificaciones // --- Gestión de notificaciones --- void show(std::vector texts, int icon = -1, const std::string &code = std::string()); // Muestra una notificación de texto por pantalla @@ -41,6 +41,10 @@ class Notifier { auto checkCode(const std::string &code) -> bool { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto private: + // --- Constantes de tiempo (en segundos) --- + static constexpr float STAY_DURATION_S = 2.5f; // Tiempo que se ve la notificación (150 frames @ 60fps) + static constexpr float ANIMATION_SPEED_PX_PER_S = 60.0f; // Velocidad de animación (1 pixel/frame @ 60fps) + // --- Enums privados --- enum class State { RISING, // Apareciendo @@ -63,7 +67,7 @@ class Notifier { std::string code; // Código identificador de la notificación State state{State::RISING}; // Estado de la notificación Shape shape{Shape::SQUARED}; // Forma de la notificación - int counter{0}; // Contador de tiempo + float timer{0.0f}; // Timer en segundos int y{0}; // Posición vertical int travel_dist{0}; // Distancia a recorrer @@ -82,7 +86,7 @@ class Notifier { // --- Variables de estado --- std::vector notifications_; // Lista de notificaciones activas Color bg_color_; // Color de fondo de las notificaciones - int wait_time_; // Tiempo que se ve la notificación + // Nota: wait_time_ eliminado, ahora se usa STAY_DURATION_S bool stack_; // Indica si las notificaciones se apilan bool has_icons_; // Indica si el notificador tiene textura para iconos @@ -90,13 +94,13 @@ class Notifier { void clearFinishedNotifications(); // Elimina las notificaciones cuyo estado es FINISHED void clearAllNotifications(); // Elimina todas las notificaciones activas, sin importar el estado [[nodiscard]] auto shouldProcessNotification(int index) const -> bool; // Determina si una notificación debe ser procesada (según su estado y posición) - void processNotification(int index); // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual + void processNotification(int index, float delta_time); // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual static void playNotificationSoundIfNeeded(const Notification ¬ification); // Reproduce sonido asociado si es necesario (dependiendo del estado o contenido) - void updateNotificationState(int index); // Actualiza el estado interno de una notificación (ej. de RISING a STAY) - void handleRisingState(int index); // Lógica de animación para el estado RISING (apareciendo) + void updateNotificationState(int index, float delta_time); // Actualiza el estado interno de una notificación (ej. de RISING a STAY) + void handleRisingState(int index, float delta_time); // Lógica de animación para el estado RISING (apareciendo) void handleStayState(int index); // Lógica para mantener una notificación visible en el estado STAY - void handleVanishingState(int index); // Lógica de animación para el estado VANISHING (desapareciendo) - static void moveNotificationVertically(Notification ¬ification, int direction); // Mueve verticalmente una notificación en una dirección dada (útil para animación en apilamiento) + void handleVanishingState(int index, float delta_time); // Lógica de animación para el estado VANISHING (desapareciendo) + static void moveNotificationVertically(Notification ¬ification, float pixels_to_move); // Mueve verticalmente una notificación con la cantidad de pixels especificada void transitionToStayState(int index); // Cambia el estado de una notificación de RISING a STAY cuando ha alcanzado su posición final // --- Constructores y destructor privados (singleton) ---