# ViBe3 Physics - Simulador de Sprites con Fisica

**ViBe3 Physics** es una demo experimental de **vibe-coding** que implementa **nuevas fisicas** expandiendo sobre el sistema de delta time. Utiliza **SDL3** para mostrar sprites (pelotas) rebotando con fisica avanzada independiente del framerate.

El nombre refleja su proposito: **ViBe** (vibe-coding experimental) + **Physics** (nuevas fisicas experimentales). La demo sirve como sandbox para probar bucles de juego con timing independiente y renderizado optimizado.

## 🎯 Caracteristicas Actuales

- **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**: 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 (mantiene aspecto), F4 para real fullscreen con resolucion nativa
- **Escalado configurable**: F5 alterna entre INTEGER (mantiene aspecto) y STRETCH (pantalla completa) en modo F3
- **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-24 colores por tema aplicadas proceduralmente
- **Monitor de rendimiento**: Contador FPS en tiempo real
- **Control V-Sync**: Activacion/desactivacion dinamica del V-Sync

## 🎮 Controles

### Controles de Sistema
| Tecla | Accion |
|-------|--------|
| `H` | **Alternar debug display (FPS, V-Sync, valores fisica)** |
| `V` | **Alternar V-Sync ON/OFF** |
| `ESC` | Salir del programa |

### Controles de Ventana
| Tecla | Accion |
|-------|--------|
| `F1` | **Zoom out (reducir zoom ventana)** |
| `F2` | **Zoom in (aumentar zoom ventana)** |
| `F3` | **Toggle fullscreen normal (mantiene aspecto)** |
| `F4` | **Toggle real fullscreen (resolucion nativa)** |
| `F5` | **Toggle escalado INTEGER/STRETCH (solo en modo F3)** |

### Controles de Temas
| Tecla | Accion |
|-------|--------|
| `KP_1` | **Tema ATARDECER (colores calidos)** |
| `KP_2` | **Tema OCEANO (azules y cianes)** |
| `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, todas las pelotas blancas)** |
| `B` | **Ciclar entre todos los temas** |
| `N` | **Cambiar sprite (ball.png ↔ ball_small.png)** |

### Controles de Simulacion
| Tecla | Accion |
|-------|--------|
| `1-8` | Cambiar numero de pelotas (1, 10, 100, 500, 1K, 10K, 50K, 100K) |
| `ESPACIO` | Impulsar todas las pelotas hacia arriba |
| `↑` | **Gravedad hacia ARRIBA (sale de figura con gravedad)** |
| `↓` | **Gravedad hacia ABAJO (sale de figura con gravedad)** |
| `←` | **Gravedad hacia IZQUIERDA (sale de figura con gravedad)** |
| `→` | **Gravedad hacia DERECHA (sale de figura con gravedad)** |
| `G` | **Alternar gravedad ON/OFF / Sale de figura SIN gravedad** |

### Controles de Figuras 3D
| Tecla | Accion |
|-------|--------|
| `F` | **Toggle entre modo FISICA ↔ última FIGURA 3D** |
| `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%** |
| `KP_/` | **Toggle zoom por profundidad Z (perspectiva ON/OFF)** |

## 📊 Informacion en Pantalla

- **Centro**: Numero de pelotas activas en **blanco** (temporal)
- **Centro**: Nombre del tema activo en **color tematico** (temporal, debajo del contador)

### Debug Display (Tecla `H`)

Cuando se activa el debug display con la tecla `H`:

- **Esquina superior izquierda**: Estado V-Sync (VSYNC ON/OFF) en **cian**
- **Esquina superior derecha**: Contador FPS en tiempo real en **amarillo**
- **Lineas 3-5**: Valores fisica primera pelota (GRAV, VY, SURFACE, LOSS) en **magenta**
- **Linea 6**: Dirección de gravedad actual (GRAVITY UP/DOWN/LEFT/RIGHT) en **amarillo**
- **Linea 7**: Tema activo (THEME SUNSET/OCEAN/NEON/FOREST/RGB) en **amarillo claro**
- **Linea 8**: Modo de simulación (MODE PHYSICS/SPHERE/CUBE/etc.) en **verde claro**

## 🎨 Sistema de Temas de Colores

**ViBe3 Physics** incluye 6 temas visuales que transforman completamente la apariencia del simulador:

### Temas Disponibles

| Tecla | Tema | Descripcion | Fondo | Paleta de Pelotas |
|-------|------|-------------|-------|-------------------|
| `KP_1` | **ATARDECER** | Colores calidos de puesta de sol | Degradado naranja-rojo | Tonos naranjas, rojos y amarillos |
| `KP_2` | **OCEANO** | Ambiente marino refrescante | Degradado azul-cian | Azules, cianes y verdes agua |
| `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 | Todas las pelotas blancas puras |

### Controles de Temas

- **Seleccion directa**: Usa `KP_1` a `KP_6` para cambiar al tema deseado
- **Ciclado secuencial**: Presiona `B` para avanzar al siguiente tema en orden
- **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-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 (8/8 Completas)

#### 🌐 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

#### 🌊 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: 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

#### 🏛️ 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

- **Física de atracción**: Sistema spring-damper (Hooke's Law) para transición suave
- **Profundidad Z simulada**: Color modulado según distancia (oscuro=fondo, brillante=frente)
- **Zoom por profundidad**: Perspectiva 3D con escala variable (50%-150% según Z)
- **Z-sorting**: Painter's Algorithm para oclusión correcta
- **Escala dinámica**: Control manual con Numpad +/- (30% - 300%)
- **Protección de clipping**: Escala limitada automáticamente según resolución
- **Sin sprites adicionales**: Usa `SDL_SetTextureColorMod` y vértices escalados para efectos 3D

### Parámetros Físicos (defines.h)

```cpp
// Física compartida entre todas las figuras
ROTOBALL_SPRING_K = 300.0f;        // Rigidez del resorte (N/m)
ROTOBALL_DAMPING_BASE = 35.0f;     // Amortiguación crítica
ROTOBALL_DAMPING_NEAR = 80.0f;     // Absorción cerca del punto

// Esfera
ROTOBALL_RADIUS_FACTOR = 0.333f;   // 33% de altura de pantalla
ROTOBALL_ROTATION_SPEED_Y = 1.5f;  // rad/s (eje Y)
ROTOBALL_ROTATION_SPEED_X = 0.8f;  // rad/s (eje X)

// Cubo
CUBE_SIZE_FACTOR = 0.25f;          // 25% de altura de pantalla
CUBE_ROTATION_SPEED_X = 0.5f;      // rad/s
CUBE_ROTATION_SPEED_Y = 0.7f;      // rad/s
CUBE_ROTATION_SPEED_Z = 0.3f;      // rad/s

// Control manual de escala
SHAPE_SCALE_MIN = 0.3f;            // Mínimo 30%
SHAPE_SCALE_MAX = 3.0f;            // Máximo 300%
SHAPE_SCALE_STEP = 0.1f;           // Incremento 10%
```

### Cómo Funciona

1. **Generación**: Algoritmo específico distribuye puntos en forma 3D
2. **Rotación**: Matrices de rotación 3D aplicadas en tiempo real
3. **Escala**: Factor manual multiplicado a coordenadas y física
4. **Proyección**: Coordenadas 3D → 2D (ortográfica)
5. **Z-sorting**: Ordenar pelotas por profundidad (fondo primero)
6. **Profundidad**: Componente Z controla brillo del color
7. **Renderizado**: Batch rendering con color modulado

### Uso

- **Activación**: Presiona Q/W/E/R/T/Y/U/I para figura específica, o F para toggle
- **Escala**: Usa Numpad +/- para ajustar tamaño, * para reset
- **Perspectiva**: Numpad / para activar/desactivar zoom por profundidad (ON por defecto)
- **Salir**: G (sin gravedad), cursores (con gravedad), F (toggle), o 1-8 (cambiar escenario)
- **Compatible**: Funciona con 1-100,000 pelotas
- **Temas**: Mantiene paleta de colores activa

## 🏗️ Estructura del Proyecto

```
vibe3_physics/
├── source/
│   ├── main.cpp            # Bucle principal y logica del juego
│   ├── engine.h/cpp        # Motor principal con loop y rendering
│   ├── ball.h/cpp          # Clase Ball - fisica de pelotas
│   ├── defines.h           # Constantes y configuracion
│   ├── shapes/             # Sistema polimorfico de figuras 3D
│   │   ├── shape.h             # Interfaz abstracta Shape
│   │   ├── sphere_shape.h/cpp  # Fibonacci Sphere
│   │   └── cube_shape.h/cpp    # Cubo rotante triple
│   └── external/           # Utilidades y bibliotecas externas
│       ├── sprite.h/cpp        # Clase Sprite - renderizado de texturas
│       ├── texture.h/cpp       # Clase Texture - gestion de imagenes
│       ├── dbgtxt.h            # Sistema de debug para texto en pantalla
│       └── stb_image.h         # Biblioteca para cargar imagenes
├── data/
│   ├── 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
└── .gitignore              # Archivos ignorados por Git
```

## 🔧 Requisitos del Sistema

- **SDL3** (Simple DirectMedia Layer 3)
- **C++20** compatible compiler
- **CMake 3.20+** o **Make**
- Plataforma: Windows, Linux, macOS

### Instalacion de SDL3

#### Windows (MinGW)
```bash
# Usando vcpkg o compilar desde fuente
vcpkg install sdl3
```

#### Linux
```bash
# Ubuntu/Debian
sudo apt install libsdl3-dev
# Arch Linux
sudo pacman -S sdl3
```

#### macOS
```bash
brew install sdl3
```

## 🚀 Compilacion

### Opcion 1: CMake (Recomendado)
```bash
mkdir build && cd build
cmake ..
make
```

### Opcion 2: Make directo
```bash
make
```

## ▶️ Ejecucion

```bash
# Desde la raiz del proyecto
./vibe3_physics        # Linux/macOS
./vibe3_physics.exe    # Windows
```

## 📊 Detalles Tecnicos

### Configuracion Actual
- **Resolucion**: 320x240 pixeles (escalado x3 = 960x720 por defecto)
- **Sistema de timing**: Delta time independiente del framerate
- **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

1. **main.cpp**: Contiene el bucle principal con cuatro fases:
   - `calculateDeltaTime()`: Calcula tiempo transcurrido entre frames
   - `update()`: Actualiza la logica del juego usando delta time + calculo FPS
   - `checkEvents()`: Procesa eventos de entrada
   - `render()`: Renderiza la escena + overlays informativos

2. **Ball**: Maneja la fisica de cada pelota individual con timing basado en delta time
3. **Sprite**: Sistema de renderizado de texturas con filtro nearest neighbor
4. **Texture**: Gestion de carga y renderizado de imagenes con filtro pixel-perfect

## ✅ Migracion a Delta Time (COMPLETADO)

### Sistema Anterior (Frame-Based)

El sistema original estaba **acoplado a 60 FPS** con logica dependiente del framerate:

```cpp
// Sistema ANTIGUO en update()
if (SDL_GetTicks() - ticks > DEMO_SPEED) { // DEMO_SPEED = 1000/60 = 16.67ms
    // Solo aqui se actualizaba la fisica cada 16.67ms
    for (auto &ball : balls) {
        ball->update(); // Sin parametros de tiempo
    }
    ticks = SDL_GetTicks();
}
```

**Problemas del sistema anterior:**
- Velocidad inconsistente entre diferentes refresh rates (60Hz vs 75Hz vs 144Hz)
- Logica de fisica acoplada a framerate fijo
- V-Sync ON/OFF cambiaba la velocidad del juego
- Rendimiento inconsistente en diferentes hardware

### Sistema Actual (Delta Time)

**Implementacion delta time** para simulacion independiente del framerate:

```cpp
// Sistema NUEVO - Variables globales
Uint64 last_frame_time = 0;
float delta_time = 0.0f;

// Calculo de delta time
void calculateDeltaTime() {
    Uint64 current_time = SDL_GetTicks();
    if (last_frame_time == 0) {
        last_frame_time = current_time;
        delta_time = 1.0f / 60.0f; // Primer frame a 60 FPS
        return;
    }

    delta_time = (current_time - last_frame_time) / 1000.0f; // Convertir a segundos
    last_frame_time = current_time;

    // Limitar delta time para evitar saltos grandes
    if (delta_time > 0.05f) {
        delta_time = 1.0f / 60.0f; // Fallback a 60 FPS
    }
}

// Bucle principal actualizado
while (!should_exit) {
    calculateDeltaTime();  // 1. Calcular tiempo transcurrido
    update();             // 2. Actualizar logica (usa delta_time)
    checkEvents();        // 3. Procesar entrada
    render();            // 4. Renderizar escena
}
```

### Conversion de Fisica: Frame-Based → Time-Based

#### 1. Conversion de Velocidades

```cpp
// En Ball::Ball() constructor
// ANTES: velocidades en pixeles/frame
vx_ = vx;
vy_ = vy;

// AHORA: convertir a pixeles/segundo (x60)
vx_ = vx * 60.0f;
vy_ = vy * 60.0f;
```

#### 2. Conversion de Gravedad (Aceleracion)

```cpp
// En Ball::Ball() constructor
// ANTES: gravedad en pixeles/frame²
gravity_force_ = GRAVITY_FORCE;

// AHORA: convertir a pixeles/segundo² (x60²)
gravity_force_ = GRAVITY_FORCE * 60.0f * 60.0f; // 3600x multiplicador
```

**¿Por que 60² para gravedad?**
- Velocidad: `pixeles/frame * frame/segundo = pixeles/segundo` → **x60**
- Aceleracion: `pixeles/frame² * frame²/segundo² = pixeles/segundo²` → **x60²**

#### 3. Aplicacion de Delta Time en Fisica

```cpp
// En Ball::update(float deltaTime)
// ANTES: incrementos fijos por frame
vy_ += gravity_force_;
pos_.x += vx_;
pos_.y += vy_;

// AHORA: incrementos proporcionales al tiempo transcurrido
vy_ += gravity_force_ * deltaTime;  // Aceleracion * tiempo
pos_.x += vx_ * deltaTime;         // Velocidad * tiempo
pos_.y += vy_ * deltaTime;
```

### Valores de Debug: Antes vs Ahora

| Parametro | Sistema Anterior | Sistema Delta Time | Razon |
|-----------|------------------|-------------------|-------|
| **Velocidad X/Y** | 1.0 - 3.0 pixeles/frame | 60.0 - 180.0 pixeles/segundo | x60 conversion |
| **Gravedad** | 0.2 pixeles/frame² | 720.0 pixeles/segundo² | x3600 conversion |
| **Debug Display** | No disponible | GRAV: 720.000000 VY: -140.5 FLOOR: NO | Valores en tiempo real |

### Beneficios Conseguidos

- ✅ **Velocidad consistente** entre 60Hz, 75Hz, 144Hz y otros refresh rates
- ✅ **V-Sync independiente**: misma velocidad con V-Sync ON/OFF
- ✅ **Fisica precisa**: gravedad y movimiento calculados correctamente
- ✅ **Escalabilidad**: preparado para futuras optimizaciones
- ✅ **Debug en tiempo real**: monitoreo de valores de fisica

### Sistema de Debug Implementado

```cpp
// Debug display para primera pelota
if (!balls.empty()) {
    std::string debug_text = "GRAV: " + std::to_string(balls[0]->getGravityForce()) +
                           " VY: " + std::to_string(balls[0]->getVelocityY()) +
                           " FLOOR: " + (balls[0]->isOnFloor() ? "YES" : "NO");
    dbg_print(8, 24, debug_text.c_str(), 255, 0, 255); // Magenta
}
```

## 🚀 Sistema de Batch Rendering

### **Problema Original**
El renderizado individual de sprites era el principal cuello de botella:
- **50,000 bolas**: 50,000 llamadas `SDL_RenderTexture()` por frame
- **Resultado**: ~10 FPS (inutilizable)

### **Solución Implementada: SDL_RenderGeometry**
Batch rendering que agrupa todos los sprites en una sola llamada:

```cpp
// Recopilar datos de todas las bolas
for (auto &ball : balls) {
    SDL_FRect pos = ball->getPosition();
    Color color = ball->getColor();
    addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b);
}

// Renderizar TODAS las bolas en una sola llamada
SDL_RenderGeometry(renderer, texture->getSDLTexture(),
                   batch_vertices.data(), batch_vertices.size(),
                   batch_indices.data(), batch_indices.size());
```

### **Arquitectura del Batch**
1. **Vértices**: 4 vértices por sprite (quad) con posición, UV y color
2. **Índices**: 6 índices por sprite (2 triángulos)
3. **Acumulación**: Todos los sprites se acumulan en vectores globales
4. **Renderizado**: Una sola llamada `SDL_RenderGeometry` por frame

### **Rendimiento Conseguido**
- **50,000 bolas**: >75 FPS constante (mejora de 750%)
- **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:

1. Fork del repositorio
2. Crear rama de feature (`git checkout -b feature/nueva-caracteristica`)
3. Commit de cambios (`git commit -am 'Añadir nueva caracteristica'`)
4. Push a la rama (`git push origin feature/nueva-caracteristica`)
5. Crear Pull Request

## 📝 Notas Tecnicas

- El proyecto usa **smart pointers** (unique_ptr, shared_ptr) para gestion de memoria
- **RAII** para recursos SDL
- **Separacion de responsabilidades** entre clases
- **Configuracion multiplataforma** (Windows, Linux, macOS)
- **Filtro nearest neighbor** para texturas pixel-perfect
- **Sistema de metricas** en tiempo real (FPS, V-Sync)

## 🐛 Problemas Conocidos

Ninguno conocido. El sistema esta completamente funcional con delta time implementado.

---

*Proyecto desarrollado como base para experimentacion con game loops y fisica en tiempo real usando SDL3.*