Files
vibe3_physics/README.md
Sergio Valor dec8d431f5 Implementar sistema de gravedad direccional con controles de cursor
- Añadir enum GravityDirection (UP/DOWN/LEFT/RIGHT) en defines.h
- Modificar Ball class para soportar gravedad multi-direccional
- Reescribir Ball::update() con lógica direccional completa
- Cambiar on_floor_ por on_surface_ (más genérico)
- Implementar detección de superficie según dirección de gravedad
- Añadir controles de teclado con teclas de cursor
- Actualizar debug display para mostrar dirección actual
- Aplicar fricción correctamente según superficie activa

Controles nuevos:
- ↑/↓/←/→: Cambiar dirección de gravedad
- H: Toggle debug display (incluye nueva info de gravedad)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 22:37:19 +02:00

358 lines
13 KiB
Markdown

# 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**: 4 temas de colores con fondos degradados y paletas tematicas
- **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
| Tecla | Accion |
|-------|--------|
| `H` | **Alternar debug display (FPS, V-Sync, valores fisica)** |
| `V` | **Alternar V-Sync ON/OFF** |
| `F1-F4` | **Seleccion directa de tema de colores (Atardecer/Oceano/Neon/Bosque)** |
| `T` | **Ciclar entre temas de colores** |
| `1-8` | Cambiar numero de pelotas (1, 10, 100, 500, 1K, 10K, 50K, 100K) |
| `ESPACIO` | Impulsar todas las pelotas hacia arriba |
| `G` | Alternar direccion de la gravedad |
| `ESC` | Salir del programa |
## 📊 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, FLOOR) en **magenta**
- **Linea 6**: Tema activo (THEME SUNSET/OCEAN/NEON/FOREST) en **amarillo claro**
## 🎨 Sistema de Temas de Colores
**ViBe1 Delta** incluye 4 temas visuales que transforman completamente la apariencia del simulador:
### Temas Disponibles
| Tecla | Tema | Descripcion | Fondo | Paleta de Pelotas |
|-------|------|-------------|-------|-------------------|
| `F1` | **ATARDECER** | Colores calidos de puesta de sol | Degradado naranja-rojo | Tonos naranjas, rojos y amarillos |
| `F2` | **OCEANO** | Ambiente marino refrescante | Degradado azul-cian | Azules, cianes y verdes agua |
| `F3` | **NEON** | Colores vibrantes futuristas | Degradado magenta-cian | Magentas, cianes y rosas brillantes |
| `F4` | **BOSQUE** | Naturaleza verde relajante | Degradado verde oscuro-claro | Verdes naturales y tierra |
### Controles de Temas
- **Seleccion directa**: Usa `F1`, `F2`, `F3` o `F4` para cambiar inmediatamente al tema deseado
- **Ciclado secuencial**: Presiona `T` 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)
## 🏗️ Estructura del Proyecto
```
vibe3_physics/
├── source/
│ ├── main.cpp # Bucle principal y logica del juego
│ ├── ball.h/cpp # Clase Ball - logica de las pelotas
│ ├── defines.h # Constantes y configuracion
│ └── 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**: 320x240 pixeles (escalado x3 = 960x720)
- **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
- FPS drops significativos con >10,000 pelotas
- Timing dependiente del framerate (solucion en desarrollo)
- Sin interpolacion en el renderizado
---
*Proyecto desarrollado como base para experimentacion con game loops y fisica en tiempo real usando SDL3.*