migrat a deltaTime screen.cpp i notifier.cpp
This commit is contained in:
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
43
development_guidelines.md
Normal file
43
development_guidelines.md
Normal file
@@ -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
|
||||
@@ -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<float>(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
|
||||
@@ -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;
|
||||
|
||||
@@ -42,7 +42,7 @@ Director::Director(int argc, std::span<char *> 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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<int>(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<int>(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;
|
||||
|
||||
@@ -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<int> 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<float>(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;
|
||||
}
|
||||
|
||||
@@ -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> &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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <SDL3/SDL.h> // Para SDL_RenderFillRect, SDL_FRect, SDL_RenderClear
|
||||
|
||||
#include <algorithm> // Para remove_if
|
||||
#include <algorithm> // Para remove_if, min
|
||||
#include <string> // Para basic_string, string
|
||||
#include <utility>
|
||||
#include <vector> // Para vector
|
||||
@@ -32,7 +32,6 @@ Notifier::Notifier(const std::string& icon_file, std::shared_ptr<Text> text)
|
||||
icon_texture_(!icon_file.empty() ? std::make_unique<Texture>(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<int>(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<int>(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<float>(notification.y); // Asegurar posición exacta
|
||||
notification.timer = 0.0f;
|
||||
}
|
||||
|
||||
// Elimina las notificaciones finalizadas
|
||||
|
||||
@@ -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<std::string> 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<Notification> 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) ---
|
||||
|
||||
Reference in New Issue
Block a user