Compare commits
2 Commits
5391e0cddf
...
6bb814e61c
| Author | SHA1 | Date | |
|---|---|---|---|
| 6bb814e61c | |||
| 95ab6dea46 |
@@ -43,6 +43,7 @@ El nombre refleja su proposito: **ViBe** (vibe-coding experimental) + **Physics*
|
|||||||
| `KP_3` | **Tema NEON (colores vibrantes)** |
|
| `KP_3` | **Tema NEON (colores vibrantes)** |
|
||||||
| `KP_4` | **Tema BOSQUE (verdes naturales)** |
|
| `KP_4` | **Tema BOSQUE (verdes naturales)** |
|
||||||
| `KP_5` | **Tema RGB (fondo blanco, colores matematicos)** |
|
| `KP_5` | **Tema RGB (fondo blanco, colores matematicos)** |
|
||||||
|
| `KP_6` | **Tema MONOCHROME (fondo negro, sprites grises)** |
|
||||||
| `B` | **Ciclar entre todos los temas** |
|
| `B` | **Ciclar entre todos los temas** |
|
||||||
|
|
||||||
### Controles de Simulacion
|
### Controles de Simulacion
|
||||||
@@ -91,7 +92,7 @@ Cuando se activa el debug display con la tecla `H`:
|
|||||||
|
|
||||||
## 🎨 Sistema de Temas de Colores
|
## 🎨 Sistema de Temas de Colores
|
||||||
|
|
||||||
**ViBe1 Delta** incluye 5 temas visuales que transforman completamente la apariencia del simulador:
|
**ViBe3 Physics** incluye 6 temas visuales que transforman completamente la apariencia del simulador:
|
||||||
|
|
||||||
### Temas Disponibles
|
### Temas Disponibles
|
||||||
|
|
||||||
@@ -102,10 +103,11 @@ Cuando se activa el debug display con la tecla `H`:
|
|||||||
| `KP_3` | **NEON** | Colores vibrantes futuristas | Degradado magenta-cian | Magentas, cianes y rosas brillantes |
|
| `KP_3` | **NEON** | Colores vibrantes futuristas | Degradado magenta-cian | Magentas, cianes y rosas brillantes |
|
||||||
| `KP_4` | **BOSQUE** | Naturaleza verde relajante | Degradado verde oscuro-claro | Verdes naturales y tierra |
|
| `KP_4` | **BOSQUE** | Naturaleza verde relajante | Degradado verde oscuro-claro | Verdes naturales y tierra |
|
||||||
| `KP_5` | **RGB** | Colores matematicos puros | Fondo blanco solido | RGB puros y subdivisiones matematicas |
|
| `KP_5` | **RGB** | Colores matematicos puros | Fondo blanco solido | RGB puros y subdivisiones matematicas |
|
||||||
|
| `KP_6` | **MONOCHROME** | Estetica minimalista monocromatica | Degradado negro | 8 tonos de gris (blanco a oscuro) |
|
||||||
|
|
||||||
### Controles de Temas
|
### Controles de Temas
|
||||||
|
|
||||||
- **Seleccion directa**: Usa `KP_1`, `KP_2`, `KP_3`, `KP_4` o `KP_5` para cambiar inmediatamente al tema deseado
|
- **Seleccion directa**: Usa `KP_1` a `KP_6` para cambiar inmediatamente al tema deseado
|
||||||
- **Ciclado secuencial**: Presiona `B` para avanzar al siguiente tema en orden
|
- **Ciclado secuencial**: Presiona `B` para avanzar al siguiente tema en orden
|
||||||
- **Indicador visual**: El nombre del tema aparece temporalmente en el centro de la pantalla con colores tematicos
|
- **Indicador visual**: El nombre del tema aparece temporalmente en el centro de la pantalla con colores tematicos
|
||||||
- **Regeneracion automatica**: Las pelotas adoptan automaticamente la nueva paleta de colores al cambiar tema
|
- **Regeneracion automatica**: Las pelotas adoptan automaticamente la nueva paleta de colores al cambiar tema
|
||||||
|
|||||||
111
ROADMAP.md
Normal file
111
ROADMAP.md
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# ROADMAP - ViBe3 Physics
|
||||||
|
|
||||||
|
## Estado Actual ✅
|
||||||
|
|
||||||
|
### Figuras 3D (8/8 Completadas)
|
||||||
|
- ✅ Q - SPHERE (Esfera Fibonacci)
|
||||||
|
- ✅ W - WAVE_GRID (Malla ondeante)
|
||||||
|
- ✅ E - HELIX (Espiral helicoidal)
|
||||||
|
- ✅ R - TORUS (Toroide/donut)
|
||||||
|
- ✅ T - CUBE (Cubo rotante)
|
||||||
|
- ✅ Y - CYLINDER (Cilindro)
|
||||||
|
- ✅ U - ICOSAHEDRON (Icosaedro D20)
|
||||||
|
- ✅ I - ATOM (Núcleo + órbitas)
|
||||||
|
|
||||||
|
### Temas Visuales (5/6)
|
||||||
|
- ✅ SUNSET (Atardecer)
|
||||||
|
- ✅ OCEAN (Océano)
|
||||||
|
- ✅ NEON (Neón vibrante)
|
||||||
|
- ✅ FOREST (Bosque)
|
||||||
|
- ✅ RGB (Círculo cromático matemático)
|
||||||
|
- ⏳ MONOCHROME (Monocromo - próximo)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mejoras de Presentación 🎨
|
||||||
|
|
||||||
|
### 1. ⏳ Tema MONOCHROME
|
||||||
|
**Descripción:** Tema monocromo con fondo negro degradado y sprites blancos sin colorear
|
||||||
|
**Prioridad:** Alta
|
||||||
|
**Estimación:** 30 minutos
|
||||||
|
**Detalles:**
|
||||||
|
- Fondo negro degradado (similar a NEON)
|
||||||
|
- Sprites base color blanco (255, 255, 255)
|
||||||
|
- Solo modulación de depth (brillo), sin cambio de hue
|
||||||
|
- Tecla KP_6 para selección directa
|
||||||
|
|
||||||
|
### 2. ⏳ Cambio de Tema con LERP
|
||||||
|
**Descripción:** Transición suave entre temas sin reiniciar escenario
|
||||||
|
**Prioridad:** Alta
|
||||||
|
**Estimación:** 1 hora
|
||||||
|
**Detalles:**
|
||||||
|
- Interpolación lineal (LERP) de colores RGB
|
||||||
|
- Transición gradual de 0.5-1.0 segundos
|
||||||
|
- Mantener pelotas existentes, solo cambiar colores
|
||||||
|
- Fondo degradado también con LERP
|
||||||
|
- No llamar a `initBalls()`, solo actualizar colores
|
||||||
|
|
||||||
|
### 3. ⏳ Cambio de Textura en Caliente
|
||||||
|
**Descripción:** Cambiar sprite/textura sin resetear física
|
||||||
|
**Prioridad:** Media
|
||||||
|
**Estimación:** 1 hora
|
||||||
|
**Detalles:**
|
||||||
|
- Sistema de gestión de múltiples texturas
|
||||||
|
- Cargar texturas al inicio (ball.png, ball_small.png, etc.)
|
||||||
|
- Actualizar collision box dinámicamente según tamaño
|
||||||
|
- Tecla dedicada (ej: `N`) para ciclar texturas
|
||||||
|
- Mantener física actual, solo cambiar render
|
||||||
|
|
||||||
|
### 4. ⏳ Modo DEMO (Auto-play)
|
||||||
|
**Descripción:** Modo demostración automática con acciones aleatorias
|
||||||
|
**Prioridad:** Alta
|
||||||
|
**Estimación:** 1.5 horas
|
||||||
|
**Detalles:**
|
||||||
|
- Toggle con tecla `D`
|
||||||
|
- Timer que ejecuta acciones cada 3-8 segundos
|
||||||
|
- Acciones: cambiar gravedad, activar figura, cambiar tema, impulso
|
||||||
|
- Secuencia pseudo-aleatoria pero visualmente coherente
|
||||||
|
- Pausable con cualquier tecla de usuario
|
||||||
|
- Indicador visual "DEMO MODE" en pantalla
|
||||||
|
|
||||||
|
### 5. ⏳ Sistema de Release
|
||||||
|
**Descripción:** Empaquetado para distribución standalone
|
||||||
|
**Prioridad:** Media
|
||||||
|
**Estimación:** 30 minutos
|
||||||
|
**Detalles:**
|
||||||
|
- Crear carpeta `release/`
|
||||||
|
- Script Python `pack_resources.py` para empaquetar
|
||||||
|
- Incluir SDL3.dll
|
||||||
|
- Incluir icon.png (si existe)
|
||||||
|
- Empaquetar `data/` en archivo .dat o .zip
|
||||||
|
- Target `make release` en Makefile
|
||||||
|
- README.txt con instrucciones
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Futuras Mejoras (Ideas)
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- [ ] Spatial partitioning para colisiones ball-to-ball
|
||||||
|
- [ ] Level-of-detail para 100K+ pelotas
|
||||||
|
- [ ] GPU compute shaders para física masiva
|
||||||
|
|
||||||
|
### Efectos Visuales
|
||||||
|
- [ ] Trails (estelas de movimiento)
|
||||||
|
- [ ] Heatmaps de velocidad/energía
|
||||||
|
- [ ] Bloom/glow para sprites
|
||||||
|
|
||||||
|
### Física Avanzada
|
||||||
|
- [ ] Colisiones entre partículas
|
||||||
|
- [ ] Viento (fuerza horizontal)
|
||||||
|
- [ ] Campos magnéticos (atracción/repulsión)
|
||||||
|
- [ ] Turbulencia
|
||||||
|
|
||||||
|
### Interactividad
|
||||||
|
- [ ] Mouse: click para aplicar fuerzas
|
||||||
|
- [ ] Mouse: drag para crear campos
|
||||||
|
- [ ] Mouse wheel: ajustar intensidad
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Última actualización:** 2025-10-04
|
||||||
BIN
data/ball.png
BIN
data/ball.png
Binary file not shown.
|
Before Width: | Height: | Size: 162 B After Width: | Height: | Size: 162 B |
BIN
data/ball_small.png
Normal file
BIN
data/ball_small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 B |
@@ -73,9 +73,10 @@ class Ball {
|
|||||||
bool isOnSurface() const { return on_surface_; }
|
bool isOnSurface() const { return on_surface_; }
|
||||||
bool isStopped() const { return stopped_; }
|
bool isStopped() const { return stopped_; }
|
||||||
|
|
||||||
// Getters para batch rendering
|
// Getters/Setters para batch rendering
|
||||||
SDL_FRect getPosition() const { return pos_; }
|
SDL_FRect getPosition() const { return pos_; }
|
||||||
Color getColor() const { return color_; }
|
Color getColor() const { return color_; }
|
||||||
|
void setColor(const Color& color) { color_ = color; }
|
||||||
|
|
||||||
// Funciones para modo RotoBall
|
// Funciones para modo RotoBall
|
||||||
void setRotoBallPosition3D(float x, float y, float z);
|
void setRotoBallPosition3D(float x, float y, float z);
|
||||||
|
|||||||
@@ -53,11 +53,12 @@ enum class GravityDirection {
|
|||||||
|
|
||||||
// Enum para temas de colores (seleccionables con teclado numérico)
|
// Enum para temas de colores (seleccionables con teclado numérico)
|
||||||
enum class ColorTheme {
|
enum class ColorTheme {
|
||||||
SUNSET = 0, // Naranjas, rojos, amarillos, rosas
|
SUNSET = 0, // Naranjas, rojos, amarillos, rosas
|
||||||
OCEAN = 1, // Azules, turquesas, blancos
|
OCEAN = 1, // Azules, turquesas, blancos
|
||||||
NEON = 2, // Cian, magenta, verde lima, amarillo vibrante
|
NEON = 2, // Cian, magenta, verde lima, amarillo vibrante
|
||||||
FOREST = 3, // Verdes, marrones, amarillos otoño
|
FOREST = 3, // Verdes, marrones, amarillos otoño
|
||||||
RGB = 4 // RGB puros y subdivisiones matemáticas (fondo blanco)
|
RGB = 4, // RGB puros y subdivisiones matemáticas (fondo blanco)
|
||||||
|
MONOCHROME = 5 // Fondo negro degradado, sprites blancos monocromáticos
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enum para tipo de figura 3D
|
// Enum para tipo de figura 3D
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <algorithm> // for std::min, std::max, std::sort
|
#include <algorithm> // for std::min, std::max, std::sort
|
||||||
#include <cmath> // for sqrtf, acosf, cosf, sinf (funciones matemáticas)
|
#include <cmath> // for sqrtf, acosf, cosf, sinf (funciones matemáticas)
|
||||||
#include <cstdlib> // for rand, srand
|
#include <cstdlib> // for rand, srand
|
||||||
|
#include <cstring> // for strlen
|
||||||
#include <ctime> // for time
|
#include <ctime> // for time
|
||||||
#include <iostream> // for cout
|
#include <iostream> // for cout
|
||||||
#include <string> // for string
|
#include <string> // for string
|
||||||
@@ -165,6 +166,25 @@ void Engine::update() {
|
|||||||
if (show_text_) {
|
if (show_text_) {
|
||||||
show_text_ = !(SDL_GetTicks() - text_init_time_ > TEXT_DURATION);
|
show_text_ = !(SDL_GetTicks() - text_init_time_ > TEXT_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualizar transición de tema (LERP)
|
||||||
|
if (transitioning_) {
|
||||||
|
transition_progress_ += delta_time_ / transition_duration_;
|
||||||
|
|
||||||
|
if (transition_progress_ >= 1.0f) {
|
||||||
|
// Transición completa
|
||||||
|
transition_progress_ = 1.0f;
|
||||||
|
current_theme_ = target_theme_;
|
||||||
|
transitioning_ = false;
|
||||||
|
|
||||||
|
// Actualizar colores de las pelotas al tema final
|
||||||
|
const ThemeColors& theme = themes_[static_cast<int>(current_theme_)];
|
||||||
|
for (size_t i = 0; i < balls_.size(); i++) {
|
||||||
|
size_t color_index = i % theme.ball_colors.size();
|
||||||
|
balls_[i]->setColor(theme.ball_colors[color_index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::handleEvents() {
|
void Engine::handleEvents() {
|
||||||
@@ -285,35 +305,36 @@ void Engine::handleEvents() {
|
|||||||
|
|
||||||
// Ciclar temas de color (movido de T a B)
|
// Ciclar temas de color (movido de T a B)
|
||||||
case SDLK_B:
|
case SDLK_B:
|
||||||
// Ciclar al siguiente tema
|
// Ciclar al siguiente tema con transición suave (LERP)
|
||||||
current_theme_ = static_cast<ColorTheme>((static_cast<int>(current_theme_) + 1) % (sizeof(themes_) / sizeof(themes_[0])));
|
{
|
||||||
initBalls(scenario_); // Regenerar bolas con nueva paleta
|
ColorTheme next_theme = static_cast<ColorTheme>((static_cast<int>(current_theme_) + 1) % (sizeof(themes_) / sizeof(themes_[0])));
|
||||||
|
startThemeTransition(next_theme);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Temas de colores con teclado numérico
|
// Temas de colores con teclado numérico (con transición suave)
|
||||||
case SDLK_KP_1:
|
case SDLK_KP_1:
|
||||||
current_theme_ = ColorTheme::SUNSET;
|
startThemeTransition(ColorTheme::SUNSET);
|
||||||
initBalls(scenario_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_KP_2:
|
case SDLK_KP_2:
|
||||||
current_theme_ = ColorTheme::OCEAN;
|
startThemeTransition(ColorTheme::OCEAN);
|
||||||
initBalls(scenario_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_KP_3:
|
case SDLK_KP_3:
|
||||||
current_theme_ = ColorTheme::NEON;
|
startThemeTransition(ColorTheme::NEON);
|
||||||
initBalls(scenario_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_KP_4:
|
case SDLK_KP_4:
|
||||||
current_theme_ = ColorTheme::FOREST;
|
startThemeTransition(ColorTheme::FOREST);
|
||||||
initBalls(scenario_);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_KP_5:
|
case SDLK_KP_5:
|
||||||
current_theme_ = ColorTheme::RGB;
|
startThemeTransition(ColorTheme::RGB);
|
||||||
initBalls(scenario_);
|
break;
|
||||||
|
|
||||||
|
case SDLK_KP_6:
|
||||||
|
startThemeTransition(ColorTheme::MONOCHROME);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Control de escala de figura (solo en modo SHAPE)
|
// Control de escala de figura (solo en modo SHAPE)
|
||||||
@@ -458,7 +479,7 @@ void Engine::render() {
|
|||||||
// Renderizar en orden de profundidad (fondo → frente)
|
// Renderizar en orden de profundidad (fondo → frente)
|
||||||
for (size_t idx : render_order) {
|
for (size_t idx : render_order) {
|
||||||
SDL_FRect pos = balls_[idx]->getPosition();
|
SDL_FRect pos = balls_[idx]->getPosition();
|
||||||
Color color = balls_[idx]->getColor();
|
Color color = getInterpolatedColor(idx); // Usar color interpolado (LERP)
|
||||||
float brightness = balls_[idx]->getDepthBrightness();
|
float brightness = balls_[idx]->getDepthBrightness();
|
||||||
float depth_scale = balls_[idx]->getDepthScale();
|
float depth_scale = balls_[idx]->getDepthScale();
|
||||||
|
|
||||||
@@ -475,10 +496,12 @@ void Engine::render() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// MODO PHYSICS: Renderizar en orden normal del vector (sin escala de profundidad)
|
// MODO PHYSICS: Renderizar en orden normal del vector (sin escala de profundidad)
|
||||||
|
size_t idx = 0;
|
||||||
for (auto &ball : balls_) {
|
for (auto &ball : balls_) {
|
||||||
SDL_FRect pos = ball->getPosition();
|
SDL_FRect pos = ball->getPosition();
|
||||||
Color color = ball->getColor();
|
Color color = getInterpolatedColor(idx); // Usar color interpolado (LERP)
|
||||||
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b, 1.0f);
|
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b, 1.0f);
|
||||||
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,27 +511,19 @@ void Engine::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (show_text_) {
|
if (show_text_) {
|
||||||
// Colores acordes a cada tema (para texto del número de pelotas y nombre del tema)
|
// Obtener tema actual
|
||||||
int theme_colors[][3] = {
|
|
||||||
{255, 140, 60}, // ATARDECER: Naranja cálido
|
|
||||||
{80, 200, 255}, // OCEANO: Azul océano
|
|
||||||
{255, 60, 255}, // NEON: Magenta brillante
|
|
||||||
{100, 255, 100}, // BOSQUE: Verde natural
|
|
||||||
{100, 100, 100} // RGB: Gris oscuro (para contraste con fondo blanco)
|
|
||||||
};
|
|
||||||
int theme_idx = static_cast<int>(current_theme_);
|
int theme_idx = static_cast<int>(current_theme_);
|
||||||
|
const ThemeColors& current = themes_[theme_idx];
|
||||||
|
|
||||||
// Texto del número de pelotas con color del tema
|
// Texto del número de pelotas con color del tema
|
||||||
dbg_print(text_pos_, 8, text_.c_str(), theme_colors[theme_idx][0], theme_colors[theme_idx][1], theme_colors[theme_idx][2]);
|
dbg_print(text_pos_, 8, text_.c_str(), current.text_color_r, current.text_color_g, current.text_color_b);
|
||||||
|
|
||||||
// Mostrar nombre del tema en castellano debajo del número de pelotas
|
// Mostrar nombre del tema en castellano debajo del número de pelotas
|
||||||
std::string theme_names_es[] = {"ATARDECER", "OCEANO", "NEON", "BOSQUE", "RGB"};
|
int theme_text_width = static_cast<int>(strlen(current.name_es) * 8); // 8 píxeles por carácter
|
||||||
std::string theme_name = theme_names_es[static_cast<int>(current_theme_)];
|
int theme_x = (current_screen_width_ - theme_text_width) / 2; // Centrar horizontalmente
|
||||||
int theme_text_width = static_cast<int>(theme_name.length() * 8); // 8 píxeles por carácter
|
|
||||||
int theme_x = (current_screen_width_ - theme_text_width) / 2; // Centrar horizontalmente
|
|
||||||
|
|
||||||
// Texto del nombre del tema con el mismo color
|
// Texto del nombre del tema con el mismo color
|
||||||
dbg_print(theme_x, 24, theme_name.c_str(), theme_colors[theme_idx][0], theme_colors[theme_idx][1], theme_colors[theme_idx][2]);
|
dbg_print(theme_x, 24, current.name_es, current.text_color_r, current.text_color_g, current.text_color_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug display (solo si está activado con tecla H)
|
// Debug display (solo si está activado con tecla H)
|
||||||
@@ -548,8 +563,7 @@ void Engine::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Debug: Mostrar tema actual
|
// Debug: Mostrar tema actual
|
||||||
std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST", "RGB"};
|
std::string theme_text = std::string("THEME ") + themes_[static_cast<int>(current_theme_)].name_en;
|
||||||
std::string theme_text = "THEME " + theme_names[static_cast<int>(current_theme_)];
|
|
||||||
dbg_print(8, 64, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema
|
dbg_print(8, 64, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema
|
||||||
|
|
||||||
// Debug: Mostrar modo de simulación actual
|
// Debug: Mostrar modo de simulación actual
|
||||||
@@ -754,16 +768,32 @@ void Engine::renderGradientBackground() {
|
|||||||
// Crear quad de pantalla completa con degradado
|
// Crear quad de pantalla completa con degradado
|
||||||
SDL_Vertex bg_vertices[4];
|
SDL_Vertex bg_vertices[4];
|
||||||
|
|
||||||
// Obtener colores del tema actual
|
// Obtener colores (con LERP si estamos en transición)
|
||||||
ThemeColors &theme = themes_[static_cast<int>(current_theme_)];
|
float top_r, top_g, top_b, bottom_r, bottom_g, bottom_b;
|
||||||
|
|
||||||
float top_r = theme.bg_top_r;
|
if (transitioning_) {
|
||||||
float top_g = theme.bg_top_g;
|
// Interpolar entre tema actual y tema destino
|
||||||
float top_b = theme.bg_top_b;
|
ThemeColors ¤t = themes_[static_cast<int>(current_theme_)];
|
||||||
|
ThemeColors &target = themes_[static_cast<int>(target_theme_)];
|
||||||
|
|
||||||
float bottom_r = theme.bg_bottom_r;
|
top_r = lerp(current.bg_top_r, target.bg_top_r, transition_progress_);
|
||||||
float bottom_g = theme.bg_bottom_g;
|
top_g = lerp(current.bg_top_g, target.bg_top_g, transition_progress_);
|
||||||
float bottom_b = theme.bg_bottom_b;
|
top_b = lerp(current.bg_top_b, target.bg_top_b, transition_progress_);
|
||||||
|
|
||||||
|
bottom_r = lerp(current.bg_bottom_r, target.bg_bottom_r, transition_progress_);
|
||||||
|
bottom_g = lerp(current.bg_bottom_g, target.bg_bottom_g, transition_progress_);
|
||||||
|
bottom_b = lerp(current.bg_bottom_b, target.bg_bottom_b, transition_progress_);
|
||||||
|
} else {
|
||||||
|
// Sin transición: usar tema actual directamente
|
||||||
|
ThemeColors &theme = themes_[static_cast<int>(current_theme_)];
|
||||||
|
top_r = theme.bg_top_r;
|
||||||
|
top_g = theme.bg_top_g;
|
||||||
|
top_b = theme.bg_top_b;
|
||||||
|
|
||||||
|
bottom_r = theme.bg_bottom_r;
|
||||||
|
bottom_g = theme.bg_bottom_g;
|
||||||
|
bottom_b = theme.bg_bottom_b;
|
||||||
|
}
|
||||||
|
|
||||||
// Vértice superior izquierdo
|
// Vértice superior izquierdo
|
||||||
bg_vertices[0].position = {0, 0};
|
bg_vertices[0].position = {0, 0};
|
||||||
@@ -922,6 +952,8 @@ void Engine::zoomOut() {
|
|||||||
void Engine::initializeThemes() {
|
void Engine::initializeThemes() {
|
||||||
// SUNSET: Naranjas, rojos, amarillos, rosas (8 colores)
|
// SUNSET: Naranjas, rojos, amarillos, rosas (8 colores)
|
||||||
themes_[0] = {
|
themes_[0] = {
|
||||||
|
"SUNSET", "ATARDECER", // Nombres (inglés, español)
|
||||||
|
255, 140, 60, // Color texto: naranja cálido
|
||||||
180.0f / 255.0f, 140.0f / 255.0f, 100.0f / 255.0f, // Fondo superior (naranja suave)
|
180.0f / 255.0f, 140.0f / 255.0f, 100.0f / 255.0f, // Fondo superior (naranja suave)
|
||||||
40.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, // Fondo inferior (púrpura oscuro)
|
40.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, // Fondo inferior (púrpura oscuro)
|
||||||
{{255, 140, 0}, {255, 69, 0}, {255, 215, 0}, {255, 20, 147}, {255, 99, 71}, {255, 165, 0}, {255, 192, 203}, {220, 20, 60}}
|
{{255, 140, 0}, {255, 69, 0}, {255, 215, 0}, {255, 20, 147}, {255, 99, 71}, {255, 165, 0}, {255, 192, 203}, {220, 20, 60}}
|
||||||
@@ -929,6 +961,8 @@ void Engine::initializeThemes() {
|
|||||||
|
|
||||||
// OCEAN: Azules, turquesas, blancos (8 colores)
|
// OCEAN: Azules, turquesas, blancos (8 colores)
|
||||||
themes_[1] = {
|
themes_[1] = {
|
||||||
|
"OCEAN", "OCEANO", // Nombres (inglés, español)
|
||||||
|
80, 200, 255, // Color texto: azul océano
|
||||||
100.0f / 255.0f, 150.0f / 255.0f, 200.0f / 255.0f, // Fondo superior (azul cielo)
|
100.0f / 255.0f, 150.0f / 255.0f, 200.0f / 255.0f, // Fondo superior (azul cielo)
|
||||||
20.0f / 255.0f, 40.0f / 255.0f, 80.0f / 255.0f, // Fondo inferior (azul marino)
|
20.0f / 255.0f, 40.0f / 255.0f, 80.0f / 255.0f, // Fondo inferior (azul marino)
|
||||||
{{0, 191, 255}, {0, 255, 255}, {32, 178, 170}, {176, 224, 230}, {70, 130, 180}, {0, 206, 209}, {240, 248, 255}, {64, 224, 208}}
|
{{0, 191, 255}, {0, 255, 255}, {32, 178, 170}, {176, 224, 230}, {70, 130, 180}, {0, 206, 209}, {240, 248, 255}, {64, 224, 208}}
|
||||||
@@ -936,6 +970,8 @@ void Engine::initializeThemes() {
|
|||||||
|
|
||||||
// NEON: Cian, magenta, verde lima, amarillo vibrante (8 colores)
|
// NEON: Cian, magenta, verde lima, amarillo vibrante (8 colores)
|
||||||
themes_[2] = {
|
themes_[2] = {
|
||||||
|
"NEON", "NEON", // Nombres (inglés, español)
|
||||||
|
255, 60, 255, // Color texto: magenta brillante
|
||||||
20.0f / 255.0f, 20.0f / 255.0f, 40.0f / 255.0f, // Fondo superior (negro azulado)
|
20.0f / 255.0f, 20.0f / 255.0f, 40.0f / 255.0f, // Fondo superior (negro azulado)
|
||||||
0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior (negro)
|
0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior (negro)
|
||||||
{{0, 255, 255}, {255, 0, 255}, {50, 205, 50}, {255, 255, 0}, {255, 20, 147}, {0, 255, 127}, {138, 43, 226}, {255, 69, 0}}
|
{{0, 255, 255}, {255, 0, 255}, {50, 205, 50}, {255, 255, 0}, {255, 20, 147}, {0, 255, 127}, {138, 43, 226}, {255, 69, 0}}
|
||||||
@@ -943,6 +979,8 @@ void Engine::initializeThemes() {
|
|||||||
|
|
||||||
// FOREST: Verdes, marrones, amarillos otoño (8 colores)
|
// FOREST: Verdes, marrones, amarillos otoño (8 colores)
|
||||||
themes_[3] = {
|
themes_[3] = {
|
||||||
|
"FOREST", "BOSQUE", // Nombres (inglés, español)
|
||||||
|
100, 255, 100, // Color texto: verde natural
|
||||||
144.0f / 255.0f, 238.0f / 255.0f, 144.0f / 255.0f, // Fondo superior (verde claro)
|
144.0f / 255.0f, 238.0f / 255.0f, 144.0f / 255.0f, // Fondo superior (verde claro)
|
||||||
101.0f / 255.0f, 67.0f / 255.0f, 33.0f / 255.0f, // Fondo inferior (marrón tierra)
|
101.0f / 255.0f, 67.0f / 255.0f, 33.0f / 255.0f, // Fondo inferior (marrón tierra)
|
||||||
{{34, 139, 34}, {107, 142, 35}, {154, 205, 50}, {255, 215, 0}, {210, 180, 140}, {160, 82, 45}, {218, 165, 32}, {50, 205, 50}}
|
{{34, 139, 34}, {107, 142, 35}, {154, 205, 50}, {255, 215, 0}, {210, 180, 140}, {160, 82, 45}, {218, 165, 32}, {50, 205, 50}}
|
||||||
@@ -950,6 +988,8 @@ void Engine::initializeThemes() {
|
|||||||
|
|
||||||
// RGB: Círculo cromático con 24 puntos (cada 15°) - Ultra precisión matemática
|
// RGB: Círculo cromático con 24 puntos (cada 15°) - Ultra precisión matemática
|
||||||
themes_[4] = {
|
themes_[4] = {
|
||||||
|
"RGB", "RGB", // Nombres (inglés, español)
|
||||||
|
100, 100, 100, // Color texto: gris oscuro (contraste con fondo blanco)
|
||||||
1.0f, 1.0f, 1.0f, // Fondo superior (blanco puro)
|
1.0f, 1.0f, 1.0f, // Fondo superior (blanco puro)
|
||||||
1.0f, 1.0f, 1.0f, // Fondo inferior (blanco puro) - sin degradado
|
1.0f, 1.0f, 1.0f, // Fondo inferior (blanco puro) - sin degradado
|
||||||
{
|
{
|
||||||
@@ -979,6 +1019,54 @@ void Engine::initializeThemes() {
|
|||||||
{255, 0, 64} // 345° - Magenta claro-Rojo
|
{255, 0, 64} // 345° - Magenta claro-Rojo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// MONOCHROME: Fondo negro degradado, sprites blancos monocromáticos (8 tonos grises)
|
||||||
|
themes_[5] = {
|
||||||
|
"MONOCHROME", "MONOCROMO", // Nombres (inglés, español)
|
||||||
|
200, 200, 200, // Color texto: gris claro
|
||||||
|
20.0f / 255.0f, 20.0f / 255.0f, 20.0f / 255.0f, // Fondo superior (gris muy oscuro)
|
||||||
|
0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior (negro)
|
||||||
|
{
|
||||||
|
{255, 255, 255}, // Blanco puro - todas las pelotas del mismo color
|
||||||
|
{255, 255, 255},
|
||||||
|
{255, 255, 255},
|
||||||
|
{255, 255, 255},
|
||||||
|
{255, 255, 255},
|
||||||
|
{255, 255, 255},
|
||||||
|
{255, 255, 255},
|
||||||
|
{255, 255, 255}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::startThemeTransition(ColorTheme new_theme) {
|
||||||
|
if (new_theme == current_theme_) return; // Ya estamos en ese tema
|
||||||
|
|
||||||
|
target_theme_ = new_theme;
|
||||||
|
transitioning_ = true;
|
||||||
|
transition_progress_ = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color Engine::getInterpolatedColor(size_t ball_index) const {
|
||||||
|
if (!transitioning_) {
|
||||||
|
// Sin transición: devolver color actual
|
||||||
|
return balls_[ball_index]->getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// En transición: interpolar entre color actual y color destino
|
||||||
|
Color current_color = balls_[ball_index]->getColor();
|
||||||
|
|
||||||
|
// Obtener el color destino (mismo índice de color en el tema destino)
|
||||||
|
const ThemeColors& target_theme = themes_[static_cast<int>(target_theme_)];
|
||||||
|
size_t color_index = ball_index % target_theme.ball_colors.size();
|
||||||
|
Color target_color = target_theme.ball_colors[color_index];
|
||||||
|
|
||||||
|
// Interpolar RGB
|
||||||
|
return {
|
||||||
|
static_cast<Uint8>(lerp(static_cast<float>(current_color.r), static_cast<float>(target_color.r), transition_progress_)),
|
||||||
|
static_cast<Uint8>(lerp(static_cast<float>(current_color.g), static_cast<float>(target_color.g), transition_progress_)),
|
||||||
|
static_cast<Uint8>(lerp(static_cast<float>(current_color.b), static_cast<float>(target_color.b), transition_progress_))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::checkAutoRestart() {
|
void Engine::checkAutoRestart() {
|
||||||
|
|||||||
@@ -70,16 +70,23 @@ private:
|
|||||||
|
|
||||||
// Sistema de temas
|
// Sistema de temas
|
||||||
ColorTheme current_theme_ = ColorTheme::SUNSET;
|
ColorTheme current_theme_ = ColorTheme::SUNSET;
|
||||||
|
ColorTheme target_theme_ = ColorTheme::SUNSET; // Tema destino para transición
|
||||||
|
bool transitioning_ = false; // ¿Estamos en transición?
|
||||||
|
float transition_progress_ = 0.0f; // Progreso de 0.0 a 1.0
|
||||||
|
float transition_duration_ = 0.5f; // Duración en segundos
|
||||||
|
|
||||||
// Estructura de tema de colores
|
// Estructura de tema de colores
|
||||||
struct ThemeColors {
|
struct ThemeColors {
|
||||||
|
const char* name_en; // Nombre en inglés (para debug)
|
||||||
|
const char* name_es; // Nombre en español (para display)
|
||||||
|
int text_color_r, text_color_g, text_color_b; // Color del texto del tema
|
||||||
float bg_top_r, bg_top_g, bg_top_b;
|
float bg_top_r, bg_top_g, bg_top_b;
|
||||||
float bg_bottom_r, bg_bottom_g, bg_bottom_b;
|
float bg_bottom_r, bg_bottom_g, bg_bottom_b;
|
||||||
std::vector<Color> ball_colors;
|
std::vector<Color> ball_colors;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Temas de colores definidos
|
// Temas de colores definidos
|
||||||
ThemeColors themes_[5];
|
ThemeColors themes_[6]; // 6 temas: SUNSET, OCEAN, NEON, FOREST, RGB, MONOCHROME
|
||||||
|
|
||||||
// Sistema de Figuras 3D (polimórfico)
|
// Sistema de Figuras 3D (polimórfico)
|
||||||
SimulationMode current_mode_ = SimulationMode::PHYSICS;
|
SimulationMode current_mode_ = SimulationMode::PHYSICS;
|
||||||
@@ -116,6 +123,11 @@ private:
|
|||||||
void checkAutoRestart();
|
void checkAutoRestart();
|
||||||
void performRandomRestart();
|
void performRandomRestart();
|
||||||
|
|
||||||
|
// Sistema de transiciones LERP
|
||||||
|
float lerp(float a, float b, float t) const { return a + (b - a) * t; }
|
||||||
|
Color getInterpolatedColor(size_t ball_index) const; // Obtener color interpolado durante transición
|
||||||
|
void startThemeTransition(ColorTheme new_theme);
|
||||||
|
|
||||||
// Sistema de zoom dinámico
|
// Sistema de zoom dinámico
|
||||||
int calculateMaxWindowZoom() const;
|
int calculateMaxWindowZoom() const;
|
||||||
void setWindowZoom(int new_zoom);
|
void setWindowZoom(int new_zoom);
|
||||||
|
|||||||
Reference in New Issue
Block a user