Refactor: Mover BALL_COUNT_SCENARIOS a defines.h + priorizar 1 capa

REFACTORING:
- Movido array de escenarios desde engine.h a defines.h
- Nombre más descriptivo: test_ → BALL_COUNT_SCENARIOS
- Ahora es constexpr y accesible globalmente

MEJORA PNG_SHAPE:
- Priorizar calidad 2D sobre profundidad 3D
- Reducir capas AGRESIVAMENTE hasta 1 (antes se detenía en 3)
- Condiciones más estrictas: < total (antes < total * 0.8)
- Vértices activados hasta 150 pelotas (antes 100)

FILOSOFÍA NUEVA:
1. Reducir capas hasta 1 (llenar bien el texto en 2D)
2. Si no alcanza: filas alternas en relleno
3. Si no alcanza: cambiar a bordes
4. Si no alcanza: filas alternas en bordes
5. Último recurso: vértices

RESULTADO ESPERADO:
- 500 pelotas: RELLENO completo 1 capa (texto lleno, sin 3D)
- 100 pelotas: BORDES completos 1 capa (todo visible)
- 50 pelotas: VÉRTICES (esqueleto visible)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 17:23:38 +02:00
parent d030d4270e
commit db3d4d6630
4 changed files with 19 additions and 25 deletions

View File

@@ -38,6 +38,9 @@ constexpr float GRAVITY_CHANGE_LATERAL_MAX = 0.08f; // Velocidad lateral máxim
// Configuración de spawn inicial de pelotas // Configuración de spawn inicial de pelotas
constexpr float BALL_SPAWN_MARGIN = 0.15f; // Margen lateral para spawn (0.25 = 25% a cada lado) constexpr float BALL_SPAWN_MARGIN = 0.15f; // Margen lateral para spawn (0.25 = 25% a cada lado)
// Escenarios de número de pelotas (teclas 1-8)
constexpr int BALL_COUNT_SCENARIOS[8] = {1, 10, 100, 500, 1000, 10000, 50000, 100000};
// Estructura para representar colores RGB // Estructura para representar colores RGB
struct Color { struct Color {
int r, g, b; // Componentes rojo, verde, azul (0-255) int r, g, b; // Componentes rojo, verde, azul (0-255)

View File

@@ -778,7 +778,7 @@ void Engine::initBalls(int value) {
changeGravityDirection(GravityDirection::DOWN); changeGravityDirection(GravityDirection::DOWN);
// Crear las bolas según el escenario // Crear las bolas según el escenario
for (int i = 0; i < test_.at(value); ++i) { for (int i = 0; i < BALL_COUNT_SCENARIOS[value]; ++i) {
const int SIGN = ((rand() % 2) * 2) - 1; // Genera un signo aleatorio (+ o -) const int SIGN = ((rand() % 2) * 2) - 1; // Genera un signo aleatorio (+ o -)
// Calcular spawn zone: margen a cada lado, zona central para spawn // Calcular spawn zone: margen a cada lado, zona central para spawn
const int margin = static_cast<int>(current_screen_width_ * BALL_SPAWN_MARGIN); const int margin = static_cast<int>(current_screen_width_ * BALL_SPAWN_MARGIN);
@@ -801,7 +801,7 @@ void Engine::setText() {
// Suprimir textos durante modos demo // Suprimir textos durante modos demo
if (demo_mode_enabled_ || demo_lite_enabled_) return; if (demo_mode_enabled_ || demo_lite_enabled_) return;
int num_balls = test_.at(scenario_); int num_balls = BALL_COUNT_SCENARIOS[scenario_];
if (num_balls == 1) { if (num_balls == 1) {
text_ = "1 PELOTA"; text_ = "1 PELOTA";
} else { } else {

View File

@@ -34,7 +34,6 @@ class Engine {
// Estado del simulador // Estado del simulador
std::vector<std::unique_ptr<Ball>> balls_; 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; GravityDirection current_gravity_ = GravityDirection::DOWN;
int scenario_ = 0; int scenario_ = 0;
bool should_exit_ = false; bool should_exit_ = false;

View File

@@ -135,20 +135,20 @@ void PNGShape::generatePoints(int num_points, float screen_width, float screen_h
<< ", total 3D: " << total_3d_points << ")\n"; << ", total 3D: " << total_3d_points << ")\n";
std::cout << "[PNG_SHAPE] Pelotas disponibles: " << num_points << "\n"; std::cout << "[PNG_SHAPE] Pelotas disponibles: " << num_points << "\n";
// NIVEL 2: Reducir capas de extrusión PRIMERO (antes de cambiar a bordes) // NIVEL 2: Reducir capas AGRESIVAMENTE hasta 1 (priorizar calidad 2D sobre profundidad 3D)
// Objetivo: Mantener relleno completo pero más fino // Objetivo: Llenar bien el texto en 2D antes de reducir píxeles
while (num_layers_ > 3 && num_points < static_cast<int>(total_3d_points) * 0.8f) { while (num_layers_ > 1 && num_points < static_cast<int>(total_3d_points)) {
num_layers_ = std::max(3, num_layers_ / 2); num_layers_ = std::max(1, num_layers_ / 2);
total_3d_points = num_2d_points * num_layers_; total_3d_points = num_2d_points * num_layers_;
std::cout << "[PNG_SHAPE] Nivel 2: Reduciendo capas a " << num_layers_ std::cout << "[PNG_SHAPE] Nivel 2: Reduciendo capas a " << num_layers_
<< " (puntos 3D: " << total_3d_points << ")\n"; << " (total 3D: " << total_3d_points << ")\n";
} }
// NIVEL 3: Filas alternas en RELLENO (mantiene densidad visual) // NIVEL 3: Filas alternas en RELLENO (solo si 1 capa no alcanza)
// Esto permite usar relleno incluso con pocas pelotas // Esto permite usar relleno incluso con pocas pelotas
int row_skip = 1; int row_skip = 1;
if (!PNG_USE_EDGES_ONLY) { // Solo si empezamos con relleno if (!PNG_USE_EDGES_ONLY) { // Solo si empezamos con relleno
while (row_skip < 4 && num_points < static_cast<int>(total_3d_points) * 0.8f) { while (row_skip < 5 && num_points < static_cast<int>(total_3d_points)) {
row_skip++; row_skip++;
// ✅ CLAVE: Recalcular desde el ORIGINAL cada vez (no desde el filtrado previo) // ✅ CLAVE: Recalcular desde el ORIGINAL cada vez (no desde el filtrado previo)
active_points_data = extractAlternateRows(filled_points_original, row_skip); active_points_data = extractAlternateRows(filled_points_original, row_skip);
@@ -160,8 +160,8 @@ void PNGShape::generatePoints(int num_points, float screen_width, float screen_h
} }
} }
// NIVEL 4: Cambiar a BORDES solo si relleno optimizado no es suficiente // NIVEL 4: Cambiar a BORDES (solo si relleno con filas alternas no alcanza)
if (!PNG_USE_EDGES_ONLY && num_points < static_cast<int>(total_3d_points) * 0.5f) { if (!PNG_USE_EDGES_ONLY && num_points < static_cast<int>(total_3d_points)) {
active_points_data = edge_points_original; active_points_data = edge_points_original;
mode_name = "BORDES (auto)"; mode_name = "BORDES (auto)";
num_2d_points = active_points_data.size(); num_2d_points = active_points_data.size();
@@ -171,8 +171,8 @@ void PNGShape::generatePoints(int num_points, float screen_width, float screen_h
<< ", necesarias: " << total_3d_points << ")\n"; << ", necesarias: " << total_3d_points << ")\n";
} }
// NIVEL 5: Filas alternas en BORDES (si aún no es suficiente) // NIVEL 5: Filas alternas en BORDES (si aún no alcanza)
while (row_skip < 8 && num_points < static_cast<int>(total_3d_points) * 0.7f) { while (row_skip < 8 && num_points < static_cast<int>(total_3d_points)) {
row_skip++; row_skip++;
// ✅ CLAVE: Recalcular desde edge_points_original cada vez // ✅ CLAVE: Recalcular desde edge_points_original cada vez
active_points_data = extractAlternateRows(edge_points_original, row_skip); active_points_data = extractAlternateRows(edge_points_original, row_skip);
@@ -185,16 +185,8 @@ void PNGShape::generatePoints(int num_points, float screen_width, float screen_h
} }
} }
// NIVEL 6: Reducir más las capas si aún sobran puntos // NIVEL 6: Vértices/esquinas (último recurso, muy pocas pelotas)
while (num_layers_ > 1 && num_points < static_cast<int>(total_3d_points) * 0.6f) { if (num_points < static_cast<int>(total_3d_points) && num_points < 150) {
num_layers_ = std::max(1, num_layers_ / 2);
total_3d_points = num_2d_points * num_layers_;
std::cout << "[PNG_SHAPE] Nivel 6: Reduciendo más capas a " << num_layers_
<< " (puntos 3D: " << total_3d_points << ")\n";
}
// NIVEL 7: Vértices/esquinas (último recurso, muy pocas pelotas)
if (num_points < static_cast<int>(total_3d_points) * 0.4f && num_points < 100) {
// Determinar desde qué conjunto extraer vértices (el que esté activo actualmente) // Determinar desde qué conjunto extraer vértices (el que esté activo actualmente)
const std::vector<Point2D>& source_for_vertices = (mode_name.find("BORDES") != std::string::npos) const std::vector<Point2D>& source_for_vertices = (mode_name.find("BORDES") != std::string::npos)
? edge_points_original ? edge_points_original
@@ -206,7 +198,7 @@ void PNGShape::generatePoints(int num_points, float screen_width, float screen_h
num_2d_points = active_points_data.size(); num_2d_points = active_points_data.size();
total_3d_points = num_2d_points * num_layers_; total_3d_points = num_2d_points * num_layers_;
mode_name = "VÉRTICES"; mode_name = "VÉRTICES";
std::cout << "[PNG_SHAPE] Nivel 7: Solo vértices (puntos 2D: " << num_2d_points << ")\n"; std::cout << "[PNG_SHAPE] Nivel 6: Solo vértices (puntos 2D: " << num_2d_points << ")\n";
} }
} }