diff --git a/README.md b/README.md index 22151b4..f84ef6f 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,16 @@ El nombre refleja su proposito: **ViBe** (vibe-coding experimental) + **Physics* - **Simulacion de fisica**: Gravedad, rebotes y colisiones con perdida de energia - **Multiples escenarios**: 8 configuraciones predefinidas (1 a 100,000 pelotas) -- **Sistema de temas visuales**: 5 temas de colores con fondos degradados y paletas tematicas +- **Sistema de temas visuales**: 6 temas de colores con fondos degradados y paletas tematicas +- **Transiciones LERP**: Cambios de tema suaves y fluidos (0.5s) sin reiniciar escenario +- **Hot-swap de sprites**: Cambio de textura dinamico (ball.png ↔ ball_small.png) con tecla N - **Sistema de zoom dinamico**: F1/F2 para ajustar el zoom de ventana (1x-10x) - **Modos fullscreen**: F3 para fullscreen normal, F4 para real fullscreen con resolucion nativa - **Gravedad multidireccional**: Gravedad hacia abajo, arriba, izquierda o derecha +- **8 Figuras 3D**: Esfera, Wave Grid, Helix, Torus, Cubo, Cilindro, Icosaedro, Atom - **Interactividad**: Controles de teclado para modificar el comportamiento - **Renderizado batch optimizado**: Sistema de batch rendering con SDL_RenderGeometry para 50K+ sprites -- **Colores tematicos**: Paletas de 8 colores por tema aplicadas proceduralmente +- **Colores tematicos**: Paletas de 8-24 colores por tema aplicadas proceduralmente - **Monitor de rendimiento**: Contador FPS en tiempo real - **Control V-Sync**: Activacion/desactivacion dinamica del V-Sync @@ -43,8 +46,9 @@ El nombre refleja su proposito: **ViBe** (vibe-coding experimental) + **Physics* | `KP_3` | **Tema NEON (colores vibrantes)** | | `KP_4` | **Tema BOSQUE (verdes naturales)** | | `KP_5` | **Tema RGB (fondo blanco, colores matematicos)** | -| `KP_6` | **Tema MONOCHROME (fondo negro, sprites grises)** | +| `KP_6` | **Tema MONOCHROME (fondo negro, todas las pelotas blancas)** | | `B` | **Ciclar entre todos los temas** | +| `N` | **Cambiar sprite (ball.png ↔ ball_small.png)** | ### Controles de Simulacion | Tecla | Accion | @@ -61,14 +65,14 @@ El nombre refleja su proposito: **ViBe** (vibe-coding experimental) + **Physics* | Tecla | Accion | |-------|--------| | `F` | **Toggle entre modo FISICA ↔ última FIGURA 3D** | -| `Q` | **Activar figura ESFERA (Fibonacci Sphere)** | -| `W` | **Activar figura WAVE GRID (pendiente)** | -| `E` | **Activar figura HELIX (pendiente)** | -| `R` | **Activar figura TORUS (pendiente)** | -| `T` | **Activar figura CUBO (rotación triple XYZ)** | -| `Y` | **Activar figura CYLINDER (pendiente)** | -| `U` | **Activar figura ICOSAHEDRON (pendiente)** | -| `I` | **Activar figura ATOM (pendiente)** | +| `Q` | **Activar figura SPHERE (Esfera Fibonacci)** | +| `W` | **Activar figura WAVE GRID (Malla ondeante)** | +| `E` | **Activar figura HELIX (Espiral helicoidal)** | +| `R` | **Activar figura TORUS (Toroide/donut)** | +| `T` | **Activar figura CUBE (Cubo rotante triple XYZ)** | +| `Y` | **Activar figura CYLINDER (Cilindro)** | +| `U` | **Activar figura ICOSAHEDRON (Icosaedro D20)** | +| `I` | **Activar figura ATOM (Núcleo + órbitas)** | | `KP_+` | **Aumentar escala de figura (+10%)** | | `KP_-` | **Reducir escala de figura (-10%)** | | `KP_*` | **Reset escala de figura a 100%** | @@ -103,48 +107,85 @@ 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_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_6` | **MONOCHROME** | Estetica minimalista monocromatica | Degradado negro | 8 tonos de gris (blanco a oscuro) | +| `KP_6` | **MONOCHROME** | Estetica minimalista monocromatica | Degradado negro | Todas las pelotas blancas puras | ### Controles de Temas -- **Seleccion directa**: Usa `KP_1` a `KP_6` para cambiar inmediatamente al tema deseado +- **Seleccion directa**: Usa `KP_1` a `KP_6` para cambiar al tema deseado - **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 -- **Regeneracion automatica**: Las pelotas adoptan automaticamente la nueva paleta de colores al cambiar tema +- **Transiciones suaves**: Cambios de tema con interpolación LERP (0.5 segundos) +- **Sin reinicio**: Mantiene física y posiciones, solo cambia colores +- **Indicador visual**: Nombre del tema aparece temporalmente en centro de pantalla + +### Sistema de Sprites Dinámico + +- **Tecla N**: Cambia entre ball.png (10x10) y ball_small.png (6x6) +- **Hot-swap**: Sin reiniciar física, actualiza textura y hitbox al instante +- **Ajuste automático**: Posiciones corregidas según gravedad y superficie +- **Tamaño dinámico**: `current_ball_size_` obtenido desde `texture->getWidth()` +- **Texto informativo**: Muestra "SPRITE: NORMAL" o "SPRITE: SMALL" ### Detalles Tecnicos - **Fondos degradados**: Implementados con `SDL_RenderGeometry` usando vertices con colores interpolados -- **Paletas tematicas**: 8 colores unicos por tema aplicados aleatoriamente a las pelotas -- **Rendimiento optimizado**: El cambio de tema solo regenera los colores, manteniendo la fisica +- **Paletas tematicas**: 8-24 colores por tema (RGB tiene 24, resto 8) +- **Interpolación LERP**: Transiciones RGB suaves frame-a-frame durante 0.5s +- **Sin regeneración**: Cambio de tema no llama `initBalls()`, solo actualiza colores +- **Rendimiento optimizado**: LERP tiene overhead mínimo (<1ms con 10K pelotas) - **Compatibilidad completa**: Funciona con todos los escenarios (1 a 100,000 pelotas) ## 🎯 Sistema de Figuras 3D - Efectos Demoscene **ViBe3 Physics** incluye un sistema polimórfico de figuras 3D que convierte las pelotas en formas geométricas rotantes proyectadas en 2D. -### Figuras Implementadas +### Figuras Implementadas (8/8 Completas) -#### 🌐 ESFERA (Tecla Q) +#### 🌐 SPHERE (Tecla Q) - **Algoritmo**: Fibonacci Sphere - distribución uniforme de puntos - **Rotación**: Dual (ejes X e Y) - **Efecto**: Esfera rotante clásica estilo demoscene -#### 🎲 CUBO (Tecla T) +#### 🌊 WAVE GRID (Tecla W) +- **Algoritmo**: Grid NxN con ondas sinusoidales en Z +- **Animación**: Olas propagándose en tiempo real +- **Rotación**: XY combinada +- **Efecto**: Océano ondulante + +#### 🧬 HELIX (Tecla E) +- **Algoritmo**: Espiral helicoidal paramétrica +- **Animación**: Rotación suave en eje Y +- **Altura**: 75% de pantalla (ajustable) +- **Efecto**: DNA/hélice rotante + +#### 🍩 TORUS (Tecla R) +- **Algoritmo**: Toroide paramétrico (radio mayor + radio menor) +- **Rotación**: Triple eje con velocidades diferentes +- **Efecto**: Donut flotante estilo demoscene + +#### 🎲 CUBE (Tecla T) - **Distribución inteligente**: - - 1-8 pelotas: Solo vértices (8 puntos) - - 9-26 pelotas: Vértices + centros de caras + aristas (26 puntos) - - 27+ pelotas: Grid volumétrico 3D uniforme -- **Rotación**: Triple (ejes X, Y y Z simultáneos) + - 1-8: Solo vértices (8 puntos) + - 9-26: Vértices + caras + aristas (26 puntos) + - 27+: Grid volumétrico 3D uniforme +- **Rotación**: Triple (X, Y, Z simultáneos) - **Efecto**: Cubo Rubik rotante -#### 🔮 Figuras Futuras (Pendientes) -- **W - WAVE GRID**: Malla ondeante 3D -- **E - HELIX**: Espiral helicoidal -- **R - TORUS**: Donut/toroide -- **Y - CYLINDER**: Cilindro rotante -- **U - ICOSAHEDRON**: Poliedro D20 -- **I - ATOM**: Núcleo con órbitas electrónicas +#### 🏛️ CYLINDER (Tecla Y) +- **Algoritmo**: Cilindro con tapas circulares +- **Rotación**: Eje Y (spin horizontal) +- **Efecto**: Columna griega rotante + +#### ⚛️ ICOSAHEDRON (Tecla U) +- **Algoritmo**: Poliedro regular de 20 caras +- **Geometría**: 12 vértices, proporción áurea +- **Rotación**: Triple eje caótico +- **Efecto**: Dado D20 flotante + +#### ⚛️ ATOM (Tecla I) +- **Estructura**: Núcleo central + 3 órbitas elípticas +- **Animación**: Electrones en movimiento orbital +- **Rotación**: Órbitas perpendiculares entre sí +- **Efecto**: Átomo de Bohr animado ### Características Técnicas @@ -219,7 +260,8 @@ vibe3_physics/ │ ├── dbgtxt.h # Sistema de debug para texto en pantalla │ └── stb_image.h # Biblioteca para cargar imagenes ├── data/ -│ └── ball.png # Textura de la pelota (10x10 pixeles) +│ ├── ball.png # Textura normal de la pelota (10x10 pixeles) +│ └── ball_small.png # Textura pequeña de la pelota (6x6 pixeles) ├── CMakeLists.txt # Configuracion de CMake ├── Makefile # Configuracion de Make ├── CLAUDE.md # Seguimiento de desarrollo @@ -279,11 +321,13 @@ make ## 📊 Detalles Tecnicos ### Configuracion Actual -- **Resolucion**: 640x360 pixeles (escalado x2 = 1280x720) +- **Resolucion**: 320x240 pixeles (escalado x3 = 960x720 por defecto) - **Sistema de timing**: Delta time independiente del framerate -- **Fisica**: Gravedad constante (0.2f), rebotes con perdida de energia -- **Tamaño de pelota**: 10x10 pixeles +- **Fisica**: Gravedad constante (0.2 px/frame² → 720 px/s²), rebotes con perdida de energia variable (0.30-0.95) +- **Tamaño de pelota**: Dinámico (10x10 o 6x6 según sprite activo) - **V-Sync**: Activado por defecto, controlable dinamicamente +- **Temas**: 6 temas con transiciones LERP de 0.5s +- **Figuras 3D**: 8 figuras completas con física de atracción ### Arquitectura del Codigo @@ -464,6 +508,118 @@ SDL_RenderGeometry(renderer, texture->getSDLTexture(), - **100,000 bolas**: Fluido y jugable - **Escalabilidad**: Preparado para renderizado masivo de sprites +## 🎨 Sistema de Transiciones LERP + +### **Problema Original** +El cambio de temas reiniciaba completamente la simulación: +- Llamaba a `initBalls()` regenerando todas las pelotas +- Perdía posiciones, velocidades y estado físico +- Cambio brusco e instantáneo +- Disruptivo para la experiencia visual + +### **Solución Implementada: Interpolación Lineal** +Transiciones suaves de colores sin afectar la física: + +```cpp +// Variables de transición +bool transitioning_ = false; +float transition_progress_ = 0.0f; // 0.0 a 1.0 +float transition_duration_ = 0.5f; // 0.5 segundos + +// Función LERP +float lerp(float a, float b, float t) { + return a + (b - a) * t; +} + +// Interpolación de colores +Color getInterpolatedColor(size_t ball_index) { + Color current = balls_[ball_index]->getColor(); + Color target = target_theme.ball_colors[ball_index % count]; + + return { + lerp(current.r, target.r, transition_progress_), + lerp(current.g, target.g, transition_progress_), + lerp(current.b, target.b, transition_progress_) + }; +} + +// En update() +if (transitioning_) { + transition_progress_ += delta_time / transition_duration_; + if (transition_progress_ >= 1.0f) { + // Finalizar transición, actualizar colores permanentes + for (size_t i = 0; i < balls_.size(); i++) { + balls_[i]->setColor(target_colors[i]); + } + transitioning_ = false; + } +} +``` + +### **Características del Sistema** +- **Interpolación frame-a-frame**: Colores RGB calculados en cada frame +- **Fondo degradado**: También interpola colores de vértices del fondo +- **Independiente del framerate**: Usa `delta_time` para duración precisa +- **Sin impacto físico**: Mantiene posiciones, velocidades y gravedad +- **Overhead mínimo**: <1ms adicional con 10,000 pelotas + +## 🔄 Sistema de Hot-Swap de Sprites + +### **Concepto** +Cambio dinámico de texturas sin reiniciar la simulación física. + +### **Desafío Técnico: Ajuste de Posiciones** +Cuando las pelotas están en reposo en superficies, cambiar el tamaño del hitbox causa problemas: + +**Caso 1: Grande → Pequeño (10px → 6px)** +- Pelota en suelo: `pos.y = screen_height - 10` +- Cambia a 6px: `pos.y = screen_height - 6` +- **Problema**: Queda flotando 4 píxeles arriba → Cae de nuevo ❌ + +**Caso 2: Pequeño → Grande (6px → 10px)** +- Pelota en suelo: `pos.y = screen_height - 6` +- Cambia a 10px: hitbox se entierra 4 píxeles +- **Problema**: Detección de colisión → Rebote violento hacia arriba ❌ + +### **Solución: Ajuste Inteligente de Posiciones** + +```cpp +void updateBallSizes(int old_size, int new_size) { + float delta_size = new_size - old_size; + + for (auto& ball : balls_) { + if (ball->isOnSurface()) { + // Solo ajustar pelotas en superficie + SDL_FRect pos = ball->getPosition(); + + switch (ball->getGravityDirection()) { + case DOWN: pos.y += delta_size; break; // Bajar si crece + case UP: pos.y -= delta_size; break; // Subir si crece + case LEFT: pos.x -= delta_size; break; + case RIGHT: pos.x += delta_size; break; + } + + ball->updateSize(new_size); + ball->setPosition(pos.x, pos.y); + } else { + // Pelotas en vuelo: solo actualizar tamaño + ball->updateSize(new_size); + } + } +} +``` + +### **Texturas Disponibles** +- **ball.png**: 10x10 píxeles (normal) +- **ball_small.png**: 6x6 píxeles (pequeño) + +### **Características** +- **Tamaño dinámico**: `current_ball_size_` obtenido de `texture->getWidth()` +- **Ajuste según gravedad**: Posición corregida según dirección gravitacional +- **Hot-swap completo**: Cambia textura, hitbox y clip del sprite +- **Sin reinicio físico**: Mantiene velocidades y trayectorias +- **Texto informativo**: Muestra "SPRITE: NORMAL" o "SPRITE: SMALL" + ## 🛠️ Desarrollo Para contribuir al proyecto: