afegit escenari personalitzat per parametre
This commit is contained in:
@@ -59,6 +59,7 @@ constexpr int BALL_COUNT_SCENARIOS[8] = {10, 50, 100, 500, 1000, 5000, 10000, 50
|
||||
constexpr int DEMO_AUTO_MIN_SCENARIO = 2; // mínimo 100 bolas
|
||||
constexpr int DEMO_AUTO_MAX_SCENARIO = 7; // máximo sin restricción hardware (ajustado por benchmark)
|
||||
constexpr int LOGO_MIN_SCENARIO_IDX = 4; // mínimo 1000 bolas (sustituye LOGO_MODE_MIN_BALLS)
|
||||
constexpr int CUSTOM_SCENARIO_IDX = 8; // Escenario custom opcional (tecla 9, --custom-balls)
|
||||
|
||||
// Estructura para representar colores RGB
|
||||
struct Color {
|
||||
|
||||
@@ -226,6 +226,10 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
|
||||
scene_manager_ = std::make_unique<SceneManager>(current_screen_width_, current_screen_height_);
|
||||
scene_manager_->initialize(0, texture_, theme_manager_.get()); // Escenario 0 (10 bolas) por defecto
|
||||
|
||||
// Propagar configuración custom si fue establecida antes de initialize()
|
||||
if (custom_scenario_enabled_)
|
||||
scene_manager_->setCustomBallCount(custom_scenario_balls_);
|
||||
|
||||
// Calcular tamaño físico de ventana ANTES de inicializar UIManager
|
||||
// NOTA: No llamar a updatePhysicalWindowSize() aquí porque ui_manager_ aún no existe
|
||||
// Calcular manualmente para poder pasar valores al constructor de UIManager
|
||||
@@ -550,6 +554,15 @@ void Engine::switchTexture() {
|
||||
switchTextureInternal(true); // Mostrar notificación en modo manual
|
||||
}
|
||||
|
||||
// Escenario custom (--custom-balls)
|
||||
void Engine::setCustomScenario(int balls) {
|
||||
custom_scenario_balls_ = balls;
|
||||
custom_scenario_enabled_ = true;
|
||||
// scene_manager_ puede no existir aún (llamada pre-init); propagación en initialize()
|
||||
if (scene_manager_)
|
||||
scene_manager_->setCustomBallCount(balls);
|
||||
}
|
||||
|
||||
// Escenarios (número de pelotas)
|
||||
void Engine::changeScenario(int scenario_id, const char* notification_text) {
|
||||
// Pasar el modo actual al SceneManager para inicialización correcta
|
||||
@@ -1420,8 +1433,12 @@ void Engine::executeDemoAction(bool is_lite) {
|
||||
accumulated_weight += DEMO_WEIGHT_SCENARIO;
|
||||
if (random_value < accumulated_weight) {
|
||||
int auto_max = std::min(max_auto_scenario_, DEMO_AUTO_MAX_SCENARIO);
|
||||
int range = auto_max - DEMO_AUTO_MIN_SCENARIO + 1;
|
||||
int new_scenario = DEMO_AUTO_MIN_SCENARIO + (rand() % range);
|
||||
std::vector<int> candidates;
|
||||
for (int i = DEMO_AUTO_MIN_SCENARIO; i <= auto_max; ++i)
|
||||
candidates.push_back(i);
|
||||
if (custom_scenario_enabled_ && custom_auto_available_)
|
||||
candidates.push_back(CUSTOM_SCENARIO_IDX);
|
||||
int new_scenario = candidates[rand() % candidates.size()];
|
||||
scene_manager_->changeScenario(new_scenario, current_mode_);
|
||||
|
||||
// Si estamos en modo SHAPE, regenerar la figura con nuevo número de pelotas
|
||||
@@ -1578,8 +1595,12 @@ void Engine::executeRandomizeOnDemoStart(bool is_lite) {
|
||||
|
||||
// 2. Escenario - rango dinámico según benchmark de rendimiento
|
||||
int auto_max = std::min(max_auto_scenario_, DEMO_AUTO_MAX_SCENARIO);
|
||||
int range = auto_max - DEMO_AUTO_MIN_SCENARIO + 1;
|
||||
int new_scenario = DEMO_AUTO_MIN_SCENARIO + (rand() % range);
|
||||
std::vector<int> candidates;
|
||||
for (int i = DEMO_AUTO_MIN_SCENARIO; i <= auto_max; ++i)
|
||||
candidates.push_back(i);
|
||||
if (custom_scenario_enabled_ && custom_auto_available_)
|
||||
candidates.push_back(CUSTOM_SCENARIO_IDX);
|
||||
int new_scenario = candidates[rand() % candidates.size()];
|
||||
scene_manager_->changeScenario(new_scenario, current_mode_);
|
||||
|
||||
// Si estamos en modo SHAPE, generar la figura y activar atracción
|
||||
@@ -1653,6 +1674,30 @@ void Engine::runPerformanceBenchmark() {
|
||||
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_);
|
||||
last_frame_time_ = 0;
|
||||
for (int w = 0; w < WARMUP_FRAMES; ++w) {
|
||||
calculateDeltaTime();
|
||||
SDL_Event e; while (SDL_PollEvent(&e)) {}
|
||||
update();
|
||||
render();
|
||||
}
|
||||
int frame_count = 0;
|
||||
Uint64 start = SDL_GetTicks();
|
||||
while (SDL_GetTicks() - start < static_cast<Uint64>(BENCH_DURATION_MS)) {
|
||||
calculateDeltaTime();
|
||||
SDL_Event e; while (SDL_PollEvent(&e)) {}
|
||||
update();
|
||||
render();
|
||||
++frame_count;
|
||||
}
|
||||
float fps = static_cast<float>(frame_count) / (BENCH_DURATION_MS / 1000.0f);
|
||||
custom_auto_available_ = (fps >= monitor_hz);
|
||||
}
|
||||
|
||||
// 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_);
|
||||
|
||||
@@ -75,6 +75,12 @@ class Engine {
|
||||
void setKioskMode(bool enabled) { kiosk_mode_ = enabled; }
|
||||
bool isKioskMode() const { return kiosk_mode_; }
|
||||
|
||||
// Escenario custom (tecla 9, --custom-balls)
|
||||
void setCustomScenario(int balls);
|
||||
bool isCustomScenarioEnabled() const { return custom_scenario_enabled_; }
|
||||
bool isCustomAutoAvailable() const { return custom_auto_available_; }
|
||||
int getCustomScenarioBalls() const { return custom_scenario_balls_; }
|
||||
|
||||
// Notificaciones (público para InputHandler)
|
||||
void showNotificationForAction(const std::string& text);
|
||||
|
||||
@@ -175,6 +181,11 @@ class Engine {
|
||||
float demo_next_action_time_ = 0.0f; // Tiempo aleatorio hasta próxima acción (segundos)
|
||||
int max_auto_scenario_ = 5; // Índice máximo en modos auto (default conservador: 5000 bolas)
|
||||
|
||||
// Escenario custom (--custom-balls)
|
||||
int custom_scenario_balls_ = 0;
|
||||
bool custom_scenario_enabled_ = false;
|
||||
bool custom_auto_available_ = false;
|
||||
|
||||
// Sistema de convergencia para LOGO MODE (escala con resolución)
|
||||
// Usado por performLogoAction() para detectar cuando las bolas forman el logo
|
||||
float shape_convergence_ = 0.0f; // % de pelotas cerca del objetivo (0.0-1.0)
|
||||
|
||||
@@ -224,6 +224,13 @@ bool InputHandler::processEvents(Engine& engine) {
|
||||
engine.changeScenario(7, "50,000 Pelotas");
|
||||
break;
|
||||
|
||||
case SDLK_9:
|
||||
if (engine.isCustomScenarioEnabled()) {
|
||||
std::string custom_notif = std::to_string(engine.getCustomScenarioBalls()) + " Pelotas";
|
||||
engine.changeScenario(CUSTOM_SCENARIO_IDX, custom_notif.c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
// Controles de zoom dinámico (solo si no estamos en fullscreen)
|
||||
case SDLK_F1:
|
||||
if (engine.isKioskMode()) engine.showNotificationForAction(KIOSK_NOTIFICATION_TEXT);
|
||||
|
||||
@@ -18,6 +18,7 @@ void printHelp() {
|
||||
std::cout << " -F, --real-fullscreen Modo pantalla completa real (F4 - nativo)\n";
|
||||
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 << " --help Mostrar esta ayuda\n\n";
|
||||
std::cout << "Ejemplos:\n";
|
||||
std::cout << " vibe3_physics # 320x240 zoom 3 (ventana 960x720)\n";
|
||||
@@ -36,6 +37,7 @@ int main(int argc, char* argv[]) {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int zoom = 0;
|
||||
int custom_balls = 0;
|
||||
bool fullscreen = false;
|
||||
bool real_fullscreen = false;
|
||||
bool kiosk_mode = false;
|
||||
@@ -104,6 +106,18 @@ int main(int argc, char* argv[]) {
|
||||
std::cerr << "Error: -m/--mode requiere un valor\n";
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(argv[i], "--custom-balls") == 0) {
|
||||
if (i + 1 < argc) {
|
||||
int n = atoi(argv[++i]);
|
||||
if (n < 1) {
|
||||
std::cerr << "Error: --custom-balls requiere un valor >= 1\n";
|
||||
return -1;
|
||||
}
|
||||
custom_balls = n;
|
||||
} else {
|
||||
std::cerr << "Error: --custom-balls requiere un valor\n";
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Error: Opción desconocida '" << argv[i] << "'\n";
|
||||
printHelp();
|
||||
@@ -118,6 +132,9 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
Engine engine;
|
||||
|
||||
if (custom_balls > 0)
|
||||
engine.setCustomScenario(custom_balls); // pre-init: asigna campos antes del benchmark
|
||||
|
||||
if (!engine.initialize(width, height, zoom, fullscreen, initial_mode)) {
|
||||
std::cout << "¡Error al inicializar el engine!" << std::endl;
|
||||
return -1;
|
||||
|
||||
@@ -44,7 +44,10 @@ void SceneManager::changeScenario(int scenario_id, SimulationMode mode) {
|
||||
changeGravityDirection(GravityDirection::DOWN);
|
||||
|
||||
// Crear las bolas según el escenario
|
||||
for (int i = 0; i < BALL_COUNT_SCENARIOS[scenario_id]; ++i) {
|
||||
int ball_count = (scenario_id == CUSTOM_SCENARIO_IDX)
|
||||
? custom_ball_count_
|
||||
: BALL_COUNT_SCENARIOS[scenario_id];
|
||||
for (int i = 0; i < ball_count; ++i) {
|
||||
float X, Y, VX, VY;
|
||||
|
||||
// Inicialización según SimulationMode (RULES.md líneas 23-26)
|
||||
|
||||
@@ -50,11 +50,17 @@ class SceneManager {
|
||||
|
||||
/**
|
||||
* @brief Cambia el número de bolas según escenario
|
||||
* @param scenario_id Índice del escenario (0-7 para 10 a 50,000 bolas)
|
||||
* @param scenario_id Índice del escenario (0-7 para 10 a 50,000 bolas; 8 = custom)
|
||||
* @param mode Modo de simulación actual (afecta inicialización)
|
||||
*/
|
||||
void changeScenario(int scenario_id, SimulationMode mode);
|
||||
|
||||
/**
|
||||
* @brief Configura el número de bolas para el escenario custom (índice 8)
|
||||
* @param n Número de bolas del escenario custom
|
||||
*/
|
||||
void setCustomBallCount(int n) { custom_ball_count_ = n; }
|
||||
|
||||
/**
|
||||
* @brief Actualiza textura y tamaño de todas las bolas
|
||||
* @param new_texture Nueva textura compartida
|
||||
@@ -146,6 +152,7 @@ class SceneManager {
|
||||
std::vector<std::unique_ptr<Ball>> balls_;
|
||||
GravityDirection current_gravity_;
|
||||
int scenario_;
|
||||
int custom_ball_count_ = 0; // Número de bolas para escenario custom (índice 8)
|
||||
|
||||
// === Configuración de pantalla ===
|
||||
int screen_width_;
|
||||
|
||||
@@ -279,6 +279,8 @@ void UIManager::renderDebugHUD(const Engine* engine,
|
||||
// Máximo de pelotas en modos automáticos (resultado del benchmark)
|
||||
int max_auto_idx = engine->getMaxAutoScenario();
|
||||
int max_auto_balls = BALL_COUNT_SCENARIOS[max_auto_idx];
|
||||
if (engine->isCustomAutoAvailable() && engine->getCustomScenarioBalls() > max_auto_balls)
|
||||
max_auto_balls = engine->getCustomScenarioBalls();
|
||||
std::string max_auto_text;
|
||||
if (max_auto_balls >= 1000) {
|
||||
std::string count_str = std::to_string(max_auto_balls);
|
||||
|
||||
Reference in New Issue
Block a user