Files
vibe3_physics/source/shapes/png_shape.h
Sergio Valor 042c3cad1a Implementar sistema de estados mutuamente excluyentes y fix PNG_SHAPE flip en LOGO
## 1. Sistema de Estados AppMode (MANUAL/DEMO/DEMO_LITE/LOGO)

**engine.h:**
- Creado enum AppMode con 4 estados mutuamente excluyentes
- Reemplazadas 4 flags booleanas por 2 variables de estado:
  * current_app_mode_: Modo actual
  * previous_app_mode_: Para restaurar al salir de LOGO
- Añadido método setState() para gestión centralizada

**engine.cpp:**
- Implementado setState() con configuración automática de timers
- Actualizado updateDemoMode() para usar current_app_mode_
- Actualizado handleEvents() para teclas D/L/K con setState()
- Actualizadas todas las referencias a flags antiguas (8 ubicaciones)
- enterLogoMode/exitLogoMode usan setState()

**Comportamiento:**
- Teclas D/L/K ahora desactivan otros modos automáticamente
- Al salir de LOGO vuelve al modo previo (DEMO/DEMO_LITE/MANUAL)

## 2. Ajuste Ratio DEMO:LOGO = 6:1

**defines.h:**
- Probabilidad DEMO→LOGO: 15% → 5% (más raro)
- Probabilidad DEMO_LITE→LOGO: 10% → 3%
- Probabilidad salir de LOGO: 25% → 60% (sale rápido)
- Intervalos LOGO: 4-8s → 3-5s (más corto que DEMO)

**Resultado:** DEMO pasa 6x más tiempo activo que LOGO

## 3. Fix PNG_SHAPE no hace flip en modo LOGO

**Bugs encontrados:**
1. next_idle_time_ inicializado a 5.0s (hardcoded) > intervalos LOGO (3-5s)
2. toggleShapeMode() recrea PNG_SHAPE → pierde is_logo_mode_=true

**Soluciones:**

**png_shape.cpp (constructor):**
- Inicializa next_idle_time_ con PNG_IDLE_TIME_MIN/MAX (no hardcoded)

**png_shape.h:**
- Añadidos includes: defines.h, <cstdlib>
- Flag is_logo_mode_ para distinguir MANUAL vs LOGO
- Expandido setLogoMode() para recalcular next_idle_time_ con rangos apropiados
- PNG_IDLE_TIME_MIN_LOGO/MAX_LOGO: 2.5-4.5s (ajustable en defines.h)

**engine.cpp (toggleShapeMode):**
- Detecta si vuelve a SHAPE en modo LOGO con PNG_SHAPE
- Restaura setLogoMode(true) después de recrear instancia

**defines.h:**
- PNG_IDLE_TIME_MIN/MAX = 0.5-2.0s (modo MANUAL)
- PNG_IDLE_TIME_MIN_LOGO/MAX_LOGO = 2.5-4.5s (modo LOGO)

**Resultado:** PNG_SHAPE ahora hace flip cada 2.5-4.5s en modo LOGO (visible antes de toggles)

## 4. Nuevas Texturas

**data/balls/big.png:** 16x16px (añadida)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-05 00:56:22 +02:00

82 lines
3.7 KiB
C++

#pragma once
#include "shape.h"
#include "../defines.h" // Para PNG_IDLE_TIME_MIN/MAX constantes
#include <vector>
#include <cstdlib> // Para rand()
// Figura: Shape generada desde PNG 1-bit (blanco sobre negro)
// Enfoque A: Extrusión 2D (implementado)
// Enfoque B: Voxelización 3D (preparado para futuro)
class PNGShape : public Shape {
private:
// Datos de la imagen cargada
int image_width_ = 0;
int image_height_ = 0;
std::vector<bool> pixel_data_; // Mapa de píxeles blancos (true = blanco)
// Puntos generados (Enfoque A: Extrusión 2D)
struct Point2D {
float x, y;
};
std::vector<Point2D> edge_points_; // Contorno (solo bordes) - ORIGINAL sin optimizar
std::vector<Point2D> filled_points_; // Relleno completo - ORIGINAL sin optimizar
std::vector<Point2D> optimized_points_; // Puntos finales optimizados (usado por getPoint3D)
// Parámetros de extrusión
float extrusion_depth_ = 0.0f; // Profundidad de extrusión en Z
int num_layers_ = 0; // Capas de extrusión (más capas = más denso)
// Rotación "legible" (de frente con volteretas ocasionales)
float angle_x_ = 0.0f;
float angle_y_ = 0.0f;
float idle_timer_ = 0.0f; // Timer para tiempo de frente
float flip_timer_ = 0.0f; // Timer para voltereta
float next_idle_time_ = 5.0f; // Próximo tiempo de espera (aleatorio)
bool is_flipping_ = false; // Estado: quieto o voltereta
int flip_axis_ = 0; // Eje de voltereta (0=X, 1=Y, 2=ambos)
// Pivoteo sutil en estado IDLE (similar a WAVE_GRID)
float tilt_x_ = 0.0f; // Oscilación sutil en eje X
float tilt_y_ = 0.0f; // Oscilación sutil en eje Y
// Modo LOGO (intervalos de flip más largos)
bool is_logo_mode_ = false; // true = usar intervalos LOGO (más lentos)
// Dimensiones normalizadas
float scale_factor_ = 1.0f;
float center_offset_x_ = 0.0f;
float center_offset_y_ = 0.0f;
int num_points_ = 0; // Total de puntos generados (para indexación)
// Métodos internos
bool loadPNG(const char* path); // Cargar PNG con stb_image
void detectEdges(); // Detectar contorno (Enfoque A)
void floodFill(); // Rellenar interior (Enfoque B - futuro)
void generateExtrudedPoints(); // Generar puntos con extrusión 2D
// Métodos de distribución adaptativa (funciones puras, no modifican parámetros)
std::vector<Point2D> extractAlternateRows(const std::vector<Point2D>& source, int row_skip); // Extraer filas alternas
std::vector<Point2D> extractCornerVertices(const std::vector<Point2D>& source); // Extraer vértices/esquinas
public:
// Constructor: recibe path relativo al PNG
PNGShape(const char* png_path = "data/shapes/jailgames.png");
void generatePoints(int num_points, float screen_width, float screen_height) override;
void update(float delta_time, float screen_width, float screen_height) override;
void getPoint3D(int index, float& x, float& y, float& z) const override;
const char* getName() const override { return "PNG SHAPE"; }
float getScaleFactor(float screen_height) const override;
// Control de modo LOGO (flip intervals más largos)
void setLogoMode(bool enable) {
is_logo_mode_ = enable;
// Recalcular next_idle_time_ con el rango apropiado
float idle_min = enable ? PNG_IDLE_TIME_MIN_LOGO : PNG_IDLE_TIME_MIN;
float idle_max = enable ? PNG_IDLE_TIME_MAX_LOGO : PNG_IDLE_TIME_MAX;
next_idle_time_ = idle_min + (rand() % 1000) / 1000.0f * (idle_max - idle_min);
}
};