diff --git a/source/shapes/cylinder_shape.cpp b/source/shapes/cylinder_shape.cpp index 7988655..b8116c1 100644 --- a/source/shapes/cylinder_shape.cpp +++ b/source/shapes/cylinder_shape.cpp @@ -1,11 +1,15 @@ #include "cylinder_shape.h" #include "../defines.h" #include +#include // Para rand() void CylinderShape::generatePoints(int num_points, float screen_width, float screen_height) { num_points_ = num_points; radius_ = screen_height * CYLINDER_RADIUS_FACTOR; height_ = screen_height * CYLINDER_HEIGHT_FACTOR; + + // Inicializar timer de tumbling con valor aleatorio (3-5 segundos) + tumble_timer_ = 3.0f + (rand() % 2000) / 1000.0f; // Las posiciones 3D se calculan en getPoint3D() usando ecuaciones paramétricas del cilindro } @@ -14,8 +18,39 @@ void CylinderShape::update(float delta_time, float screen_width, float screen_he radius_ = screen_height * CYLINDER_RADIUS_FACTOR; height_ = screen_height * CYLINDER_HEIGHT_FACTOR; - // Actualizar ángulo de rotación en eje Y + // Actualizar ángulo de rotación en eje Y (siempre activo) angle_y_ += CYLINDER_ROTATION_SPEED_Y * delta_time; + + // Sistema de tumbling ocasional + if (is_tumbling_) { + // Estamos en tumble: animar angle_x hacia el objetivo + tumble_duration_ += delta_time; + float tumble_progress = tumble_duration_ / 1.5f; // 1.5 segundos de duración + + if (tumble_progress >= 1.0f) { + // Tumble completado + angle_x_ = tumble_target_; + is_tumbling_ = false; + tumble_timer_ = 3.0f + (rand() % 2000) / 1000.0f; // Nuevo timer (3-5s) + } else { + // Interpolación suave con ease-in-out + float t = tumble_progress; + float ease = t < 0.5f + ? 2.0f * t * t + : 1.0f - (-2.0f * t + 2.0f) * (-2.0f * t + 2.0f) / 2.0f; + angle_x_ = ease * tumble_target_; + } + } else { + // No estamos en tumble: contar tiempo + tumble_timer_ -= delta_time; + if (tumble_timer_ <= 0.0f) { + // Iniciar nuevo tumble + is_tumbling_ = true; + tumble_duration_ = 0.0f; + // Objetivo: PI/2 radianes (90°) o -PI/2 + tumble_target_ = angle_x_ + ((rand() % 2) == 0 ? PI * 0.5f : -PI * 0.5f); + } + } } void CylinderShape::getPoint3D(int index, float& x, float& y, float& z) const { @@ -56,15 +91,21 @@ void CylinderShape::getPoint3D(int index, float& x, float& y, float& z) const { float y_base = (height_ * 0.5f) * v; // Centrar verticalmente float z_base = radius_ * sinf(u); - // Aplicar rotación en eje Y + // Aplicar rotación en eje Y (principal, siempre activa) float cos_y = cosf(angle_y_); float sin_y = sinf(angle_y_); - float x_rot = x_base * cos_y - z_base * sin_y; - float z_rot = x_base * sin_y + z_base * cos_y; + float x_rot_y = x_base * cos_y - z_base * sin_y; + float z_rot_y = x_base * sin_y + z_base * cos_y; - // Retornar coordenadas finales rotadas - x = x_rot; - y = y_base; + // Aplicar rotación en eje X (tumbling ocasional) + float cos_x = cosf(angle_x_); + float sin_x = sinf(angle_x_); + float y_rot = y_base * cos_x - z_rot_y * sin_x; + float z_rot = y_base * sin_x + z_rot_y * cos_x; + + // Retornar coordenadas finales con ambas rotaciones + x = x_rot_y; + y = y_rot; z = z_rot; } diff --git a/source/shapes/cylinder_shape.h b/source/shapes/cylinder_shape.h index 277c572..5e26b5b 100644 --- a/source/shapes/cylinder_shape.h +++ b/source/shapes/cylinder_shape.h @@ -3,15 +3,22 @@ #include "shape.h" // Figura: Cilindro 3D rotante -// Comportamiento: Superficie cilíndrica con rotación en eje Y +// Comportamiento: Superficie cilíndrica con rotación en eje Y + tumbling ocasional en X/Z // Ecuaciones: x = r*cos(u), y = v, z = r*sin(u) class CylinderShape : public Shape { private: float angle_y_ = 0.0f; // Ángulo de rotación en eje Y (rad) + float angle_x_ = 0.0f; // Ángulo de rotación en eje X (tumbling ocasional) float radius_ = 0.0f; // Radio del cilindro (píxeles) float height_ = 0.0f; // Altura del cilindro (píxeles) int num_points_ = 0; // Cantidad de puntos generados + // Sistema de tumbling ocasional + float tumble_timer_ = 0.0f; // Temporizador para próximo tumble + float tumble_duration_ = 0.0f; // Duración del tumble actual + bool is_tumbling_ = false; // ¿Estamos en modo tumble? + float tumble_target_ = 0.0f; // Ángulo objetivo del tumble + public: void generatePoints(int num_points, float screen_width, float screen_height) override; void update(float delta_time, float screen_width, float screen_height) override; diff --git a/source/shapes/wave_grid_shape.cpp b/source/shapes/wave_grid_shape.cpp index ab1330f..37d4023 100644 --- a/source/shapes/wave_grid_shape.cpp +++ b/source/shapes/wave_grid_shape.cpp @@ -34,8 +34,10 @@ void WaveGridShape::update(float delta_time, float screen_width, float screen_he grid_size_ = screen_height * WAVE_GRID_SIZE_FACTOR; amplitude_ = screen_height * WAVE_GRID_AMPLITUDE; - // Actualizar rotación en eje Y (horizontal) - angle_y_ += WAVE_GRID_ROTATION_SPEED_Y * delta_time; + // Pivoteo sutil en ejes X e Y (esquinas adelante/atrás, izq/der) + // Usamos velocidades lentas para movimiento sutil y orgánico + tilt_x_ += 0.3f * delta_time; // Pivoteo vertical (esquinas arriba/abajo) + tilt_y_ += 0.5f * delta_time; // Pivoteo horizontal (esquinas izq/der) // Actualizar fase de las ondas (animación) phase_ += WAVE_GRID_PHASE_SPEED * delta_time; @@ -70,18 +72,22 @@ void WaveGridShape::getPoint3D(int index, float& x, float& y, float& z) const { // z = amplitude * sin(frequency * x + phase) * cos(frequency * y + phase) float kx = WAVE_GRID_FREQUENCY * PI; // Frecuencia en X float ky = WAVE_GRID_FREQUENCY * PI; // Frecuencia en Y - float z_base = amplitude_ * sinf(kx * u + phase_) * cosf(ky * v + phase_); + float z_wave = amplitude_ * sinf(kx * u + phase_) * cosf(ky * v + phase_); - // Aplicar rotación en eje Y (horizontal) - float cos_y = cosf(angle_y_); - float sin_y = sinf(angle_y_); - float x_rot = x_base * cos_y - z_base * sin_y; - float z_rot = x_base * sin_y + z_base * cos_y; + // Añadir pivoteo sutil: esquinas se mueven adelante/atrás según posición + // tilt_x oscila esquinas arriba/abajo, tilt_y oscila esquinas izq/der + float tilt_amount_x = sinf(tilt_x_) * 0.15f; // Máximo 15% del grid_size + float tilt_amount_y = sinf(tilt_y_) * 0.1f; // Máximo 10% del grid_size - // Retornar coordenadas finales - x = x_rot; + float z_tilt = (u * tilt_amount_y + v * tilt_amount_x) * grid_size_; + + // Z final = ondas + pivoteo + float z_final = z_wave + z_tilt; + + // Retornar coordenadas (grid paralelo a pantalla, sin rotación global) + x = x_base; y = y_base; - z = z_rot; + z = z_final; } float WaveGridShape::getScaleFactor(float screen_height) const { diff --git a/source/shapes/wave_grid_shape.h b/source/shapes/wave_grid_shape.h index d00aac2..f3f4ca8 100644 --- a/source/shapes/wave_grid_shape.h +++ b/source/shapes/wave_grid_shape.h @@ -3,11 +3,12 @@ #include "shape.h" // Figura: Malla ondeante 3D (Wave Grid) -// Comportamiento: Grid 2D con ondas sinusoidales en Z + rotación -// Ecuaciones: z = A * sin(kx*x + phase) * cos(ky*y + phase) +// Comportamiento: Grid 2D paralelo a pantalla con ondas + pivoteo sutil en esquinas +// Ecuaciones: z = A * sin(kx*x + phase) * cos(ky*y + phase) + pivoteo class WaveGridShape : public Shape { private: - float angle_y_ = 0.0f; // Ángulo de rotación en eje Y (rad) + float tilt_x_ = 0.0f; // Ángulo de pivoteo en eje X (esquinas adelante/atrás) + float tilt_y_ = 0.0f; // Ángulo de pivoteo en eje Y (esquinas izq/der) float phase_ = 0.0f; // Fase de animación de ondas (rad) float grid_size_ = 0.0f; // Tamaño del grid (píxeles) float amplitude_ = 0.0f; // Amplitud de las ondas (píxeles)