# 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**: 5 temas de colores con fondos degradados y paletas tematicas - **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 - **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 - **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** | | `F4` | **Toggle real fullscreen (resolucion nativa)** | ### 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)** | | `B` | **Ciclar entre todos los temas** | ### 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 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)** | | `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 **ViBe1 Delta** incluye 5 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 | ### Controles de Temas - **Seleccion directa**: Usa `KP_1`, `KP_2`, `KP_3`, `KP_4` o `KP_5` para cambiar inmediatamente 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 ### 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 - **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 #### 🌐 ESFERA (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) - **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) - **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 ### 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 de la pelota (10x10 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**: 640x360 pixeles (escalado x2 = 1280x720) - **Sistema de timing**: Delta time independiente del framerate - **Fisica**: Gravedad constante (0.2f), rebotes con perdida de energia - **Tamaño de pelota**: 10x10 pixeles - **V-Sync**: Activado por defecto, controlable dinamicamente ### 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 ## 🛠️ 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.*