3 Commits

3 changed files with 64 additions and 5 deletions

View File

@@ -74,7 +74,16 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
// VALIDACIÓN 2: Calcular max_zoom y ajustar si es necesario
int max_zoom = std::min(screen_w / logical_width, screen_h / logical_height);
if (window_zoom > max_zoom) {
if (max_zoom < 1) {
// Resolució lògica no cap en pantalla ni a zoom=1: escalar-la per fer-la càpida
float scale = std::min(static_cast<float>(screen_w) / logical_width,
static_cast<float>(screen_h) / logical_height);
logical_width = std::max(320, static_cast<int>(logical_width * scale));
logical_height = std::max(240, static_cast<int>(logical_height * scale));
window_zoom = 1;
std::cout << "Advertencia: Resolución no cabe en pantalla. Ajustando a "
<< logical_width << "x" << logical_height << "\n";
} else if (window_zoom > max_zoom) {
std::cout << "Advertencia: Zoom " << window_zoom << " excede máximo " << max_zoom
<< " para " << logical_width << "x" << logical_height << ". Ajustando a " << max_zoom << "\n";
window_zoom = max_zoom;
@@ -288,7 +297,8 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
}
// Benchmark de rendimiento (determina max_auto_scenario_ para modos automáticos)
runPerformanceBenchmark();
if (!skip_benchmark_)
runPerformanceBenchmark();
// Precalentar caché: shapes PNG (evitar I/O en primera activación de PNG_SHAPE)
{
@@ -554,6 +564,21 @@ void Engine::switchTexture() {
switchTextureInternal(true); // Mostrar notificación en modo manual
}
// Control manual del benchmark (--skip-benchmark, --max-balls)
void Engine::setSkipBenchmark() {
skip_benchmark_ = true;
}
void Engine::setMaxBallsOverride(int n) {
skip_benchmark_ = true;
int best = DEMO_AUTO_MIN_SCENARIO;
for (int i = DEMO_AUTO_MIN_SCENARIO; i <= DEMO_AUTO_MAX_SCENARIO; ++i) {
if (BALL_COUNT_SCENARIOS[i] <= n) best = i;
else break;
}
max_auto_scenario_ = best;
}
// Escenario custom (--custom-balls)
void Engine::setCustomScenario(int balls) {
custom_scenario_balls_ = balls;
@@ -1667,17 +1692,22 @@ void Engine::runPerformanceBenchmark() {
const int BENCH_DURATION_MS = 600;
const int WARMUP_FRAMES = 5;
SimulationMode original_mode = current_mode_;
auto restore = [&]() {
SDL_SetRenderVSync(renderer_, vsync_enabled_ ? 1 : 0);
SDL_ShowWindow(window_);
scene_manager_->changeScenario(0, current_mode_);
current_mode_ = original_mode;
active_shape_.reset();
scene_manager_->changeScenario(0, original_mode);
last_frame_time_ = 0;
};
// Test escenario custom (independiente de max_auto_scenario_)
custom_auto_available_ = false;
if (custom_scenario_enabled_) {
scene_manager_->changeScenario(CUSTOM_SCENARIO_IDX, current_mode_);
scene_manager_->changeScenario(CUSTOM_SCENARIO_IDX, SimulationMode::SHAPE);
activateShapeInternal(ShapeType::SPHERE);
last_frame_time_ = 0;
for (int w = 0; w < WARMUP_FRAMES; ++w) {
calculateDeltaTime();
@@ -1700,7 +1730,8 @@ void Engine::runPerformanceBenchmark() {
// Probar de más pesado a más ligero
for (int idx = DEMO_AUTO_MAX_SCENARIO; idx >= DEMO_AUTO_MIN_SCENARIO; --idx) {
scene_manager_->changeScenario(idx, current_mode_);
scene_manager_->changeScenario(idx, SimulationMode::SHAPE);
activateShapeInternal(ShapeType::SPHERE);
// Warmup: estabilizar física y pipeline GPU
last_frame_time_ = 0;

View File

@@ -81,6 +81,10 @@ class Engine {
bool isCustomAutoAvailable() const { return custom_auto_available_; }
int getCustomScenarioBalls() const { return custom_scenario_balls_; }
// Control manual del benchmark (--skip-benchmark, --max-balls)
void setSkipBenchmark();
void setMaxBallsOverride(int n);
// Notificaciones (público para InputHandler)
void showNotificationForAction(const std::string& text);
@@ -189,6 +193,7 @@ class Engine {
int custom_scenario_balls_ = 0;
bool custom_scenario_enabled_ = false;
bool custom_auto_available_ = false;
bool skip_benchmark_ = false;
// Sistema de convergencia para LOGO MODE (escala con resolución)
// Usado por performLogoAction() para detectar cuando las bolas forman el logo

View File

@@ -19,6 +19,8 @@ void printHelp() {
std::cout << " -k, --kiosk Modo kiosko (F4 fijo, sin ESC, sin zoom)\n";
std::cout << " -m, --mode <mode> Modo inicial: sandbox, demo, demo-lite, logo (default: sandbox)\n";
std::cout << " --custom-balls <n> Activa escenario custom (tecla 9) con N pelotas\n";
std::cout << " --skip-benchmark Salta el benchmark y usa el máximo de bolas (50000)\n";
std::cout << " --max-balls <n> Limita el máximo de bolas en modos DEMO/DEMO_LITE\n";
std::cout << " --help Mostrar esta ayuda\n\n";
std::cout << "Ejemplos:\n";
std::cout << " vibe3_physics # 320x240 zoom 3 (ventana 960x720)\n";
@@ -41,6 +43,8 @@ int main(int argc, char* argv[]) {
bool fullscreen = false;
bool real_fullscreen = false;
bool kiosk_mode = false;
bool skip_benchmark = false;
int max_balls_override = 0;
AppMode initial_mode = AppMode::SANDBOX; // Modo inicial (default: SANDBOX)
// Parsear argumentos
@@ -118,6 +122,20 @@ int main(int argc, char* argv[]) {
std::cerr << "Error: --custom-balls requiere un valor\n";
return -1;
}
} else if (strcmp(argv[i], "--skip-benchmark") == 0) {
skip_benchmark = true;
} else if (strcmp(argv[i], "--max-balls") == 0) {
if (i + 1 < argc) {
int n = atoi(argv[++i]);
if (n < 1) {
std::cerr << "Error: --max-balls requiere un valor >= 1\n";
return -1;
}
max_balls_override = n;
} else {
std::cerr << "Error: --max-balls requiere un valor\n";
return -1;
}
} else {
std::cerr << "Error: Opción desconocida '" << argv[i] << "'\n";
printHelp();
@@ -135,6 +153,11 @@ int main(int argc, char* argv[]) {
if (custom_balls > 0)
engine.setCustomScenario(custom_balls); // pre-init: asigna campos antes del benchmark
if (max_balls_override > 0)
engine.setMaxBallsOverride(max_balls_override);
else if (skip_benchmark)
engine.setSkipBenchmark();
if (!engine.initialize(width, height, zoom, fullscreen, initial_mode)) {
std::cout << "¡Error al inicializar el engine!" << std::endl;
return -1;