Mejorar interacción entre modos RotoBall y física con gestión de gravedad

Cambios principales:
- Fix: Pelotas ahora caen correctamente al salir de RotoBall (resetear on_surface_/stopped_)
- Fix: Al cambiar escenario en RotoBall, desactivar modo figura primero
- Feature: Al entrar en RotoBall, gravedad se desactiva automáticamente
- Feature: Tecla G desde RotoBall → Sale a física SIN gravedad (pelotas flotan)
- Feature: Tecla C desde RotoBall → Sale a física CON gravedad (pelotas caen)
- Feature: Cursores desde RotoBall → Sale a física CON gravedad + cambio dirección
- Feature: Cursores desde física sin gravedad → Reactiva gravedad automáticamente

Nuevos métodos:
- Ball::enableGravityIfDisabled() - Reactiva solo si está desactivada
- Ball::forceGravityOn() - Fuerza activación
- Ball::forceGravityOff() - Fuerza desactivación
- Engine::toggleRotoBallMode(bool force_gravity_on_exit) - Control de gravedad al salir

Lógica de controles desde RotoBall:
- C: Figura OFF → Física CON gravedad (caen)
- ↑↓←→: Figura OFF → Física CON gravedad + dirección (caen hacia dirección)
- G: Figura OFF → Física SIN gravedad (flotan)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-03 19:34:33 +02:00
parent 31ac22bd0f
commit 535c397be2
4 changed files with 100 additions and 3 deletions

View File

@@ -227,6 +227,23 @@ void Ball::switchGravity() {
gravity_force_ = gravity_force_ == 0.0f ? (GRAVITY_FORCE * 60.0f * 60.0f) : 0.0f;
}
// Reactiva la gravedad si está desactivada
void Ball::enableGravityIfDisabled() {
if (gravity_force_ == 0.0f) {
gravity_force_ = GRAVITY_FORCE * 60.0f * 60.0f;
}
}
// Fuerza gravedad ON (siempre activa)
void Ball::forceGravityOn() {
gravity_force_ = GRAVITY_FORCE * 60.0f * 60.0f;
}
// Fuerza gravedad OFF (siempre desactiva)
void Ball::forceGravityOff() {
gravity_force_ = 0.0f;
}
// Cambia la dirección de gravedad
void Ball::setGravityDirection(GravityDirection direction) {
gravity_direction_ = direction;
@@ -283,6 +300,12 @@ void Ball::setDepthBrightness(float brightness) {
// Activar/desactivar atracción física hacia esfera RotoBall
void Ball::enableRotoBallAttraction(bool enable) {
rotoball_attraction_active_ = enable;
// Al activar atracción, resetear flags de superficie para permitir física completa
if (enable) {
on_surface_ = false;
stopped_ = false;
}
}
// Aplicar fuerza de resorte hacia punto objetivo en esfera rotante

View File

@@ -48,6 +48,15 @@ class Ball {
// Cambia la gravedad
void switchGravity();
// Reactiva la gravedad si está desactivada
void enableGravityIfDisabled();
// Fuerza gravedad ON (siempre activa)
void forceGravityOn();
// Fuerza gravedad OFF (siempre desactiva)
void forceGravityOff();
// Cambia la direcci\u00f3n de gravedad
void setGravityDirection(GravityDirection direction);

View File

@@ -180,23 +180,52 @@ void Engine::handleEvents() {
break;
case SDLK_G:
switchBallsGravity();
// Si estamos en RotoBall, salir a modo física SIN GRAVEDAD
if (current_mode_ == SimulationMode::ROTOBALL) {
toggleRotoBallMode(false); // Desactivar RotoBall sin forzar gravedad ON
} else {
switchBallsGravity(); // Toggle normal en modo física
}
break;
// Controles de dirección de gravedad con teclas de cursor
case SDLK_UP:
// Si estamos en RotoBall, salir a modo física CON gravedad
if (current_mode_ == SimulationMode::ROTOBALL) {
toggleRotoBallMode(); // Desactivar RotoBall (activa gravedad automáticamente)
} else {
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
}
changeGravityDirection(GravityDirection::UP);
break;
case SDLK_DOWN:
// Si estamos en RotoBall, salir a modo física CON gravedad
if (current_mode_ == SimulationMode::ROTOBALL) {
toggleRotoBallMode(); // Desactivar RotoBall (activa gravedad automáticamente)
} else {
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
}
changeGravityDirection(GravityDirection::DOWN);
break;
case SDLK_LEFT:
// Si estamos en RotoBall, salir a modo física CON gravedad
if (current_mode_ == SimulationMode::ROTOBALL) {
toggleRotoBallMode(); // Desactivar RotoBall (activa gravedad automáticamente)
} else {
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
}
changeGravityDirection(GravityDirection::LEFT);
break;
case SDLK_RIGHT:
// Si estamos en RotoBall, salir a modo física CON gravedad
if (current_mode_ == SimulationMode::ROTOBALL) {
toggleRotoBallMode(); // Desactivar RotoBall (activa gravedad automáticamente)
} else {
enableBallsGravityIfDisabled(); // Reactivar gravedad si estaba OFF
}
changeGravityDirection(GravityDirection::RIGHT);
break;
@@ -441,6 +470,13 @@ void Engine::render() {
}
void Engine::initBalls(int value) {
// Si estamos en modo RotoBall, desactivarlo antes de regenerar pelotas
if (current_mode_ == SimulationMode::ROTOBALL) {
current_mode_ = SimulationMode::PHYSICS;
rotoball_.transitioning = false;
rotoball_.transition_progress = 0.0f;
}
// Limpiar las bolas actuales
balls_.clear();
@@ -514,6 +550,24 @@ void Engine::switchBallsGravity() {
}
}
void Engine::enableBallsGravityIfDisabled() {
for (auto &ball : balls_) {
ball->enableGravityIfDisabled();
}
}
void Engine::forceBallsGravityOn() {
for (auto &ball : balls_) {
ball->forceGravityOn();
}
}
void Engine::forceBallsGravityOff() {
for (auto &ball : balls_) {
ball->forceGravityOff();
}
}
void Engine::changeGravityDirection(GravityDirection direction) {
current_gravity_ = direction;
for (auto &ball : balls_) {
@@ -869,7 +923,7 @@ void Engine::performRandomRestart() {
}
// Sistema RotoBall - Alternar entre modo física y esfera 3D
void Engine::toggleRotoBallMode() {
void Engine::toggleRotoBallMode(bool force_gravity_on_exit) {
if (current_mode_ == SimulationMode::PHYSICS) {
// Cambiar a modo RotoBall
current_mode_ = SimulationMode::ROTOBALL;
@@ -878,6 +932,9 @@ void Engine::toggleRotoBallMode() {
rotoball_.angle_y = 0.0f;
rotoball_.angle_x = 0.0f;
// Desactivar gravedad al entrar en modo figura
forceBallsGravityOff();
// Generar esfera 3D
generateRotoBallSphere();
@@ -904,6 +961,11 @@ void Engine::toggleRotoBallMode() {
ball->enableRotoBallAttraction(false);
}
// Activar gravedad al salir (solo si se especifica)
if (force_gravity_on_exit) {
forceBallsGravityOn();
}
// Mostrar texto informativo
text_ = "MODO FISICA";
int text_width = static_cast<int>(text_.length() * 8);

View File

@@ -105,6 +105,9 @@ private:
void setText();
void pushBallsAwayFromGravity();
void switchBallsGravity();
void enableBallsGravityIfDisabled();
void forceBallsGravityOn();
void forceBallsGravityOff();
void changeGravityDirection(GravityDirection direction);
void toggleVSync();
void toggleFullscreen();
@@ -125,7 +128,7 @@ private:
void addSpriteToBatch(float x, float y, float w, float h, int r, int g, int b);
// Sistema RotoBall
void toggleRotoBallMode();
void toggleRotoBallMode(bool force_gravity_on_exit = true);
void generateRotoBallSphere();
void updateRotoBall();
};