Compare commits
5 Commits
7609b9ef5c
...
db8acf0331
| Author | SHA1 | Date | |
|---|---|---|---|
| db8acf0331 | |||
| 5a35cc1abf | |||
| d30a4fd440 | |||
| 97c0683f6e | |||
| c3d24cc07d |
Binary file not shown.
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 123 KiB |
@@ -222,8 +222,8 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
|||||||
// Fade in: alpha de 0 a 255, con Logo 2 retrasado 0.25s
|
// Fade in: alpha de 0 a 255, con Logo 2 retrasado 0.25s
|
||||||
{
|
{
|
||||||
// Calcular progreso de cada logo (Logo 2 con retraso)
|
// Calcular progreso de cada logo (Logo 2 con retraso)
|
||||||
float fade_progress_logo1 = timer_ / APPLOGO_FADE_DURATION;
|
float fade_progress_logo1 = timer_ / APPLOGO_ANIMATION_DURATION;
|
||||||
float fade_progress_logo2 = std::max(0.0f, (timer_ - APPLOGO_LOGO2_DELAY) / APPLOGO_FADE_DURATION);
|
float fade_progress_logo2 = std::max(0.0f, (timer_ - APPLOGO_LOGO2_DELAY) / APPLOGO_ANIMATION_DURATION);
|
||||||
|
|
||||||
// Verificar si fade in completado (cuando logo2 también termina)
|
// Verificar si fade in completado (cuando logo2 también termina)
|
||||||
if (fade_progress_logo2 >= 1.0f) {
|
if (fade_progress_logo2 >= 1.0f) {
|
||||||
@@ -242,11 +242,9 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
|||||||
logo2_stretch_x_ = 1.0f;
|
logo2_stretch_x_ = 1.0f;
|
||||||
logo2_rotation_ = 0.0f;
|
logo2_rotation_ = 0.0f;
|
||||||
} else {
|
} else {
|
||||||
// Interpolar alpha con retraso + easing para suavidad
|
// Interpolar alpha con retraso de forma LINEAL (sin easing)
|
||||||
float eased_prog1 = easeInOutQuad(std::min(1.0f, fade_progress_logo1));
|
logo1_alpha_ = static_cast<int>(std::min(1.0f, fade_progress_logo1) * 255.0f);
|
||||||
float eased_prog2 = easeInOutQuad(std::min(1.0f, fade_progress_logo2));
|
logo2_alpha_ = static_cast<int>(std::min(1.0f, fade_progress_logo2) * 255.0f);
|
||||||
logo1_alpha_ = static_cast<int>(eased_prog1 * 255.0f);
|
|
||||||
logo2_alpha_ = static_cast<int>(eased_prog2 * 255.0f);
|
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// Aplicar MISMA animación (current_animation_) a ambos logos
|
// Aplicar MISMA animación (current_animation_) a ambos logos
|
||||||
@@ -342,8 +340,8 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
|||||||
// Fade out: alpha de 255 a 0, con Logo 2 retrasado 0.25s (misma animación que entrada)
|
// Fade out: alpha de 255 a 0, con Logo 2 retrasado 0.25s (misma animación que entrada)
|
||||||
{
|
{
|
||||||
// Calcular progreso de cada logo (Logo 2 con retraso)
|
// Calcular progreso de cada logo (Logo 2 con retraso)
|
||||||
float fade_progress_logo1 = timer_ / APPLOGO_FADE_DURATION;
|
float fade_progress_logo1 = timer_ / APPLOGO_ANIMATION_DURATION;
|
||||||
float fade_progress_logo2 = std::max(0.0f, (timer_ - APPLOGO_LOGO2_DELAY) / APPLOGO_FADE_DURATION);
|
float fade_progress_logo2 = std::max(0.0f, (timer_ - APPLOGO_LOGO2_DELAY) / APPLOGO_ANIMATION_DURATION);
|
||||||
|
|
||||||
// Verificar si fade out completado (cuando logo2 también termina)
|
// Verificar si fade out completado (cuando logo2 también termina)
|
||||||
if (fade_progress_logo2 >= 1.0f) {
|
if (fade_progress_logo2 >= 1.0f) {
|
||||||
@@ -362,11 +360,9 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
|||||||
logo2_stretch_x_ = 1.0f;
|
logo2_stretch_x_ = 1.0f;
|
||||||
logo2_rotation_ = 0.0f;
|
logo2_rotation_ = 0.0f;
|
||||||
} else {
|
} else {
|
||||||
// Interpolar alpha con retraso + easing para suavidad (255 → 0)
|
// Interpolar alpha con retraso de forma LINEAL (255 → 0, sin easing)
|
||||||
float eased_prog1 = easeInOutQuad(std::min(1.0f, fade_progress_logo1));
|
logo1_alpha_ = static_cast<int>((1.0f - std::min(1.0f, fade_progress_logo1)) * 255.0f);
|
||||||
float eased_prog2 = easeInOutQuad(std::min(1.0f, fade_progress_logo2));
|
logo2_alpha_ = static_cast<int>((1.0f - std::min(1.0f, fade_progress_logo2)) * 255.0f);
|
||||||
logo1_alpha_ = static_cast<int>((1.0f - eased_prog1) * 255.0f);
|
|
||||||
logo2_alpha_ = static_cast<int>((1.0f - eased_prog2) * 255.0f);
|
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// Aplicar MISMA animación (current_animation_) de forma invertida
|
// Aplicar MISMA animación (current_animation_) de forma invertida
|
||||||
@@ -607,24 +603,26 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
|||||||
|
|
||||||
// Aplicar alpha específico de cada logo (con retraso para logo2)
|
// Aplicar alpha específico de cada logo (con retraso para logo2)
|
||||||
int alpha = (logo_index == 1) ? logo1_alpha_ : logo2_alpha_;
|
int alpha = (logo_index == 1) ? logo1_alpha_ : logo2_alpha_;
|
||||||
SDL_SetTextureAlphaMod(texture, static_cast<Uint8>(alpha));
|
float alpha_normalized = static_cast<float>(alpha) / 255.0f; // Convertir 0-255 → 0.0-1.0
|
||||||
|
// NO usar SDL_SetTextureAlphaMod - aplicar alpha directamente a vértices
|
||||||
// Calcular tamaño con escala y deformaciones aplicadas
|
|
||||||
// (base_width y base_height ya están pre-escalados al tamaño correcto de pantalla)
|
|
||||||
float width = base_width * scale * stretch_x;
|
|
||||||
float height = base_height * scale * squash_y;
|
|
||||||
|
|
||||||
// Calcular padding desde bordes derecho e inferior
|
// Calcular padding desde bordes derecho e inferior
|
||||||
float padding_x = screen_width_ * APPLOGO_PADDING_PERCENT;
|
float padding_x = screen_width_ * APPLOGO_PADDING_PERCENT;
|
||||||
float padding_y = screen_height_ * APPLOGO_PADDING_PERCENT;
|
float padding_y = screen_height_ * APPLOGO_PADDING_PERCENT;
|
||||||
|
|
||||||
// Calcular esquina del logo (anclado a esquina inferior derecha con padding)
|
// Calcular esquina BASE (sin escala) para obtener centro FIJO
|
||||||
float corner_x = screen_width_ - width - padding_x;
|
// Esto asegura que el centro no se mueva cuando cambia scale/squash/stretch
|
||||||
float corner_y = screen_height_ - height - padding_y;
|
float corner_x_base = screen_width_ - base_width - padding_x;
|
||||||
|
float corner_y_base = screen_height_ - base_height - padding_y;
|
||||||
|
|
||||||
// Centro del logo (para rotación) = esquina + mitad del tamaño
|
// Centro FIJO del logo (no cambia con scale/squash/stretch)
|
||||||
float center_x = corner_x + (width / 2.0f);
|
float center_x = corner_x_base + (base_width / 2.0f);
|
||||||
float center_y = corner_y + (height / 2.0f);
|
float center_y = corner_y_base + (base_height / 2.0f);
|
||||||
|
|
||||||
|
// Calcular tamaño ESCALADO (para vértices)
|
||||||
|
// (base_width y base_height ya están pre-escalados al tamaño correcto de pantalla)
|
||||||
|
float width = base_width * scale * stretch_x;
|
||||||
|
float height = base_height * scale * squash_y;
|
||||||
|
|
||||||
// Pre-calcular seno y coseno de rotación
|
// Pre-calcular seno y coseno de rotación
|
||||||
float cos_rot = cosf(rotation);
|
float cos_rot = cosf(rotation);
|
||||||
@@ -645,7 +643,7 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
|||||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||||
vertices[0].position = {center_x + rotated_x, center_y + rotated_y};
|
vertices[0].position = {center_x + rotated_x, center_y + rotated_y};
|
||||||
vertices[0].tex_coord = {0.0f, 0.0f};
|
vertices[0].tex_coord = {0.0f, 0.0f};
|
||||||
vertices[0].color = {1.0f, 1.0f, 1.0f, 1.0f}; // Color blanco (textura se modula con alpha)
|
vertices[0].color = {1.0f, 1.0f, 1.0f, alpha_normalized}; // Alpha aplicado al vértice
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vértice superior derecho (rotado)
|
// Vértice superior derecho (rotado)
|
||||||
@@ -656,7 +654,7 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
|||||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||||
vertices[1].position = {center_x + rotated_x, center_y + rotated_y};
|
vertices[1].position = {center_x + rotated_x, center_y + rotated_y};
|
||||||
vertices[1].tex_coord = {1.0f, 0.0f};
|
vertices[1].tex_coord = {1.0f, 0.0f};
|
||||||
vertices[1].color = {1.0f, 1.0f, 1.0f, 1.0f};
|
vertices[1].color = {1.0f, 1.0f, 1.0f, alpha_normalized}; // Alpha aplicado al vértice
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vértice inferior derecho (rotado)
|
// Vértice inferior derecho (rotado)
|
||||||
@@ -667,7 +665,7 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
|||||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||||
vertices[2].position = {center_x + rotated_x, center_y + rotated_y};
|
vertices[2].position = {center_x + rotated_x, center_y + rotated_y};
|
||||||
vertices[2].tex_coord = {1.0f, 1.0f};
|
vertices[2].tex_coord = {1.0f, 1.0f};
|
||||||
vertices[2].color = {1.0f, 1.0f, 1.0f, 1.0f};
|
vertices[2].color = {1.0f, 1.0f, 1.0f, alpha_normalized}; // Alpha aplicado al vértice
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vértice inferior izquierdo (rotado)
|
// Vértice inferior izquierdo (rotado)
|
||||||
@@ -678,7 +676,7 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
|||||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||||
vertices[3].position = {center_x + rotated_x, center_y + rotated_y};
|
vertices[3].position = {center_x + rotated_x, center_y + rotated_y};
|
||||||
vertices[3].tex_coord = {0.0f, 1.0f};
|
vertices[3].tex_coord = {0.0f, 1.0f};
|
||||||
vertices[3].color = {1.0f, 1.0f, 1.0f, 1.0f};
|
vertices[3].color = {1.0f, 1.0f, 1.0f, alpha_normalized}; // Alpha aplicado al vértice
|
||||||
}
|
}
|
||||||
|
|
||||||
// Índices para 2 triángulos
|
// Índices para 2 triángulos
|
||||||
|
|||||||
@@ -289,12 +289,12 @@ constexpr float LOGO_FLIP_TRIGGER_MAX = 0.80f; // 80% máximo de progres
|
|||||||
constexpr int LOGO_FLIP_WAIT_PROBABILITY = 50; // 50% probabilidad de elegir el camino "esperar flip"
|
constexpr int LOGO_FLIP_WAIT_PROBABILITY = 50; // 50% probabilidad de elegir el camino "esperar flip"
|
||||||
|
|
||||||
// Configuración de AppLogo (logo periódico en pantalla)
|
// Configuración de AppLogo (logo periódico en pantalla)
|
||||||
constexpr float APPLOGO_DISPLAY_INTERVAL = 20.0f; // Intervalo entre apariciones del logo (segundos)
|
constexpr float APPLOGO_DISPLAY_INTERVAL = 2.0f; // Intervalo entre apariciones del logo (segundos)
|
||||||
constexpr float APPLOGO_DISPLAY_DURATION = 5.0f; // Duración de visibilidad del logo (segundos)
|
constexpr float APPLOGO_DISPLAY_DURATION = 4.0f; // Duración de visibilidad del logo (segundos)
|
||||||
constexpr float APPLOGO_FADE_DURATION = 0.5f; // Duración del fade in/out (segundos)
|
constexpr float APPLOGO_ANIMATION_DURATION = 0.5f; // Duración de animación entrada/salida (segundos)
|
||||||
constexpr float APPLOGO_HEIGHT_PERCENT = 0.4f; // Altura del logo = 40% de la altura de pantalla
|
constexpr float APPLOGO_HEIGHT_PERCENT = 0.4f; // Altura del logo = 40% de la altura de pantalla
|
||||||
constexpr float APPLOGO_PADDING_PERCENT = 0.1f; // Padding desde esquina inferior-derecha = 10%
|
constexpr float APPLOGO_PADDING_PERCENT = 0.05f; // Padding desde esquina inferior-derecha = 10%
|
||||||
constexpr float APPLOGO_LOGO2_DELAY = 0.25f; // Retraso de Logo 2 respecto a Logo 1 (segundos)
|
constexpr float APPLOGO_LOGO2_DELAY = 0.25f; // Retraso de Logo 2 respecto a Logo 1 (segundos)
|
||||||
|
|
||||||
// Configuración de Modo BOIDS (comportamiento de enjambre)
|
// Configuración de Modo BOIDS (comportamiento de enjambre)
|
||||||
// TIME-BASED CONVERSION (frame-based → time-based):
|
// TIME-BASED CONVERSION (frame-based → time-based):
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
// getExecutableDirectory() ya está definido en defines.h como inline
|
// getExecutableDirectory() ya está definido en defines.h como inline
|
||||||
|
|
||||||
// Implementación de métodos públicos
|
// Implementación de métodos públicos
|
||||||
bool Engine::initialize(int width, int height, int zoom, bool fullscreen) {
|
bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMode initial_mode) {
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
// Obtener resolución de pantalla para validación
|
// Obtener resolución de pantalla para validación
|
||||||
@@ -246,6 +246,11 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen) {
|
|||||||
state_manager_ = std::make_unique<StateManager>();
|
state_manager_ = std::make_unique<StateManager>();
|
||||||
state_manager_->initialize(this); // Callback al Engine
|
state_manager_->initialize(this); // Callback al Engine
|
||||||
|
|
||||||
|
// Establecer modo inicial si no es SANDBOX (default)
|
||||||
|
if (initial_mode != AppMode::SANDBOX) {
|
||||||
|
state_manager_->setState(initial_mode, current_screen_width_, current_screen_height_);
|
||||||
|
}
|
||||||
|
|
||||||
// Actualizar ShapeManager con StateManager (dependencia circular - StateManager debe existir primero)
|
// Actualizar ShapeManager con StateManager (dependencia circular - StateManager debe existir primero)
|
||||||
shape_manager_->initialize(this, scene_manager_.get(), ui_manager_.get(), state_manager_.get(),
|
shape_manager_->initialize(this, scene_manager_.get(), ui_manager_.get(), state_manager_.get(),
|
||||||
current_screen_width_, current_screen_height_);
|
current_screen_width_, current_screen_height_);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
class Engine {
|
class Engine {
|
||||||
public:
|
public:
|
||||||
// Interfaz pública principal
|
// Interfaz pública principal
|
||||||
bool initialize(int width = 0, int height = 0, int zoom = 0, bool fullscreen = false);
|
bool initialize(int width = 0, int height = 0, int zoom = 0, bool fullscreen = false, AppMode initial_mode = AppMode::SANDBOX);
|
||||||
void run();
|
void run();
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
// getExecutableDirectory() ya está definido en defines.h como inline
|
// getExecutableDirectory() ya está definido en defines.h como inline
|
||||||
|
|
||||||
@@ -13,13 +15,17 @@ void printHelp() {
|
|||||||
std::cout << " -z, --zoom <n> Zoom de ventana (default: 3)\n";
|
std::cout << " -z, --zoom <n> Zoom de ventana (default: 3)\n";
|
||||||
std::cout << " -f, --fullscreen Modo pantalla completa (F3 - letterbox)\n";
|
std::cout << " -f, --fullscreen Modo pantalla completa (F3 - letterbox)\n";
|
||||||
std::cout << " -F, --real-fullscreen Modo pantalla completa real (F4 - nativo)\n";
|
std::cout << " -F, --real-fullscreen Modo pantalla completa real (F4 - nativo)\n";
|
||||||
|
std::cout << " -m, --mode <mode> Modo inicial: sandbox, demo, demo-lite, logo (default: sandbox)\n";
|
||||||
std::cout << " --help Mostrar esta ayuda\n\n";
|
std::cout << " --help Mostrar esta ayuda\n\n";
|
||||||
std::cout << "Ejemplos:\n";
|
std::cout << "Ejemplos:\n";
|
||||||
std::cout << " vibe3_physics # 320x240 zoom 3 (ventana 960x720)\n";
|
std::cout << " vibe3_physics # 320x240 zoom 3 (ventana 960x720)\n";
|
||||||
std::cout << " vibe3_physics -w 1920 -h 1080 # 1920x1080 zoom 1 (auto)\n";
|
std::cout << " vibe3_physics -w 1920 -h 1080 # 1920x1080 zoom 1 (auto)\n";
|
||||||
std::cout << " vibe3_physics -w 640 -h 480 -z 2 # 640x480 zoom 2 (ventana 1280x960)\n";
|
std::cout << " vibe3_physics -w 640 -h 480 -z 2 # 640x480 zoom 2 (ventana 1280x960)\n";
|
||||||
std::cout << " vibe3_physics -f # Fullscreen letterbox (F3)\n";
|
std::cout << " vibe3_physics -f # Fullscreen letterbox (F3)\n";
|
||||||
std::cout << " vibe3_physics -F # Fullscreen real (F4 - resolución nativa)\n\n";
|
std::cout << " vibe3_physics -F # Fullscreen real (F4 - resolución nativa)\n";
|
||||||
|
std::cout << " vibe3_physics --mode demo # Arrancar en modo DEMO (auto-play)\n";
|
||||||
|
std::cout << " vibe3_physics -m demo-lite # Arrancar en modo DEMO_LITE (solo física)\n";
|
||||||
|
std::cout << " vibe3_physics -F --mode logo # Fullscreen + modo LOGO (easter egg)\n\n";
|
||||||
std::cout << "Nota: Si resolución > pantalla, se usa default. Zoom se ajusta automáticamente.\n";
|
std::cout << "Nota: Si resolución > pantalla, se usa default. Zoom se ajusta automáticamente.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +35,7 @@ int main(int argc, char* argv[]) {
|
|||||||
int zoom = 0;
|
int zoom = 0;
|
||||||
bool fullscreen = false;
|
bool fullscreen = false;
|
||||||
bool real_fullscreen = false;
|
bool real_fullscreen = false;
|
||||||
|
AppMode initial_mode = AppMode::SANDBOX; // Modo inicial (default: SANDBOX)
|
||||||
|
|
||||||
// Parsear argumentos
|
// Parsear argumentos
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
@@ -72,6 +79,25 @@ int main(int argc, char* argv[]) {
|
|||||||
fullscreen = true;
|
fullscreen = true;
|
||||||
} else if (strcmp(argv[i], "-F") == 0 || strcmp(argv[i], "--real-fullscreen") == 0) {
|
} else if (strcmp(argv[i], "-F") == 0 || strcmp(argv[i], "--real-fullscreen") == 0) {
|
||||||
real_fullscreen = true;
|
real_fullscreen = true;
|
||||||
|
} else if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--mode") == 0) {
|
||||||
|
if (i + 1 < argc) {
|
||||||
|
std::string mode_str = argv[++i];
|
||||||
|
if (mode_str == "sandbox") {
|
||||||
|
initial_mode = AppMode::SANDBOX;
|
||||||
|
} else if (mode_str == "demo") {
|
||||||
|
initial_mode = AppMode::DEMO;
|
||||||
|
} else if (mode_str == "demo-lite") {
|
||||||
|
initial_mode = AppMode::DEMO_LITE;
|
||||||
|
} else if (mode_str == "logo") {
|
||||||
|
initial_mode = AppMode::LOGO;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: Modo '" << mode_str << "' no válido. Usa: sandbox, demo, demo-lite, logo\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: -m/--mode requiere un valor\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Error: Opción desconocida '" << argv[i] << "'\n";
|
std::cerr << "Error: Opción desconocida '" << argv[i] << "'\n";
|
||||||
printHelp();
|
printHelp();
|
||||||
@@ -86,7 +112,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
Engine engine;
|
Engine engine;
|
||||||
|
|
||||||
if (!engine.initialize(width, height, zoom, fullscreen)) {
|
if (!engine.initialize(width, height, zoom, fullscreen, initial_mode)) {
|
||||||
std::cout << "¡Error al inicializar el engine!" << std::endl;
|
std::cout << "¡Error al inicializar el engine!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user