From 0873d80765bee433455c7cdde3132429b4d3ffb0 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sat, 11 Oct 2025 22:13:40 +0200 Subject: [PATCH] =?UTF-8?q?Boids=20Fase=201.4:=20FIX=20CR=C3=8DTICO=20-=20?= =?UTF-8?q?Normalizar=20fuerza=20de=20cohesi=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG CRÍTICO ENCONTRADO: La fuerza de cohesión NO estaba normalizada, causando atracción tipo "gravedad" que hacía que los boids colapsaran a puntos. CAUSA RAÍZ: ```cpp // ANTES (INCORRECTO): float steer_x = (center_of_mass_x - center_x) * WEIGHT * delta_time; // Si center_of_mass está a 100px → fuerza = 100 * 0.5 * 0.016 = 0.8 // ¡FUERZA PROPORCIONAL A DISTANCIA! Como una gravedad newtoniana ``` SOLUCIÓN IMPLEMENTADA: ```cpp // DESPUÉS (CORRECTO): float distance = sqrt(dx*dx + dy*dy); float steer_x = (dx / distance) * WEIGHT * delta_time; // Fuerza siempre normalizada = 1.0 * WEIGHT * delta_time // Independiente de distancia (comportamiento Reynolds correcto) ``` CAMBIOS: 1. boid_manager.cpp::applyCohesion() - Fase 1.4 - Normalizar dirección hacia centro de masa - Fuerza constante independiente de distancia - Check de división por cero (distance > 0.1f) 2. defines.h - Ajuste de parámetros tras normalización - BOID_COHESION_WEIGHT: 0.5 → 0.001 (1000x menor) * Ahora que está normalizado, el valor anterior era gigantesco - BOID_MAX_SPEED: 3.0 → 2.5 (reducida para evitar velocidades extremas) - BOID_MAX_FORCE: 0.5 → 0.05 (reducida 10x) - BOID_MIN_SPEED: 0.5 → 0.3 (reducida) - Radios restaurados a valores originales (30/50/80) RESULTADO ESPERADO: ✅ Sin colapso a puntos (cohesión normalizada correctamente) ✅ Movimiento orgánico sin "órbitas" artificiales ✅ Velocidades controladas y naturales ✅ Balance correcto entre las 3 fuerzas TESTING: Por favor probar con 100 y 1000 boids: - ¿Se mantienen dispersos sin colapsar? - ¿Las órbitas han desaparecido? - ¿El movimiento es más natural? Estado: Compilación exitosa Rama: boids_development 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- source/boids_mgr/boid_manager.cpp | 36 +++++++++++++++++++------------ source/defines.h | 20 ++++++++--------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/source/boids_mgr/boid_manager.cpp b/source/boids_mgr/boid_manager.cpp index f70e469..01f172d 100644 --- a/source/boids_mgr/boid_manager.cpp +++ b/source/boids_mgr/boid_manager.cpp @@ -253,22 +253,30 @@ void BoidManager::applyCohesion(Ball* boid, float delta_time) { center_of_mass_x /= count; center_of_mass_y /= count; - // Dirección hacia el centro - float steer_x = (center_of_mass_x - center_x) * BOID_COHESION_WEIGHT * delta_time; - float steer_y = (center_of_mass_y - center_y) * BOID_COHESION_WEIGHT * delta_time; + // FASE 1.4: Normalizar dirección hacia el centro (CRÍTICO - antes no estaba normalizado!) + float dx_to_center = center_of_mass_x - center_x; + float dy_to_center = center_of_mass_y - center_y; + float distance_to_center = std::sqrt(dx_to_center * dx_to_center + dy_to_center * dy_to_center); - // Limitar fuerza máxima de steering - float steer_mag = std::sqrt(steer_x * steer_x + steer_y * steer_y); - if (steer_mag > BOID_MAX_FORCE) { - steer_x = (steer_x / steer_mag) * BOID_MAX_FORCE; - steer_y = (steer_y / steer_mag) * BOID_MAX_FORCE; + // Solo aplicar si hay distancia al centro (evitar división por cero) + if (distance_to_center > 0.1f) { + // Normalizar vector dirección (fuerza independiente de distancia) + float steer_x = (dx_to_center / distance_to_center) * BOID_COHESION_WEIGHT * delta_time; + float steer_y = (dy_to_center / distance_to_center) * BOID_COHESION_WEIGHT * delta_time; + + // Limitar fuerza máxima de steering + float steer_mag = std::sqrt(steer_x * steer_x + steer_y * steer_y); + if (steer_mag > BOID_MAX_FORCE) { + steer_x = (steer_x / steer_mag) * BOID_MAX_FORCE; + steer_y = (steer_y / steer_mag) * BOID_MAX_FORCE; + } + + float vx, vy; + boid->getVelocity(vx, vy); + vx += steer_x; + vy += steer_y; + boid->setVelocity(vx, vy); } - - float vx, vy; - boid->getVelocity(vx, vy); - vx += steer_x; - vy += steer_y; - boid->setVelocity(vx, vy); } } diff --git a/source/defines.h b/source/defines.h index 0360b71..5c0e7e7 100644 --- a/source/defines.h +++ b/source/defines.h @@ -289,16 +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) -// 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.5f; // Fuerza máxima de steering (QUINTUPLICADO) -constexpr float BOID_MIN_SPEED = 0.5f; // Velocidad mínima (NUEVO - evita boids estáticos) +// FASE 1.1 REVISADA: Parámetros ajustados tras detectar cohesión mal normalizada +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 +constexpr float BOID_ALIGNMENT_WEIGHT = 1.0f; // Peso de alineación +constexpr float BOID_COHESION_WEIGHT = 0.001f; // Peso de cohesión (MICRO - 1000x menor por falta de normalización) +constexpr float BOID_MAX_SPEED = 2.5f; // Velocidad máxima (píxeles/frame - REDUCIDA) +constexpr float BOID_MAX_FORCE = 0.05f; // Fuerza máxima de steering (REDUCIDA para evitar aceleración excesiva) +constexpr float BOID_MIN_SPEED = 0.3f; // Velocidad mínima (evita boids estáticos) constexpr float PI = 3.14159265358979323846f; // Constante PI