Refactoring semántico: - Renombrar rotoball_* → shape_* (variables y métodos) - Mejora legibilidad: aplica a todas las figuras 3D, no solo esfera Fixes críticos: - Fix convergencia: setShapeTarget2D() actualiza targets cada frame - Fix getDistanceToTarget(): siempre calcula distancia (sin guarda) - Fix lógica flip: destruir DURANTE flip N (no después de N flips) - Añadir display CONV en debug HUD (monitoreo convergencia) Mejoras timing: - Reducir PNG_IDLE_TIME_LOGO: 3-5s → 2-4s (flips más dinámicos) - Bajar CONVERGENCE_THRESHOLD: 0.8 → 0.4 (40% permite flips) Sistema flip-waiting (LOGO mode): - CAMINO A: Convergencia + tiempo (inmediato) - CAMINO B: Esperar 1-3 flips y destruir durante flip (20-80% progreso) - Tracking de flips con getFlipCount() y getFlipProgress() 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
214 lines
10 KiB
C++
214 lines
10 KiB
C++
#pragma once
|
|
|
|
#include <SDL3/SDL_events.h> // for SDL_Event
|
|
#include <SDL3/SDL_render.h> // for SDL_Renderer
|
|
#include <SDL3/SDL_stdinc.h> // for Uint64
|
|
#include <SDL3/SDL_video.h> // for SDL_Window
|
|
|
|
#include <array> // for array
|
|
#include <memory> // for unique_ptr, shared_ptr
|
|
#include <string> // for string
|
|
#include <vector> // for vector
|
|
|
|
#include "ball.h" // for Ball
|
|
#include "defines.h" // for GravityDirection, ColorTheme, ShapeType
|
|
#include "external/texture.h" // for Texture
|
|
#include "shapes/shape.h" // for Shape (interfaz polimórfica)
|
|
|
|
// Modos de aplicación mutuamente excluyentes
|
|
enum class AppMode {
|
|
MANUAL, // Control manual del usuario
|
|
DEMO, // Modo demo completo (auto-play)
|
|
DEMO_LITE, // Modo demo lite (solo física/figuras)
|
|
LOGO // Modo logo (easter egg)
|
|
};
|
|
|
|
class Engine {
|
|
public:
|
|
// Interfaz pública
|
|
bool initialize(int width = 0, int height = 0, int zoom = 0, bool fullscreen = false);
|
|
void run();
|
|
void shutdown();
|
|
|
|
private:
|
|
// Recursos SDL
|
|
SDL_Window* window_ = nullptr;
|
|
SDL_Renderer* renderer_ = nullptr;
|
|
std::shared_ptr<Texture> texture_ = nullptr; // Textura activa actual
|
|
std::vector<std::shared_ptr<Texture>> textures_; // Todas las texturas disponibles
|
|
std::vector<std::string> texture_names_; // Nombres de texturas (sin extensión)
|
|
size_t current_texture_index_ = 0; // Índice de textura activa
|
|
int current_ball_size_ = 10; // Tamaño actual de pelotas (dinámico, se actualiza desde texture)
|
|
|
|
// Estado del simulador
|
|
std::vector<std::unique_ptr<Ball>> balls_;
|
|
GravityDirection current_gravity_ = GravityDirection::DOWN;
|
|
int scenario_ = 0;
|
|
bool should_exit_ = false;
|
|
|
|
// Sistema de timing
|
|
Uint64 last_frame_time_ = 0;
|
|
float delta_time_ = 0.0f;
|
|
|
|
// UI y debug
|
|
bool show_debug_ = false;
|
|
bool show_text_ = true;
|
|
|
|
// Sistema de zoom dinámico
|
|
int current_window_zoom_ = DEFAULT_WINDOW_ZOOM;
|
|
std::string text_;
|
|
int text_pos_ = 0;
|
|
Uint64 text_init_time_ = 0;
|
|
|
|
// FPS y V-Sync
|
|
Uint64 fps_last_time_ = 0;
|
|
int fps_frame_count_ = 0;
|
|
int fps_current_ = 0;
|
|
std::string fps_text_ = "FPS: 0";
|
|
bool vsync_enabled_ = true;
|
|
std::string vsync_text_ = "VSYNC ON";
|
|
bool fullscreen_enabled_ = false;
|
|
bool real_fullscreen_enabled_ = false;
|
|
ScalingMode current_scaling_mode_ = ScalingMode::INTEGER; // Modo de escalado actual (F5)
|
|
|
|
// Resolución base (configurada por CLI o default)
|
|
int base_screen_width_ = DEFAULT_SCREEN_WIDTH;
|
|
int base_screen_height_ = DEFAULT_SCREEN_HEIGHT;
|
|
|
|
// Resolución dinámica actual (cambia en fullscreen real)
|
|
int current_screen_width_ = DEFAULT_SCREEN_WIDTH;
|
|
int current_screen_height_ = DEFAULT_SCREEN_HEIGHT;
|
|
|
|
// Sistema de temas
|
|
ColorTheme current_theme_ = ColorTheme::SUNSET;
|
|
ColorTheme target_theme_ = ColorTheme::SUNSET; // Tema destino para transición
|
|
bool transitioning_ = false; // ¿Estamos en transición?
|
|
float transition_progress_ = 0.0f; // Progreso de 0.0 a 1.0
|
|
float transition_duration_ = 0.5f; // Duración en segundos
|
|
|
|
// Estructura de tema de colores
|
|
struct ThemeColors {
|
|
const char* name_en; // Nombre en inglés (para debug)
|
|
const char* name_es; // Nombre en español (para display)
|
|
int text_color_r, text_color_g, text_color_b; // Color del texto del tema
|
|
float bg_top_r, bg_top_g, bg_top_b;
|
|
float bg_bottom_r, bg_bottom_g, bg_bottom_b;
|
|
std::vector<Color> ball_colors;
|
|
};
|
|
|
|
// Temas de colores definidos
|
|
ThemeColors themes_[7]; // 7 temas: SUNSET, OCEAN, NEON, FOREST, RGB, MONOCHROME, LAVENDER
|
|
|
|
// Sistema de Temas Dinámicos (animados)
|
|
DynamicTheme dynamic_themes_[3]; // 3 temas dinámicos predefinidos
|
|
bool dynamic_theme_active_ = false; // ¿Tema dinámico activo?
|
|
int current_dynamic_theme_index_ = -1; // Índice del tema dinámico actual (-1 = ninguno)
|
|
size_t current_keyframe_index_ = 0; // Keyframe actual
|
|
size_t target_keyframe_index_ = 1; // Próximo keyframe
|
|
float dynamic_transition_progress_ = 0.0f; // Progreso 0.0-1.0 hacia próximo keyframe
|
|
bool dynamic_theme_paused_ = false; // Pausa manual con Shift+D
|
|
|
|
// Sistema de Figuras 3D (polimórfico)
|
|
SimulationMode current_mode_ = SimulationMode::PHYSICS;
|
|
ShapeType current_shape_type_ = ShapeType::SPHERE; // Tipo de figura actual
|
|
ShapeType last_shape_type_ = ShapeType::SPHERE; // Última figura para toggle F
|
|
std::unique_ptr<Shape> active_shape_; // Puntero polimórfico a figura activa
|
|
float shape_scale_factor_ = 1.0f; // Factor de escala manual (Numpad +/-)
|
|
bool depth_zoom_enabled_ = true; // Zoom por profundidad Z activado
|
|
|
|
// Sistema de Modo DEMO (auto-play)
|
|
AppMode current_app_mode_ = AppMode::MANUAL; // Modo actual (mutuamente excluyente)
|
|
AppMode previous_app_mode_ = AppMode::MANUAL; // Modo previo antes de entrar a LOGO
|
|
float demo_timer_ = 0.0f; // Contador de tiempo para próxima acción
|
|
float demo_next_action_time_ = 0.0f; // Tiempo aleatorio hasta próxima acción (segundos)
|
|
|
|
// Sistema de convergencia para LOGO MODE (escala con resolución)
|
|
float shape_convergence_ = 0.0f; // % de pelotas cerca del objetivo (0.0-1.0)
|
|
float logo_convergence_threshold_ = 0.90f; // Threshold aleatorio (75-100%)
|
|
float logo_min_time_ = 3.0f; // Tiempo mínimo escalado con resolución
|
|
float logo_max_time_ = 5.0f; // Tiempo máximo escalado (backup)
|
|
|
|
// Sistema de espera de flips en LOGO MODE (camino alternativo)
|
|
bool logo_waiting_for_flip_ = false; // true si eligió el camino "esperar flip"
|
|
int logo_target_flip_number_ = 0; // En qué flip actuar (1, 2 o 3)
|
|
float logo_target_flip_percentage_ = 0.0f; // % de flip a esperar (0.2-0.8)
|
|
int logo_current_flip_count_ = 0; // Flips observados hasta ahora
|
|
|
|
// Estado previo antes de entrar a Logo Mode (para restaurar al salir)
|
|
ColorTheme logo_previous_theme_ = ColorTheme::SUNSET;
|
|
size_t logo_previous_texture_index_ = 0;
|
|
float logo_previous_shape_scale_ = 1.0f;
|
|
|
|
// Batch rendering
|
|
std::vector<SDL_Vertex> batch_vertices_;
|
|
std::vector<int> batch_indices_;
|
|
|
|
// Métodos principales del loop
|
|
void calculateDeltaTime();
|
|
void update();
|
|
void handleEvents();
|
|
void render();
|
|
|
|
// Métodos auxiliares
|
|
void initBalls(int value);
|
|
void setText();
|
|
void pushBallsAwayFromGravity();
|
|
void switchBallsGravity();
|
|
void enableBallsGravityIfDisabled();
|
|
void forceBallsGravityOn();
|
|
void forceBallsGravityOff();
|
|
void changeGravityDirection(GravityDirection direction);
|
|
void toggleVSync();
|
|
void toggleFullscreen();
|
|
void toggleRealFullscreen();
|
|
void toggleIntegerScaling();
|
|
std::string gravityDirectionToString(GravityDirection direction) const;
|
|
void initializeThemes();
|
|
|
|
// Sistema de Temas Dinámicos
|
|
void initializeDynamicThemes(); // Inicializar 3 temas dinámicos predefinidos
|
|
void updateDynamicTheme(); // Actualizar animación de tema dinámico (llamado cada frame)
|
|
void activateDynamicTheme(int index); // Activar tema dinámico (0-2)
|
|
void pauseDynamicTheme(); // Toggle pausa de animación (Shift+D)
|
|
|
|
// Sistema de gestión de estados (MANUAL/DEMO/DEMO_LITE/LOGO)
|
|
void setState(AppMode new_mode); // Cambiar modo de aplicación (mutuamente excluyente)
|
|
|
|
// Sistema de Modo DEMO
|
|
void updateDemoMode();
|
|
void performDemoAction(bool is_lite);
|
|
void randomizeOnDemoStart(bool is_lite);
|
|
void toggleGravityOnOff();
|
|
|
|
// Sistema de Modo Logo (easter egg)
|
|
void toggleLogoMode(); // Activar/desactivar modo logo manual (tecla K)
|
|
void enterLogoMode(bool from_demo = false); // Entrar al modo logo (manual o automático)
|
|
void exitLogoMode(bool return_to_demo = false); // Salir del modo logo
|
|
|
|
// Sistema de transiciones LERP
|
|
float lerp(float a, float b, float t) const { return a + (b - a) * t; }
|
|
Color getInterpolatedColor(size_t ball_index) const; // Obtener color interpolado durante transición
|
|
void startThemeTransition(ColorTheme new_theme);
|
|
|
|
// Sistema de cambio de sprites dinámico
|
|
void switchTexture(); // Cambia a siguiente textura disponible
|
|
void updateBallSizes(int old_size, int new_size); // Ajusta posiciones al cambiar tamaño
|
|
|
|
// Sistema de zoom dinámico
|
|
int calculateMaxWindowZoom() const;
|
|
void setWindowZoom(int new_zoom);
|
|
void zoomIn();
|
|
void zoomOut();
|
|
|
|
// Rendering
|
|
void renderGradientBackground();
|
|
void addSpriteToBatch(float x, float y, float w, float h, int r, int g, int b, float scale = 1.0f);
|
|
|
|
// Sistema de Figuras 3D
|
|
void toggleShapeMode(bool force_gravity_on_exit = true); // Toggle PHYSICS ↔ última figura (tecla F)
|
|
void activateShape(ShapeType type); // Activar figura específica (teclas Q/W/E/R/Y/U/I)
|
|
void updateShape(); // Actualizar figura activa
|
|
void generateShape(); // Generar puntos de figura activa
|
|
void clampShapeScale(); // Limitar escala para evitar clipping
|
|
};
|