Commit Graph

67 Commits

Author SHA1 Message Date
355fa4ffb7 Ajustar amortiguación para absorción rápida sin oscilación
Incrementar constantes de damping para lograr amortiguamiento crítico
y eliminar oscilaciones durante la convergencia a la esfera RotoBall.

## Cambios

**defines.h - Nuevos valores:**
- `ROTOBALL_DAMPING_BASE`: 15.0 → 35.0 (+133%)
  - Amortiguamiento crítico calculado: c ≈ 2*√(k*m) = 2*√(300*1) ≈ 34.64
- `ROTOBALL_DAMPING_NEAR`: 50.0 → 80.0 (+60%)
  - Absorción rápida cuando están cerca del punto

## Problema Resuelto

**Antes (subdamped):**
- Las pelotas oscilaban varias veces antes de estabilizarse
- Sobrepasaban el punto destino repetidamente
- Convergencia lenta con "rebotes" visuales

**Ahora (critically damped):**
- Las pelotas convergen directamente sin oscilar
- Se "pegan" suavemente a la esfera
- Absorción rápida y visualmente limpia

## Teoría

Sistema masa-resorte-amortiguador:
- Subdamped (c < 2√km): Oscila antes de estabilizar
- Critically damped (c = 2√km): Converge rápido sin oscilar
- Overdamped (c > 2√km): Converge muy lento

Valores ajustados para estar en el punto crítico, logrando
la convergencia más rápida posible sin oscilación.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 13:27:26 +02:00
91ab6487b3 Implementar física de atracción con resorte en RotoBall
Reemplazar interpolación lineal artificial por sistema de fuerzas físicamente
realista usando Ley de Hooke con amortiguación variable.

## Cambios Principales

### Sistema de Física Implementado

**Fuerza de Resorte (Hooke's Law):**
```cpp
F_spring = k * (target - position)
F_damping = c * velocity
F_total = F_spring - F_damping
acceleration = F_total / mass
```

**Constantes (defines.h):**
- `ROTOBALL_SPRING_K = 300.0f`: Rigidez del resorte
- `ROTOBALL_DAMPING_BASE = 15.0f`: Amortiguación lejos del punto
- `ROTOBALL_DAMPING_NEAR = 50.0f`: Amortiguación cerca (estabilización)
- `ROTOBALL_NEAR_THRESHOLD = 5.0f`: Distancia considerada "cerca"
- `ROTOBALL_MAX_FORCE = 1000.0f`: Límite de seguridad

### Nuevas Funciones (Ball class)

- `enableRotoBallAttraction(bool)`: Activa/desactiva atracción física
- `applyRotoBallForce(target_x, target_y, deltaTime)`: Aplica fuerza de resorte

### Comportamiento Físico

**Al entrar (PHYSICS → ROTOBALL):**
1. Pelotas mantienen velocidad actual (vx, vy)
2. Fuerza de atracción las acelera hacia puntos en esfera rotante
3. Amortiguación variable evita oscilaciones infinitas
4. Convergen al punto con aceleración natural

**Durante RotoBall:**
- Punto destino rota constantemente
- Fuerza se recalcula cada frame hacia posición rotada
- Pelotas "persiguen" su punto móvil
- Efecto: Convergencia orgánica con ligera oscilación

**Al salir (ROTOBALL → PHYSICS):**
1. Atracción se desactiva
2. Pelotas conservan velocidad tangencial actual
3. Gravedad vuelve a aplicarse
4. Caen con la inercia que traían de la esfera

### Archivos Modificados

- `defines.h`: 5 nuevas constantes físicas
- `ball.h/cpp`: Sistema de resorte completo
- `engine.cpp`: Enable/disable atracción en toggle, updateRotoBall() usa física
- `CLAUDE.md`: Documentación técnica completa

## Ventajas del Sistema

 Física realista con conservación de momento
 Transición orgánica (no artificial)
 Inercia preservada entrada/salida
 Amortiguación automática (no oscila infinito)
 Constantes ajustables para tuning
 Performance: O(1) por pelota

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 13:24:07 +02:00
22e3356f80 Implementar modo RotoBall - Esfera 3D rotante (demoscene effect)
Añadido modo alternativo de simulación que transforma las pelotas en una
esfera 3D rotante proyectada en 2D, inspirado en efectos clásicos de demoscene.

## Características Principales

- **Algoritmo Fibonacci Sphere**: Distribución uniforme de puntos en esfera 3D
- **Rotación dual**: Matrices de rotación en ejes X e Y simultáneos
- **Profundidad Z simulada**: Color modulation según distancia (oscuro=lejos, brillante=cerca)
- **Transición suave**: Interpolación de 1.5s desde física a esfera
- **Sin sprites adicionales**: Usa SDL_SetTextureColorMod para profundidad
- **Performance optimizado**: >60 FPS con 100,000 pelotas

## Implementación Técnica

### Nuevos Archivos/Cambios:
- `defines.h`: Enum SimulationMode + constantes RotoBall (radio, velocidades, brillo)
- `ball.h/cpp`: Soporte 3D (pos_3d, target_2d, depth_brightness, setters)
- `engine.h/cpp`: Lógica completa RotoBall (generate, update, toggle)
  - `generateRotoBallSphere()`: Fibonacci sphere algorithm
  - `updateRotoBall()`: Rotación 3D + proyección ortográfica
  - `toggleRotoBallMode()`: Cambio entre PHYSICS/ROTOBALL
- `README.md`: Documentación completa del modo
- `CLAUDE.md`: Detalles técnicos y algoritmos

## Parámetros Configurables (defines.h)

```cpp
ROTOBALL_RADIUS = 80.0f;           // Radio de la esfera
ROTOBALL_ROTATION_SPEED_Y = 1.5f;  // Velocidad rotación eje Y (rad/s)
ROTOBALL_ROTATION_SPEED_X = 0.8f;  // Velocidad rotación eje X (rad/s)
ROTOBALL_TRANSITION_TIME = 1.5f;   // Tiempo de transición (segundos)
ROTOBALL_MIN_BRIGHTNESS = 50;      // Brillo mínimo fondo (0-255)
ROTOBALL_MAX_BRIGHTNESS = 255;     // Brillo máximo frente (0-255)
```

## Uso

- **Tecla C**: Alternar entre modo física y modo RotoBall
- Compatible con todos los temas de colores
- Funciona con 1-100,000 pelotas
- Debug display muestra "MODE PHYSICS" o "MODE ROTOBALL"

## Performance

- Batch rendering: Una sola llamada SDL_RenderGeometry
- Fibonacci sphere recalculada por frame (O(n) predecible)
- Color mod CPU-side sin overhead GPU
- Delta time independiente del framerate

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 13:03:03 +02:00
79964732ef Implementar sistema de auto-reinicio con temporizador de inactividad
- Añadir getter isStopped() en Ball para detectar pelotas quietas
- Sistema de temporizador de 5 segundos que detecta cuando todas las pelotas están paradas
- Auto-reinicio aleatorio cuando se cumple el tiempo de inactividad:
  * Escenario aleatorio usando test_.size() (1 a 100,000 pelotas)
  * Tema aleatorio usando sizeof(themes_) (5 temas disponibles)
  * Reset inteligente del temporizador si alguna pelota se mueve
- Integración no intrusiva en update() del bucle principal
- Usa infraestructura existente (SDL_GetTicks, initBalls, rand)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 22:21:30 +02:00
7ac29f899b Implementar impulso direccional adaptativo para tecla ESPACIO
- Renombrar pushUpBalls() → pushBallsAwayFromGravity() con lógica direccional
- ESPACIO ahora impulsa en dirección opuesta a gravedad actual:
  * Gravedad DOWN → impulsa ARRIBA (comportamiento original)
  * Gravedad UP → impulsa ABAJO
  * Gravedad LEFT → impulsa DERECHA
  * Gravedad RIGHT → impulsa IZQUIERDA
- Corregir modVel() para aplicar impulso horizontal a todas las pelotas
- Actualizar documentación de controles en README.md

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 22:10:33 +02:00
4e030e4ef9 Implementar sistema flexible de temas con cantidad variable de colores
- Refactorizar ThemeColors para usar std::vector<Color> en lugar de array fijo
- Cada tema puede tener cualquier cantidad de colores (8, 12, 24, etc.)
- Expandir tema RGB a 24 colores del círculo cromático (cada 15°)
- Añadir función initializeThemes() para configuración dinámica
- Mantener temas originales con 8 colores cada uno
- Tema RGB ahora incluye transiciones suaves por todo el espectro

Paleta RGB matemáticamente perfecta:
- 6 colores primarios: R, Y, G, C, B, M (cada 60°)
- 18 colores intermedios: transiciones cada 15°
- Cobertura completa del círculo cromático 0°-345°

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 22:22:57 +02:00
ac57755bd2 Añadir tema RGB y actualizar documentación completa
- Añadido nuevo tema RGB con fondo blanco puro y colores matemáticos
- Actualizado README.md con controles actuales y nuevas características
- Reorganizada documentación de controles por categorías
- Corregida información obsoleta (resolución, temas, problemas)
- Añadido control KP_5 para selección directa del tema RGB
- Mejorada visibilidad del texto adaptando colores por tema

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 22:08:28 +02:00
7b24e387b7 Implementar modo real fullscreen y resolver conflictos
MODO REAL FULLSCREEN (F4):
- F4: Cambia resolución interna a resolución nativa del escritorio
- Pelotas usan dimensiones dinámicas del terreno de juego
- Interfaz se adapta automáticamente (texto, debug, gradiente)
- Reinicio automático de escena con nuevas dimensiones

RESOLUCIÓN DINÁMICA:
- Ball constructor acepta screen_width/height como parámetros
- Colisiones usan dimensiones dinámicas en lugar de constantes
- Spawn de pelotas usa margen configurable (BALL_SPAWN_MARGIN)
- Toda la interfaz se adapta a resolución actual

MODOS FULLSCREEN MUTUAMENTE EXCLUYENTES:
- F3 (fullscreen normal) y F4 (real fullscreen) se desactivan mutuamente
- F1/F2 (zoom) bloqueados durante cualquier modo fullscreen
- Sin estados mixtos que rompan el renderizado
- Transiciones seguras entre todos los modos

MEJORAS DE CONFIGURACIÓN:
- BALL_SPAWN_MARGIN: margen lateral configurable para spawn de pelotas
- Resolución base actualizada a 640x360 (16:9)
- Spawn margin reducido a 15% para mayor dispersión

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 19:20:02 +02:00
9908165104 Agregar comentarios descriptivos a defines.h
- Comentar todas las constantes, structs y enums
- Organizar en secciones: ventana, zoom, física, interfaz, rebotes, masa
- Documentar valores y unidades (píxeles, ms, factores)
- Explicar propósito de cada tema de colores

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 18:49:33 +02:00
8a05f69442 Implementar sistema de zoom dinámico y fullscreen
- Agregar zoom dinámico de ventana con F1/F2
- F1: reducir zoom hasta 1x mínimo
- F2: aumentar zoom hasta máximo basado en resolución
- Centrado inteligente al cambiar zoom
- Cálculo correcto de zoom máximo usando SDL_GetCurrentDisplayMode()
- F3: toggle fullscreen entre ventana y pantalla completa
- Mover temas de colores de F1-F4 a teclado numérico (KP_1-4)
- Mejorar resolución base a 640x480 con zoom inicial 2x
- Resolver paths absolutos para data/ball.png

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 18:48:12 +02:00
036268f135 Implementar empuje lateral sutil al cambiar gravedad
🎯 Problema solucionado:
- Pelotas se movían en líneas perfectas al cambiar gravedad
- Todas llegaban exactamente una encima de otra

 Solución implementada:
- Empuje lateral aleatorio muy sutil (2.4-4.8 px/s)
- Se aplica automáticamente al cambiar dirección de gravedad
- Perpendicular a la gravedad: UP/DOWN → empuje X, LEFT/RIGHT → empuje Y

🔧 Implementación técnica:
- Nueva función Ball::applyRandomLateralPush()
- Integrada en Engine::changeGravityDirection()
- Velocidades ajustadas para ser apenas perceptibles

📊 Valores finales:
- GRAVITY_CHANGE_LATERAL_MIN = 0.04f (2.4 px/s)
- GRAVITY_CHANGE_LATERAL_MAX = 0.08f (4.8 px/s)
- Rango: ~3-5 píxeles en 1 segundo (muy sutil)

🎮 Resultado:
- Rompe la simetría perfecta sin crear caos
- Movimiento más natural y orgánico
- Mantiene la física realista

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 18:06:19 +02:00
a798811d23 Implementar sistema de masa/peso individual por pelota
 Nueva característica:
- Cada pelota tiene un factor de masa único que afecta la gravedad
- Simula pelotas de diferente peso/densidad para física más realista

🔧 Implementación:
- GRAVITY_MASS_MIN = 0.7f (pelotas ligeras - 70% gravedad)
- GRAVITY_MASS_MAX = 1.3f (pelotas pesadas - 130% gravedad)
- Factor aleatorio generado por pelota en initBalls()
- Gravedad efectiva = gravity_force × mass_factor × deltaTime

📊 Comportamiento:
- Pelotas ligeras (0.7): Caen 30% más lento, efecto "flotante"
- Pelotas pesadas (1.3): Caen 30% más rápido, más "densas"
- Variabilidad continua entre 0.7-1.3 para cada pelota

🎯 Resultado visual:
- FIN del problema: "todas llegan al mismo tiempo"
- Ahora las pelotas llegan escalonadas al cambiar gravedad
- Física más realista y visualmente interesante

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 17:52:31 +02:00
e15c1f5349 Corregir física de rebotes: solo pérdida, nunca ganancia de energía
🔧 Problema corregido:
- BOUNCE_VARIATION_PERCENT permitía rebotes con ganancia de energía (0.95-1.05)
- Pelotas podían rebotar más alto que su posición inicial (violaba física)

 Cambios aplicados:
- Renombrado: BOUNCE_VARIATION_PERCENT → BOUNCE_RANDOM_LOSS_PERCENT
- Valor aumentado: 0.05f (5%) → 0.1f (10%) para mayor variabilidad
- Lógica corregida: rango 0.90-1.00 (solo pérdida, nunca ganancia)
- Comentarios actualizados para claridad semántica

📊 Impacto físico:
- Antes: 0.75 × (0.95-1.05) = 0.7125-0.7875  (ganancia posible)
- Después: 0.75 × (0.90-1.00) = 0.675-0.750  (solo pérdida)

🎯 Resultado: Física realista - las pelotas siempre pierden energía en rebotes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 17:46:07 +02:00
19e1c414c2 Refactoring completo: migrar main.cpp a Engine class
 Características principales:
- Encapsulación completa de variables globales en Engine class
- main.cpp simplificado: 580+ líneas → 15 líneas
- Eliminados problemas de orden de declaración de funciones

🔧 Correcciones aplicadas:
- Colores degradado SUNSET restaurados al original
- Inicialización pelotas: velocidad lateral y posición corregidas
- Textos en MAYÚSCULAS con singular/plural correcto ("1 PELOTA"/"X PELOTAS")
- Uso correcto de changeGravityDirection() para reset de gravedad
- Funciones dbgtxt marcadas como inline para evitar múltiples definiciones

📁 Estructura final:
- engine.h/cpp: Clase Engine con toda la lógica encapsulada
- main.cpp: Interfaz mínima con Engine
- main_old.cpp: Eliminado (ya no necesario)
- CMakeLists.txt: Actualizado para excluir archivos obsoletos

🧪 Testing: Compilación exitosa, funcionalidad restaurada completamente

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 17:33:53 +02:00
cada46f732 Refactorización inicial: Crear estructura de clase Engine
PROGRESO INTERMEDIO - Estructura base de Engine implementada:

Nuevos archivos:
- engine.h: Declaración completa de clase Engine con encapsulación
- engine.cpp: Esqueleto de implementación con métodos stub
- main_new.cpp: Nuevo main simplificado (15 líneas vs 580)

Cambios en archivos existentes:
- defines.h: Añadir enum ColorTheme (centralizar definiciones)
- main.cpp: Eliminar enum ColorTheme duplicado

Arquitectura Engine:
- Encapsulación completa de variables globales (SDL, estado, timing, UI)
- Métodos organizados por responsabilidad (public/private)
- Eliminación de problemas de orden de declaración
- Base sólida para futuras extensiones

Estado: Compilación exitosa 
Pendiente: Migrar funcionalidad completa de métodos stub

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 17:09:42 +02:00
78656cf17d Implementar sistema de variación por rebote individual
- Corregir coeficiente base: ahora TODAS las pelotas tienen el mismo (0.75)
- Añadir constantes configurables en defines.h:
  * BASE_BOUNCE_COEFFICIENT = 0.75f (igual para todas)
  * BOUNCE_VARIATION_PERCENT = 0.05f (±5% por rebote)
  * LATERAL_LOSS_PERCENT = 0.02f (±2% pérdida lateral)
- Implementar funciones generateBounceVariation() y generateLateralLoss()
- Aplicar variación aleatoria en cada rebote individual:
  * Superficie de gravedad: rebote con ±5% variación
  * Otras superficies: pérdida lateral 0-2%
- Añadir pérdida lateral perpendicular en todos los rebotes
- Actualizar debug display para mostrar coeficiente LOSS

Efecto: Pelotas idénticas divergen gradualmente por variaciones microscópicas
acumulativas, eliminando sincronización de forma natural y realista.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 16:52:24 +02:00
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