Sergio Valor dcd05e502f Implementar cambio de sprite dinámico con hot-swap (Tecla N)
Sistema de múltiples texturas:
- Carga ball.png (10x10) y ball_small.png (6x6) al inicio
- Variable current_ball_size_ obtiene tamaño desde texture->getWidth()
- Eliminar constante BALL_SIZE hardcoded

Cambio de tamaño con ajuste de posiciones:
- updateBallSizes() ajusta pos según gravedad y superficie
- DOWN: mueve Y hacia abajo si crece
- UP: mueve Y hacia arriba si crece
- LEFT/RIGHT: mueve X correspondiente
- Solo ajusta pelotas en superficie (isOnSurface())

Ball class actualizada:
- Constructor recibe ball_size como parámetro
- updateSize(new_size): actualiza hitbox y sprite
- setTexture(texture): cambia textura del sprite
- setPosition() usa setRotoBallScreenPosition()

Sprite class:
- Añadido setTexture() inline para hot-swap

Tecla N:
- Cicla entre texturas disponibles
- Actualiza todas las pelotas sin reiniciar física
- Texto informativo "SPRITE: NORMAL" / "SPRITE: SMALL"

Fix bug initBalls():
- Ahora usa current_ball_size_ en constructor
- Pelotas nuevas tienen tamaño correcto según textura activa

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 08:08:00 +02:00
2025-10-03 13:45:55 +02:00

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)
KP_6 Tema MONOCHROME (fondo negro, sprites grises)
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

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 8 tonos de gris (blanco a oscuro)

Controles de Temas

  • 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
  • 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)

// 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)

# Usando vcpkg o compilar desde fuente
vcpkg install sdl3

Linux

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

macOS

brew install sdl3

🚀 Compilacion

Opcion 1: CMake (Recomendado)

mkdir build && cd build
cmake ..
make

Opcion 2: Make directo

make

▶️ Ejecucion

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

// 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:

// 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

// 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)

// 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/segundox60
  • Aceleracion: pixeles/frame² * frame²/segundo² = pixeles/segundo²x60²

3. Aplicacion de Delta Time en Fisica

// 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

// 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:

// 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.

Description
Simulador experimental de física avanzada con 100,000+ pelotas en tiempo real usando SDL3. Implementa delta time independiente del framerate, 5 temas visuales, zoom dinámico, fullscreen y gravedad multidireccional.
Readme 33 MiB
2025-10-25 11:05:33 +02:00
Languages
C 91.1%
C++ 8.7%
Makefile 0.2%