Añadido modo alternativo de simulación que transforma las pelotas en una esfera 3D rotante proyectada en 2D, inspirado en efectos clásicos de demoscene. ## Características Principales - **Algoritmo Fibonacci Sphere**: Distribución uniforme de puntos en esfera 3D - **Rotación dual**: Matrices de rotación en ejes X e Y simultáneos - **Profundidad Z simulada**: Color modulation según distancia (oscuro=lejos, brillante=cerca) - **Transición suave**: Interpolación de 1.5s desde física a esfera - **Sin sprites adicionales**: Usa SDL_SetTextureColorMod para profundidad - **Performance optimizado**: >60 FPS con 100,000 pelotas ## Implementación Técnica ### Nuevos Archivos/Cambios: - `defines.h`: Enum SimulationMode + constantes RotoBall (radio, velocidades, brillo) - `ball.h/cpp`: Soporte 3D (pos_3d, target_2d, depth_brightness, setters) - `engine.h/cpp`: Lógica completa RotoBall (generate, update, toggle) - `generateRotoBallSphere()`: Fibonacci sphere algorithm - `updateRotoBall()`: Rotación 3D + proyección ortográfica - `toggleRotoBallMode()`: Cambio entre PHYSICS/ROTOBALL - `README.md`: Documentación completa del modo - `CLAUDE.md`: Detalles técnicos y algoritmos ## Parámetros Configurables (defines.h) ```cpp ROTOBALL_RADIUS = 80.0f; // Radio de la esfera ROTOBALL_ROTATION_SPEED_Y = 1.5f; // Velocidad rotación eje Y (rad/s) ROTOBALL_ROTATION_SPEED_X = 0.8f; // Velocidad rotación eje X (rad/s) ROTOBALL_TRANSITION_TIME = 1.5f; // Tiempo de transición (segundos) ROTOBALL_MIN_BRIGHTNESS = 50; // Brillo mínimo fondo (0-255) ROTOBALL_MAX_BRIGHTNESS = 255; // Brillo máximo frente (0-255) ``` ## Uso - **Tecla C**: Alternar entre modo física y modo RotoBall - Compatible con todos los temas de colores - Funciona con 1-100,000 pelotas - Debug display muestra "MODE PHYSICS" o "MODE ROTOBALL" ## Performance - Batch rendering: Una sola llamada SDL_RenderGeometry - Fibonacci sphere recalculada por frame (O(n) predecible) - Color mod CPU-side sin overhead GPU - Delta time independiente del framerate 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
131 lines
3.9 KiB
C++
131 lines
3.9 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 "defines.h" // for GravityDirection, ColorTheme
|
|
#include "ball.h" // for Ball
|
|
#include "external/texture.h" // for Texture
|
|
|
|
class Engine {
|
|
public:
|
|
// Interfaz pública
|
|
bool initialize();
|
|
void run();
|
|
void shutdown();
|
|
|
|
private:
|
|
// Recursos SDL
|
|
SDL_Window* window_ = nullptr;
|
|
SDL_Renderer* renderer_ = nullptr;
|
|
std::shared_ptr<Texture> texture_ = nullptr;
|
|
|
|
// Estado del simulador
|
|
std::vector<std::unique_ptr<Ball>> balls_;
|
|
std::array<int, 8> test_ = {1, 10, 100, 500, 1000, 10000, 50000, 100000};
|
|
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_ = 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;
|
|
|
|
// Auto-restart system
|
|
Uint64 all_balls_stopped_start_time_ = 0; // Momento cuando todas se pararon
|
|
bool all_balls_were_stopped_ = false; // Flag de estado anterior
|
|
static constexpr Uint64 AUTO_RESTART_DELAY = 5000; // 5 segundos en ms
|
|
|
|
// Resolución dinámica para modo real fullscreen
|
|
int current_screen_width_ = SCREEN_WIDTH;
|
|
int current_screen_height_ = SCREEN_HEIGHT;
|
|
|
|
// Sistema de temas
|
|
ColorTheme current_theme_ = ColorTheme::SUNSET;
|
|
|
|
// Estructura de tema de colores
|
|
struct ThemeColors {
|
|
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_[5];
|
|
|
|
// Sistema RotoBall (esfera 3D rotante)
|
|
SimulationMode current_mode_ = SimulationMode::PHYSICS;
|
|
struct RotoBallData {
|
|
float angle_y = 0.0f; // Ángulo de rotación en eje Y
|
|
float angle_x = 0.0f; // Ángulo de rotación en eje X
|
|
float transition_progress = 0.0f; // Progreso de transición (0.0-1.0)
|
|
bool transitioning = false; // ¿Está en transición?
|
|
};
|
|
RotoBallData rotoball_;
|
|
|
|
// 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 changeGravityDirection(GravityDirection direction);
|
|
void toggleVSync();
|
|
void toggleFullscreen();
|
|
void toggleRealFullscreen();
|
|
std::string gravityDirectionToString(GravityDirection direction) const;
|
|
void initializeThemes();
|
|
void checkAutoRestart();
|
|
void performRandomRestart();
|
|
|
|
// 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);
|
|
|
|
// Sistema RotoBall
|
|
void toggleRotoBallMode();
|
|
void generateRotoBallSphere();
|
|
void updateRotoBall();
|
|
}; |