Boids Fase 1: Corregir bug de clustering crítico

PROBLEMA RESUELTO:
Los boids colapsaban al mismo punto dentro de cada grupo, haciendo
el sistema visualmente inutilizable.

CAMBIOS IMPLEMENTADOS:

1. BOIDS_ROADMAP.md creado (NEW FILE)
   - Roadmap completo de 6 fases para mejora de boids
   - Diagnóstico detallado de problemas actuales
   - Plan de implementación con métricas de éxito
   - Fase 1 (crítica): Fix clustering
   - Fase 2 (alto impacto): Spatial Hash Grid O(n²)→O(n)
   - Fases 3-6: Mejoras visuales, comportamientos avanzados

2. defines.h - Rebalanceo de parámetros (Fase 1.1)
   - BOID_SEPARATION_RADIUS: 30→25px
   - BOID_COHESION_RADIUS: 80→60px (REDUCIDO 25%)
   - BOID_SEPARATION_WEIGHT: 1.5→3.0 (TRIPLICADO)
   - BOID_COHESION_WEIGHT: 0.8→0.5 (REDUCIDO 37%)
   - BOID_MAX_FORCE: 0.1→0.5 (QUINTUPLICADO)
   - BOID_MIN_SPEED: 0.5 (NUEVO - evita boids estáticos)

3. boid_manager.cpp - Mejoras físicas
   - Fase 1.2: Velocidad mínima en limitSpeed()
     * Evita boids completamente estáticos
     * Mantiene movimiento continuo
   - Fase 1.3: Fuerza de separación proporcional a cercanía
     * Antes: dividir por distance² (muy débil)
     * Ahora: proporcional a (RADIUS - distance) / RADIUS
     * Resultado: 100% fuerza en colisión, 0% en radio máximo

RESULTADO ESPERADO:
 Separación domina sobre cohesión (peso 3.0 vs 0.5)
 Boids mantienen distancia personal (~10-15px)
 Sin colapso a puntos únicos
 Movimiento continuo sin boids estáticos

PRÓXIMOS PASOS:
- Testing manual con 100, 1000 boids
- Validar comportamiento disperso sin clustering
- Fase 2: Spatial Hash Grid para rendimiento O(n)

Estado: Compilación exitosa, listo para testing
Rama: boids_development

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-11 22:04:20 +02:00
parent 1bb8807060
commit b73e77e9bc
3 changed files with 708 additions and 10 deletions

View File

@@ -141,9 +141,11 @@ void BoidManager::applySeparation(Ball* boid, float delta_time) {
float distance = std::sqrt(dx * dx + dy * dy);
if (distance > 0.0f && distance < BOID_SEPARATION_RADIUS) {
// Vector normalizado apuntando lejos del vecino, ponderado por cercanía
steer_x += (dx / distance) / distance;
steer_y += (dy / distance) / distance;
// FASE 1.3: Separación más fuerte cuando más cerca (inversamente proporcional a distancia)
// Fuerza proporcional a cercanía: 0% en radio máximo, 100% en colisión
float separation_strength = (BOID_SEPARATION_RADIUS - distance) / BOID_SEPARATION_RADIUS;
steer_x += (dx / distance) * separation_strength;
steer_y += (dy / distance) * separation_strength;
count++;
}
}
@@ -306,9 +308,18 @@ void BoidManager::limitSpeed(Ball* boid) {
boid->getVelocity(vx, vy);
float speed = std::sqrt(vx * vx + vy * vy);
// Limitar velocidad máxima
if (speed > BOID_MAX_SPEED) {
vx = (vx / speed) * BOID_MAX_SPEED;
vy = (vy / speed) * BOID_MAX_SPEED;
boid->setVelocity(vx, vy);
}
// FASE 1.2: Aplicar velocidad mínima (evitar boids estáticos)
if (speed > 0.0f && speed < BOID_MIN_SPEED) {
vx = (vx / speed) * BOID_MIN_SPEED;
vy = (vy / speed) * BOID_MIN_SPEED;
boid->setVelocity(vx, vy);
}
}

View File

@@ -289,14 +289,16 @@ constexpr float LOGO_FLIP_TRIGGER_MAX = 0.80f; // 80% máximo de progres
constexpr int LOGO_FLIP_WAIT_PROBABILITY = 50; // 50% probabilidad de elegir el camino "esperar flip"
// Configuración de Modo BOIDS (comportamiento de enjambre)
constexpr float BOID_SEPARATION_RADIUS = 30.0f; // Radio para evitar colisiones (píxeles)
constexpr float BOID_ALIGNMENT_RADIUS = 50.0f; // Radio para alinear velocidad con vecinos
constexpr float BOID_COHESION_RADIUS = 80.0f; // Radio para moverse hacia centro del grupo
constexpr float BOID_SEPARATION_WEIGHT = 1.5f; // Peso de separación (evitar colisiones)
constexpr float BOID_ALIGNMENT_WEIGHT = 1.0f; // Peso de alineación (seguir dirección del grupo)
constexpr float BOID_COHESION_WEIGHT = 0.8f; // Peso de cohesión (moverse al centro)
// FASE 1.1: Parámetros rebalanceados para evitar clustering
constexpr float BOID_SEPARATION_RADIUS = 25.0f; // Radio para evitar colisiones (píxeles)
constexpr float BOID_ALIGNMENT_RADIUS = 40.0f; // Radio para alinear velocidad con vecinos
constexpr float BOID_COHESION_RADIUS = 60.0f; // Radio para moverse hacia centro del grupo (REDUCIDO)
constexpr float BOID_SEPARATION_WEIGHT = 3.0f; // Peso de separación (TRIPLICADO - alta prioridad)
constexpr float BOID_ALIGNMENT_WEIGHT = 1.0f; // Peso de alineación (sin cambios)
constexpr float BOID_COHESION_WEIGHT = 0.5f; // Peso de cohesión (REDUCIDO a la mitad)
constexpr float BOID_MAX_SPEED = 3.0f; // Velocidad máxima (píxeles/frame)
constexpr float BOID_MAX_FORCE = 0.1f; // Fuerza máxima de steering
constexpr float BOID_MAX_FORCE = 0.5f; // Fuerza máxima de steering (QUINTUPLICADO)
constexpr float BOID_MIN_SPEED = 0.5f; // Velocidad mínima (NUEVO - evita boids estáticos)
constexpr float PI = 3.14159265358979323846f; // Constante PI