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>
This commit is contained in:
2025-09-18 16:52:24 +02:00
parent dec8d431f5
commit 78656cf17d
5 changed files with 278 additions and 64 deletions

View File

@@ -7,6 +7,20 @@
#include "defines.h" // for BALL_SIZE, Color, SCREEN_HEIGHT, GRAVITY_FORCE
class Texture;
// Función auxiliar para generar variación aleatoria en rebotes
float generateBounceVariation() {
// Genera un valor entre -BOUNCE_VARIATION_PERCENT y +BOUNCE_VARIATION_PERCENT
float variation = ((rand() % 1000) / 1000.0f - 0.5f) * 2.0f * BOUNCE_VARIATION_PERCENT;
return 1.0f + variation; // Retorna multiplicador (ej: 0.95 - 1.05 para ±5%)
}
// Función auxiliar para generar pérdida lateral aleatoria
float generateLateralLoss() {
// Genera un valor entre 0 y LATERAL_LOSS_PERCENT
float loss = (rand() % 1000) / 1000.0f * LATERAL_LOSS_PERCENT;
return 1.0f - loss; // Retorna multiplicador (ej: 0.98 - 1.0 para 0-2% pérdida)
}
// Constructor
Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> texture, GravityDirection gravity_dir)
: sprite_(std::make_unique<Sprite>(texture)),
@@ -23,7 +37,8 @@ Ball::Ball(float x, float vx, float vy, Color color, std::shared_ptr<Texture> te
gravity_direction_ = gravity_dir;
on_surface_ = false;
stopped_ = false;
loss_ = ((rand() % 30) * 0.01f) + 0.6f;
// Coeficiente base IGUAL para todas las pelotas (solo variación por rebote individual)
loss_ = BASE_BOUNCE_COEFFICIENT; // Coeficiente fijo para todas las pelotas
}
// Actualiza la lógica de la clase
@@ -80,64 +95,72 @@ void Ball::update(float deltaTime) {
if (pos_.x < 0) {
pos_.x = 0;
if (gravity_direction_ == GravityDirection::LEFT) {
// Colisión con superficie de gravedad
vx_ = -vx_ * loss_;
// Colisión con superficie de gravedad - aplicar variación aleatoria
vx_ = -vx_ * loss_ * generateBounceVariation();
if (std::fabs(vx_) < 6.0f) {
vx_ = 0.0f;
on_surface_ = true;
}
} else {
// Rebote normal
vx_ = -vx_;
// Rebote normal - con pérdida lateral aleatoria
vx_ = -vx_ * generateLateralLoss();
}
// Pérdida lateral en velocidad vertical también
vy_ *= generateLateralLoss();
}
// Comprueba las colisiones con el lateral derecho
if (pos_.x + pos_.w > SCREEN_WIDTH) {
pos_.x = SCREEN_WIDTH - pos_.w;
if (gravity_direction_ == GravityDirection::RIGHT) {
// Colisión con superficie de gravedad
vx_ = -vx_ * loss_;
// Colisión con superficie de gravedad - aplicar variación aleatoria
vx_ = -vx_ * loss_ * generateBounceVariation();
if (std::fabs(vx_) < 6.0f) {
vx_ = 0.0f;
on_surface_ = true;
}
} else {
// Rebote normal
vx_ = -vx_;
// Rebote normal - con pérdida lateral aleatoria
vx_ = -vx_ * generateLateralLoss();
}
// Pérdida lateral en velocidad vertical también
vy_ *= generateLateralLoss();
}
// Comprueba las colisiones con la parte superior
if (pos_.y < 0) {
pos_.y = 0;
if (gravity_direction_ == GravityDirection::UP) {
// Colisión con superficie de gravedad
vy_ = -vy_ * loss_;
// Colisión con superficie de gravedad - aplicar variación aleatoria
vy_ = -vy_ * loss_ * generateBounceVariation();
if (std::fabs(vy_) < 6.0f) {
vy_ = 0.0f;
on_surface_ = true;
}
} else {
// Rebote normal
vy_ = -vy_;
// Rebote normal - con pérdida lateral aleatoria
vy_ = -vy_ * generateLateralLoss();
}
// Pérdida lateral en velocidad horizontal también
vx_ *= generateLateralLoss();
}
// Comprueba las colisiones con la parte inferior
if (pos_.y + pos_.h > SCREEN_HEIGHT) {
pos_.y = SCREEN_HEIGHT - pos_.h;
if (gravity_direction_ == GravityDirection::DOWN) {
// Colisión con superficie de gravedad
vy_ = -vy_ * loss_;
// Colisión con superficie de gravedad - aplicar variación aleatoria
vy_ = -vy_ * loss_ * generateBounceVariation();
if (std::fabs(vy_) < 6.0f) {
vy_ = 0.0f;
on_surface_ = true;
}
} else {
// Rebote normal
vy_ = -vy_;
// Rebote normal - con pérdida lateral aleatoria
vy_ = -vy_ * generateLateralLoss();
}
// Pérdida lateral en velocidad horizontal también
vx_ *= generateLateralLoss();
}
// Aplica rozamiento al estar en superficie

View File

@@ -46,6 +46,7 @@ class Ball {
float getVelocityY() const { return vy_; }
float getVelocityX() const { return vx_; }
float getGravityForce() const { return gravity_force_; }
float getLossCoefficient() const { return loss_; }
GravityDirection getGravityDirection() const { return gravity_direction_; }
bool isOnSurface() const { return on_surface_; }

View File

@@ -11,6 +11,11 @@ constexpr float GRAVITY_FORCE = 0.2f;
// DEMO_SPEED eliminado - ya no se usa con delta time
constexpr Uint64 TEXT_DURATION = 2000;
// Configuración de variación aleatoria en rebotes
constexpr float BASE_BOUNCE_COEFFICIENT = 0.75f; // Coeficiente base IGUAL para todas las pelotas
constexpr float BOUNCE_VARIATION_PERCENT = 0.05f; // ±5% variación en cada rebote
constexpr float LATERAL_LOSS_PERCENT = 0.02f; // ±2% pérdida lateral en rebotes
struct Color {
int r, g, b;
};

View File

@@ -555,15 +555,20 @@ void render() {
std::string surface_text = balls[0]->isOnSurface() ? "SURFACE YES" : "SURFACE NO";
dbg_print(8, 40, surface_text.c_str(), 255, 0, 255); // Magenta para debug
// Línea 4: Dirección de gravedad
// Línea 4: Coeficiente de rebote (loss)
float loss_val = balls[0]->getLossCoefficient();
std::string loss_text = "LOSS " + std::to_string(loss_val).substr(0, 4); // Solo 2 decimales
dbg_print(8, 48, loss_text.c_str(), 255, 0, 255); // Magenta para debug
// Línea 5: Dirección de gravedad
std::string gravity_dir_text = "GRAVITY " + gravityDirectionToString(current_gravity);
dbg_print(8, 48, gravity_dir_text.c_str(), 255, 255, 0); // Amarillo para dirección
dbg_print(8, 56, gravity_dir_text.c_str(), 255, 255, 0); // Amarillo para dirección
}
// Debug: Mostrar tema actual
std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"};
std::string theme_text = "THEME " + theme_names[static_cast<int>(current_theme)];
dbg_print(8, 56, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema
dbg_print(8, 64, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema
}
SDL_RenderPresent(renderer);