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
|
||||
{
|
||||
// Calcular progreso de cada logo (Logo 2 con retraso)
|
||||
float fade_progress_logo1 = timer_ / APPLOGO_FADE_DURATION;
|
||||
float fade_progress_logo2 = std::max(0.0f, (timer_ - APPLOGO_LOGO2_DELAY) / APPLOGO_FADE_DURATION);
|
||||
float fade_progress_logo1 = timer_ / APPLOGO_ANIMATION_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)
|
||||
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_rotation_ = 0.0f;
|
||||
} else {
|
||||
// Interpolar alpha con retraso + easing para suavidad
|
||||
float eased_prog1 = easeInOutQuad(std::min(1.0f, fade_progress_logo1));
|
||||
float eased_prog2 = easeInOutQuad(std::min(1.0f, fade_progress_logo2));
|
||||
logo1_alpha_ = static_cast<int>(eased_prog1 * 255.0f);
|
||||
logo2_alpha_ = static_cast<int>(eased_prog2 * 255.0f);
|
||||
// Interpolar alpha con retraso de forma LINEAL (sin easing)
|
||||
logo1_alpha_ = static_cast<int>(std::min(1.0f, fade_progress_logo1) * 255.0f);
|
||||
logo2_alpha_ = static_cast<int>(std::min(1.0f, fade_progress_logo2) * 255.0f);
|
||||
|
||||
// ================================================================
|
||||
// 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)
|
||||
{
|
||||
// Calcular progreso de cada logo (Logo 2 con retraso)
|
||||
float fade_progress_logo1 = timer_ / APPLOGO_FADE_DURATION;
|
||||
float fade_progress_logo2 = std::max(0.0f, (timer_ - APPLOGO_LOGO2_DELAY) / APPLOGO_FADE_DURATION);
|
||||
float fade_progress_logo1 = timer_ / APPLOGO_ANIMATION_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)
|
||||
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_rotation_ = 0.0f;
|
||||
} else {
|
||||
// Interpolar alpha con retraso + easing para suavidad (255 → 0)
|
||||
float eased_prog1 = easeInOutQuad(std::min(1.0f, fade_progress_logo1));
|
||||
float eased_prog2 = easeInOutQuad(std::min(1.0f, fade_progress_logo2));
|
||||
logo1_alpha_ = static_cast<int>((1.0f - eased_prog1) * 255.0f);
|
||||
logo2_alpha_ = static_cast<int>((1.0f - eased_prog2) * 255.0f);
|
||||
// Interpolar alpha con retraso de forma LINEAL (255 → 0, sin easing)
|
||||
logo1_alpha_ = static_cast<int>((1.0f - std::min(1.0f, fade_progress_logo1)) * 255.0f);
|
||||
logo2_alpha_ = static_cast<int>((1.0f - std::min(1.0f, fade_progress_logo2)) * 255.0f);
|
||||
|
||||
// ================================================================
|
||||
// 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)
|
||||
int alpha = (logo_index == 1) ? logo1_alpha_ : logo2_alpha_;
|
||||
SDL_SetTextureAlphaMod(texture, static_cast<Uint8>(alpha));
|
||||
|
||||
// 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;
|
||||
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 padding desde bordes derecho e inferior
|
||||
float padding_x = screen_width_ * APPLOGO_PADDING_PERCENT;
|
||||
float padding_y = screen_height_ * APPLOGO_PADDING_PERCENT;
|
||||
|
||||
// Calcular esquina del logo (anclado a esquina inferior derecha con padding)
|
||||
float corner_x = screen_width_ - width - padding_x;
|
||||
float corner_y = screen_height_ - height - padding_y;
|
||||
// Calcular esquina BASE (sin escala) para obtener centro FIJO
|
||||
// Esto asegura que el centro no se mueva cuando cambia scale/squash/stretch
|
||||
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
|
||||
float center_x = corner_x + (width / 2.0f);
|
||||
float center_y = corner_y + (height / 2.0f);
|
||||
// Centro FIJO del logo (no cambia con scale/squash/stretch)
|
||||
float center_x = corner_x_base + (base_width / 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
|
||||
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;
|
||||
vertices[0].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
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)
|
||||
@@ -656,7 +654,7 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||
vertices[1].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
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)
|
||||
@@ -667,7 +665,7 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||
vertices[2].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
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)
|
||||
@@ -678,7 +676,7 @@ void AppLogo::renderWithGeometry(int logo_index) {
|
||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||
vertices[3].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
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
|
||||
|
||||
@@ -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"
|
||||
|
||||
// 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_DURATION = 5.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_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_LOGO2_DELAY = 0.25f; // Retraso de Logo 2 respecto a Logo 1 (segundos)
|
||||
constexpr float APPLOGO_DISPLAY_INTERVAL = 2.0f; // Intervalo entre apariciones del logo (segundos)
|
||||
constexpr float APPLOGO_DISPLAY_DURATION = 4.0f; // Duración de visibilidad del logo (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_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)
|
||||
|
||||
// Configuración de Modo BOIDS (comportamiento de enjambre)
|
||||
// TIME-BASED CONVERSION (frame-based → time-based):
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
// getExecutableDirectory() ya está definido en defines.h como inline
|
||||
|
||||
// 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;
|
||||
|
||||
// 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_->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)
|
||||
shape_manager_->initialize(this, scene_manager_.get(), ui_manager_.get(), state_manager_.get(),
|
||||
current_screen_width_, current_screen_height_);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
class Engine {
|
||||
public:
|
||||
// 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 shutdown();
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include "engine.h"
|
||||
#include "defines.h"
|
||||
|
||||
// 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 << " -f, --fullscreen Modo pantalla completa (F3 - letterbox)\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 << "Ejemplos:\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 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 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";
|
||||
}
|
||||
|
||||
@@ -29,6 +35,7 @@ int main(int argc, char* argv[]) {
|
||||
int zoom = 0;
|
||||
bool fullscreen = false;
|
||||
bool real_fullscreen = false;
|
||||
AppMode initial_mode = AppMode::SANDBOX; // Modo inicial (default: SANDBOX)
|
||||
|
||||
// Parsear argumentos
|
||||
for (int i = 1; i < argc; i++) {
|
||||
@@ -72,6 +79,25 @@ int main(int argc, char* argv[]) {
|
||||
fullscreen = true;
|
||||
} else if (strcmp(argv[i], "-F") == 0 || strcmp(argv[i], "--real-fullscreen") == 0) {
|
||||
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 {
|
||||
std::cerr << "Error: Opción desconocida '" << argv[i] << "'\n";
|
||||
printHelp();
|
||||
@@ -86,7 +112,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user