Hacer RotoBall totalmente escalable con resolución de pantalla
Problema: - Radio fijo de 80px funcionaba bien en 320x240 - En F4 fullscreen (1920x1080), radio de 360px era correcto visualmente - PERO las fuerzas físicas (spring_k, damping) seguían siendo para 80px - Resultado: pelotas nunca llegaban a pegarse en resoluciones altas Solución: 1. Radio proporcional a altura de pantalla (ROTOBALL_RADIUS_FACTOR = 0.333) 2. Escalar TODAS las constantes de física proporcionalmente al radio 3. Fórmula: scale = sphere_radius / BASE_RADIUS (80px) Cambios técnicos: - defines.h: ROTOBALL_RADIUS → ROTOBALL_RADIUS_FACTOR (0.333) - engine.cpp: Calcular radius dinámicamente en generate/update - ball.h: applyRotoBallForce() ahora recibe sphere_radius - ball.cpp: Escalar spring_k, damping_base, damping_near, near_threshold, max_force Resultado: - 320x240: Radio 80px, scale=1.0 (idéntico a antes) - 640x480: Radio 160px, scale=2.0 (fuerzas 2x) - 1920x1080: Radio 360px, scale=4.5 (fuerzas 4.5x) Comportamiento físico IDÉNTICO en todas las resoluciones ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -309,9 +309,21 @@ void Ball::enableRotoBallAttraction(bool enable) {
|
||||
}
|
||||
|
||||
// Aplicar fuerza de resorte hacia punto objetivo en esfera rotante
|
||||
void Ball::applyRotoBallForce(float target_x, float target_y, float deltaTime) {
|
||||
void Ball::applyRotoBallForce(float target_x, float target_y, float sphere_radius, float deltaTime) {
|
||||
if (!rotoball_attraction_active_) return;
|
||||
|
||||
// Calcular factor de escala basado en el radio (radio base = 80px)
|
||||
// Si radius=80 → scale=1.0, si radius=160 → scale=2.0, si radius=360 → scale=4.5
|
||||
const float BASE_RADIUS = 80.0f;
|
||||
float scale = sphere_radius / BASE_RADIUS;
|
||||
|
||||
// Escalar constantes de física proporcionalmente
|
||||
float spring_k = ROTOBALL_SPRING_K * scale;
|
||||
float damping_base = ROTOBALL_DAMPING_BASE * scale;
|
||||
float damping_near = ROTOBALL_DAMPING_NEAR * scale;
|
||||
float near_threshold = ROTOBALL_NEAR_THRESHOLD * scale;
|
||||
float max_force = ROTOBALL_MAX_FORCE * scale;
|
||||
|
||||
// Calcular vector diferencia (dirección hacia el target)
|
||||
float diff_x = target_x - pos_.x;
|
||||
float diff_y = target_y - pos_.y;
|
||||
@@ -320,13 +332,13 @@ void Ball::applyRotoBallForce(float target_x, float target_y, float deltaTime) {
|
||||
float distance = sqrtf(diff_x * diff_x + diff_y * diff_y);
|
||||
|
||||
// Fuerza de resorte (Ley de Hooke: F = -k * x)
|
||||
float spring_force_x = ROTOBALL_SPRING_K * diff_x;
|
||||
float spring_force_y = ROTOBALL_SPRING_K * diff_y;
|
||||
float spring_force_x = spring_k * diff_x;
|
||||
float spring_force_y = spring_k * diff_y;
|
||||
|
||||
// Amortiguación variable: más cerca del punto = más amortiguación (estabilización)
|
||||
float damping = (distance < ROTOBALL_NEAR_THRESHOLD)
|
||||
? ROTOBALL_DAMPING_NEAR
|
||||
: ROTOBALL_DAMPING_BASE;
|
||||
float damping = (distance < near_threshold)
|
||||
? damping_near
|
||||
: damping_base;
|
||||
|
||||
// Fuerza de amortiguación (proporcional a la velocidad)
|
||||
float damping_force_x = damping * vx_;
|
||||
@@ -338,10 +350,10 @@ void Ball::applyRotoBallForce(float target_x, float target_y, float deltaTime) {
|
||||
|
||||
// Limitar magnitud de fuerza (evitar explosiones numéricas)
|
||||
float force_magnitude = sqrtf(total_force_x * total_force_x + total_force_y * total_force_y);
|
||||
if (force_magnitude > ROTOBALL_MAX_FORCE) {
|
||||
float scale = ROTOBALL_MAX_FORCE / force_magnitude;
|
||||
total_force_x *= scale;
|
||||
total_force_y *= scale;
|
||||
if (force_magnitude > max_force) {
|
||||
float scale_limit = max_force / force_magnitude;
|
||||
total_force_x *= scale_limit;
|
||||
total_force_y *= scale_limit;
|
||||
}
|
||||
|
||||
// Aplicar aceleración (F = ma, asumiendo m = 1 para simplificar)
|
||||
|
||||
Reference in New Issue
Block a user