Compare commits
3 Commits
770523ab08
...
6c49b34120
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c49b34120 | |||
| 0474c3166d | |||
| 01643d2c5e |
75
README.md
75
README.md
@@ -6,9 +6,10 @@
|
|||||||
|
|
||||||
- **Simulacion de fisica**: Gravedad, rebotes y colisiones con perdida de energia
|
- **Simulacion de fisica**: Gravedad, rebotes y colisiones con perdida de energia
|
||||||
- **Multiples escenarios**: 8 configuraciones predefinidas (1 a 100,000 pelotas)
|
- **Multiples escenarios**: 8 configuraciones predefinidas (1 a 100,000 pelotas)
|
||||||
|
- **Sistema de temas visuales**: 4 temas de colores con fondos degradados y paletas tematicas
|
||||||
- **Interactividad**: Controles de teclado para modificar el comportamiento
|
- **Interactividad**: Controles de teclado para modificar el comportamiento
|
||||||
- **Renderizado eficiente**: Uso de SDL3 con escalado logico
|
- **Renderizado batch optimizado**: Sistema de batch rendering con SDL_RenderGeometry para 50K+ sprites
|
||||||
- **Colores aleatorios**: Cada pelota tiene un color unico generado proceduralmente
|
- **Colores tematicos**: Paletas de 8 colores por tema aplicadas proceduralmente
|
||||||
- **Monitor de rendimiento**: Contador FPS en tiempo real
|
- **Monitor de rendimiento**: Contador FPS en tiempo real
|
||||||
- **Control V-Sync**: Activacion/desactivacion dinamica del V-Sync
|
- **Control V-Sync**: Activacion/desactivacion dinamica del V-Sync
|
||||||
|
|
||||||
@@ -18,6 +19,8 @@
|
|||||||
|-------|--------|
|
|-------|--------|
|
||||||
| `H` | **Alternar debug display (FPS, V-Sync, valores fisica)** |
|
| `H` | **Alternar debug display (FPS, V-Sync, valores fisica)** |
|
||||||
| `V` | **Alternar V-Sync ON/OFF** |
|
| `V` | **Alternar V-Sync ON/OFF** |
|
||||||
|
| `F1-F4` | **Seleccion directa de tema de colores (Atardecer/Oceano/Neon/Bosque)** |
|
||||||
|
| `T` | **Ciclar entre temas de colores** |
|
||||||
| `1-8` | Cambiar numero de pelotas (1, 10, 100, 500, 1K, 10K, 50K, 100K) |
|
| `1-8` | Cambiar numero de pelotas (1, 10, 100, 500, 1K, 10K, 50K, 100K) |
|
||||||
| `ESPACIO` | Impulsar todas las pelotas hacia arriba |
|
| `ESPACIO` | Impulsar todas las pelotas hacia arriba |
|
||||||
| `G` | Alternar direccion de la gravedad |
|
| `G` | Alternar direccion de la gravedad |
|
||||||
@@ -26,14 +29,43 @@
|
|||||||
## 📊 Informacion en Pantalla
|
## 📊 Informacion en Pantalla
|
||||||
|
|
||||||
- **Centro**: Numero de pelotas activas en **blanco** (temporal)
|
- **Centro**: Numero de pelotas activas en **blanco** (temporal)
|
||||||
|
- **Centro**: Nombre del tema activo en **color tematico** (temporal, debajo del contador)
|
||||||
|
|
||||||
### Debug Display (Tecla `H`)
|
### Debug Display (Tecla `H`)
|
||||||
|
|
||||||
Cuando se activa el debug display con la tecla `H`:
|
Cuando se activa el debug display con la tecla `H`:
|
||||||
|
|
||||||
- **Esquina superior izquierda**: Estado V-Sync (VSYNC: ON/OFF) en **cian**
|
- **Esquina superior izquierda**: Estado V-Sync (VSYNC ON/OFF) en **cian**
|
||||||
- **Esquina superior derecha**: Contador FPS en tiempo real en **amarillo**
|
- **Esquina superior derecha**: Contador FPS en tiempo real en **amarillo**
|
||||||
- **Linea 3**: Valores fisica primera pelota (GRAV, VY, FLOOR) en **magenta**
|
- **Lineas 3-5**: Valores fisica primera pelota (GRAV, VY, FLOOR) en **magenta**
|
||||||
|
- **Linea 6**: Tema activo (THEME SUNSET/OCEAN/NEON/FOREST) en **amarillo claro**
|
||||||
|
|
||||||
|
## 🎨 Sistema de Temas de Colores
|
||||||
|
|
||||||
|
**ViBe1 Delta** incluye 4 temas visuales que transforman completamente la apariencia del simulador:
|
||||||
|
|
||||||
|
### Temas Disponibles
|
||||||
|
|
||||||
|
| Tecla | Tema | Descripcion | Fondo | Paleta de Pelotas |
|
||||||
|
|-------|------|-------------|-------|-------------------|
|
||||||
|
| `F1` | **ATARDECER** | Colores calidos de puesta de sol | Degradado naranja-rojo | Tonos naranjas, rojos y amarillos |
|
||||||
|
| `F2` | **OCEANO** | Ambiente marino refrescante | Degradado azul-cian | Azules, cianes y verdes agua |
|
||||||
|
| `F3` | **NEON** | Colores vibrantes futuristas | Degradado magenta-cian | Magentas, cianes y rosas brillantes |
|
||||||
|
| `F4` | **BOSQUE** | Naturaleza verde relajante | Degradado verde oscuro-claro | Verdes naturales y tierra |
|
||||||
|
|
||||||
|
### Controles de Temas
|
||||||
|
|
||||||
|
- **Seleccion directa**: Usa `F1`, `F2`, `F3` o `F4` para cambiar inmediatamente al tema deseado
|
||||||
|
- **Ciclado secuencial**: Presiona `T` para avanzar al siguiente tema en orden
|
||||||
|
- **Indicador visual**: El nombre del tema aparece temporalmente en el centro de la pantalla con colores tematicos
|
||||||
|
- **Regeneracion automatica**: Las pelotas adoptan automaticamente la nueva paleta de colores al cambiar tema
|
||||||
|
|
||||||
|
### Detalles Tecnicos
|
||||||
|
|
||||||
|
- **Fondos degradados**: Implementados con `SDL_RenderGeometry` usando vertices con colores interpolados
|
||||||
|
- **Paletas tematicas**: 8 colores unicos por tema aplicados aleatoriamente a las pelotas
|
||||||
|
- **Rendimiento optimizado**: El cambio de tema solo regenera los colores, manteniendo la fisica
|
||||||
|
- **Compatibilidad completa**: Funciona con todos los escenarios (1 a 100,000 pelotas)
|
||||||
|
|
||||||
## 🏗️ Estructura del Proyecto
|
## 🏗️ Estructura del Proyecto
|
||||||
|
|
||||||
@@ -259,6 +291,41 @@ if (!balls.empty()) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 🚀 Sistema de Batch Rendering
|
||||||
|
|
||||||
|
### **Problema Original**
|
||||||
|
El renderizado individual de sprites era el principal cuello de botella:
|
||||||
|
- **50,000 bolas**: 50,000 llamadas `SDL_RenderTexture()` por frame
|
||||||
|
- **Resultado**: ~10 FPS (inutilizable)
|
||||||
|
|
||||||
|
### **Solución Implementada: SDL_RenderGeometry**
|
||||||
|
Batch rendering que agrupa todos los sprites en una sola llamada:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Recopilar datos de todas las bolas
|
||||||
|
for (auto &ball : balls) {
|
||||||
|
SDL_FRect pos = ball->getPosition();
|
||||||
|
Color color = ball->getColor();
|
||||||
|
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderizar TODAS las bolas en una sola llamada
|
||||||
|
SDL_RenderGeometry(renderer, texture->getSDLTexture(),
|
||||||
|
batch_vertices.data(), batch_vertices.size(),
|
||||||
|
batch_indices.data(), batch_indices.size());
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Arquitectura del Batch**
|
||||||
|
1. **Vértices**: 4 vértices por sprite (quad) con posición, UV y color
|
||||||
|
2. **Índices**: 6 índices por sprite (2 triángulos)
|
||||||
|
3. **Acumulación**: Todos los sprites se acumulan en vectores globales
|
||||||
|
4. **Renderizado**: Una sola llamada `SDL_RenderGeometry` por frame
|
||||||
|
|
||||||
|
### **Rendimiento Conseguido**
|
||||||
|
- **50,000 bolas**: >75 FPS constante (mejora de 750%)
|
||||||
|
- **100,000 bolas**: Fluido y jugable
|
||||||
|
- **Escalabilidad**: Preparado para renderizado masivo de sprites
|
||||||
|
|
||||||
## 🛠️ Desarrollo
|
## 🛠️ Desarrollo
|
||||||
|
|
||||||
Para contribuir al proyecto:
|
Para contribuir al proyecto:
|
||||||
|
|||||||
@@ -39,7 +39,15 @@ void Ball::update(float deltaTime)
|
|||||||
|
|
||||||
// Actualiza la posición en función de la velocidad (píxeles/segundo)
|
// Actualiza la posición en función de la velocidad (píxeles/segundo)
|
||||||
pos_.x += vx_ * deltaTime;
|
pos_.x += vx_ * deltaTime;
|
||||||
pos_.y += vy_ * deltaTime;
|
if (!on_floor_)
|
||||||
|
{
|
||||||
|
pos_.y += vy_ * deltaTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Si está en el suelo, mantenerla ahí
|
||||||
|
pos_.y = SCREEN_HEIGHT - pos_.h;
|
||||||
|
}
|
||||||
|
|
||||||
// Comprueba las colisiones con el lateral izquierdo
|
// Comprueba las colisiones con el lateral izquierdo
|
||||||
if (pos_.x < 0)
|
if (pos_.x < 0)
|
||||||
@@ -67,7 +75,7 @@ void Ball::update(float deltaTime)
|
|||||||
{
|
{
|
||||||
pos_.y = SCREEN_HEIGHT - pos_.h;
|
pos_.y = SCREEN_HEIGHT - pos_.h;
|
||||||
vy_ = -vy_ * loss_;
|
vy_ = -vy_ * loss_;
|
||||||
if (std::fabs(vy_) < 0.1f)
|
if (std::fabs(vy_) < 6.0f) // Convertir 0.1f frame-based a 6.0f time-based
|
||||||
{
|
{
|
||||||
vy_ = 0.0f;
|
vy_ = 0.0f;
|
||||||
on_floor_ = true;
|
on_floor_ = true;
|
||||||
@@ -77,8 +85,13 @@ void Ball::update(float deltaTime)
|
|||||||
// Aplica rozamiento al rodar por el suelo
|
// Aplica rozamiento al rodar por el suelo
|
||||||
if (on_floor_)
|
if (on_floor_)
|
||||||
{
|
{
|
||||||
vx_ = vx_ * 0.97f;
|
// Convertir rozamiento de frame-based a time-based
|
||||||
if (std::fabs(vx_) < 0.1f)
|
// 0.97f por frame equivale a pow(0.97f, 60 * deltaTime)
|
||||||
|
float friction_factor = pow(0.97f, 60.0f * deltaTime);
|
||||||
|
vx_ = vx_ * friction_factor;
|
||||||
|
|
||||||
|
// Umbral de parada ajustado para velocidades en píxeles/segundo
|
||||||
|
if (std::fabs(vx_) < 6.0f) // ~0.1f * 60 para time-based
|
||||||
{
|
{
|
||||||
vx_ = 0.0f;
|
vx_ = 0.0f;
|
||||||
stopped_ = true;
|
stopped_ = true;
|
||||||
|
|||||||
@@ -41,4 +41,8 @@ public:
|
|||||||
float getVelocityY() const { return vy_; }
|
float getVelocityY() const { return vy_; }
|
||||||
float getGravityForce() const { return gravity_force_; }
|
float getGravityForce() const { return gravity_force_; }
|
||||||
bool isOnFloor() const { return on_floor_; }
|
bool isOnFloor() const { return on_floor_; }
|
||||||
|
|
||||||
|
// Getters para batch rendering
|
||||||
|
SDL_FRect getPosition() const { return pos_; }
|
||||||
|
Color getColor() const { return color_; }
|
||||||
};
|
};
|
||||||
3
source/external/texture.h
vendored
3
source/external/texture.h
vendored
@@ -37,4 +37,7 @@ public:
|
|||||||
|
|
||||||
// Modula el color de la textura
|
// Modula el color de la textura
|
||||||
void setColor(int r, int g, int b);
|
void setColor(int r, int g, int b);
|
||||||
|
|
||||||
|
// Getter para batch rendering
|
||||||
|
SDL_Texture* getSDLTexture() const { return texture_; }
|
||||||
};
|
};
|
||||||
|
|||||||
249
source/main.cpp
249
source/main.cpp
@@ -41,7 +41,7 @@ std::string fps_text = "FPS: 0"; // Texto del contador de FPS
|
|||||||
|
|
||||||
// Variables para V-Sync
|
// Variables para V-Sync
|
||||||
bool vsync_enabled = true; // Estado inicial del V-Sync (activado por defecto)
|
bool vsync_enabled = true; // Estado inicial del V-Sync (activado por defecto)
|
||||||
std::string vsync_text = "VSYNC: ON"; // Texto del estado V-Sync
|
std::string vsync_text = "VSYNC ON"; // Texto del estado V-Sync
|
||||||
|
|
||||||
// Variables para Delta Time
|
// Variables para Delta Time
|
||||||
Uint64 last_frame_time = 0; // Tiempo del último frame en milisegundos
|
Uint64 last_frame_time = 0; // Tiempo del último frame en milisegundos
|
||||||
@@ -50,6 +50,155 @@ float delta_time = 0.0f; // Tiempo transcurrido desde el último frame en seg
|
|||||||
// Variables para Debug Display
|
// Variables para Debug Display
|
||||||
bool show_debug = false; // Debug display desactivado por defecto
|
bool show_debug = false; // Debug display desactivado por defecto
|
||||||
|
|
||||||
|
// Sistema de temas de colores
|
||||||
|
enum class ColorTheme {
|
||||||
|
SUNSET = 0,
|
||||||
|
OCEAN = 1,
|
||||||
|
NEON = 2,
|
||||||
|
FOREST = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorTheme current_theme = ColorTheme::SUNSET;
|
||||||
|
std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"};
|
||||||
|
|
||||||
|
struct ThemeColors {
|
||||||
|
// Colores de fondo (superior -> inferior)
|
||||||
|
float bg_top_r, bg_top_g, bg_top_b;
|
||||||
|
float bg_bottom_r, bg_bottom_g, bg_bottom_b;
|
||||||
|
|
||||||
|
// Paletas de colores para bolas (RGB 0-255)
|
||||||
|
int ball_colors[8][3]; // 8 colores por tema
|
||||||
|
};
|
||||||
|
|
||||||
|
ThemeColors themes[4] = {
|
||||||
|
// SUNSET: Naranjas, rojos, amarillos, rosas
|
||||||
|
{
|
||||||
|
180.0f/255.0f, 140.0f/255.0f, 100.0f/255.0f, // Fondo superior (naranja suave)
|
||||||
|
40.0f/255.0f, 20.0f/255.0f, 60.0f/255.0f, // Fondo inferior (púrpura oscuro)
|
||||||
|
{{255, 140, 0}, {255, 69, 0}, {255, 215, 0}, {255, 20, 147}, // Bolas sunset
|
||||||
|
{255, 99, 71}, {255, 165, 0}, {255, 192, 203}, {220, 20, 60}}
|
||||||
|
},
|
||||||
|
// OCEAN: Azules, cianes, verdes agua, blancos
|
||||||
|
{
|
||||||
|
100.0f/255.0f, 150.0f/255.0f, 200.0f/255.0f, // Fondo superior (azul cielo)
|
||||||
|
20.0f/255.0f, 40.0f/255.0f, 80.0f/255.0f, // Fondo inferior (azul marino)
|
||||||
|
{{0, 191, 255}, {0, 255, 255}, {32, 178, 170}, {176, 224, 230}, // Bolas ocean
|
||||||
|
{70, 130, 180}, {0, 206, 209}, {240, 248, 255}, {64, 224, 208}}
|
||||||
|
},
|
||||||
|
// NEON: Cian, magenta, verde lima, amarillo vibrante
|
||||||
|
{
|
||||||
|
20.0f/255.0f, 20.0f/255.0f, 40.0f/255.0f, // Fondo superior (negro azulado)
|
||||||
|
0.0f/255.0f, 0.0f/255.0f, 0.0f/255.0f, // Fondo inferior (negro)
|
||||||
|
{{0, 255, 255}, {255, 0, 255}, {50, 205, 50}, {255, 255, 0}, // Bolas neon
|
||||||
|
{255, 20, 147}, {0, 255, 127}, {138, 43, 226}, {255, 69, 0}}
|
||||||
|
},
|
||||||
|
// FOREST: Verdes, marrones, amarillos otoño
|
||||||
|
{
|
||||||
|
144.0f/255.0f, 238.0f/255.0f, 144.0f/255.0f, // Fondo superior (verde claro)
|
||||||
|
101.0f/255.0f, 67.0f/255.0f, 33.0f/255.0f, // Fondo inferior (marrón tierra)
|
||||||
|
{{34, 139, 34}, {107, 142, 35}, {154, 205, 50}, {255, 215, 0}, // Bolas forest
|
||||||
|
{210, 180, 140}, {160, 82, 45}, {218, 165, 32}, {50, 205, 50}}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Variables para Batch Rendering
|
||||||
|
std::vector<SDL_Vertex> batch_vertices;
|
||||||
|
std::vector<int> batch_indices;
|
||||||
|
|
||||||
|
// Función para renderizar fondo degradado
|
||||||
|
void renderGradientBackground()
|
||||||
|
{
|
||||||
|
// Crear quad de pantalla completa con degradado
|
||||||
|
SDL_Vertex bg_vertices[4];
|
||||||
|
|
||||||
|
// Obtener colores del tema actual
|
||||||
|
ThemeColors& theme = themes[static_cast<int>(current_theme)];
|
||||||
|
|
||||||
|
float top_r = theme.bg_top_r;
|
||||||
|
float top_g = theme.bg_top_g;
|
||||||
|
float top_b = theme.bg_top_b;
|
||||||
|
|
||||||
|
float bottom_r = theme.bg_bottom_r;
|
||||||
|
float bottom_g = theme.bg_bottom_g;
|
||||||
|
float bottom_b = theme.bg_bottom_b;
|
||||||
|
|
||||||
|
// Vértice superior izquierdo
|
||||||
|
bg_vertices[0].position = {0, 0};
|
||||||
|
bg_vertices[0].tex_coord = {0.0f, 0.0f};
|
||||||
|
bg_vertices[0].color = {top_r, top_g, top_b, 1.0f};
|
||||||
|
|
||||||
|
// Vértice superior derecho
|
||||||
|
bg_vertices[1].position = {SCREEN_WIDTH, 0};
|
||||||
|
bg_vertices[1].tex_coord = {1.0f, 0.0f};
|
||||||
|
bg_vertices[1].color = {top_r, top_g, top_b, 1.0f};
|
||||||
|
|
||||||
|
// Vértice inferior derecho
|
||||||
|
bg_vertices[2].position = {SCREEN_WIDTH, SCREEN_HEIGHT};
|
||||||
|
bg_vertices[2].tex_coord = {1.0f, 1.0f};
|
||||||
|
bg_vertices[2].color = {bottom_r, bottom_g, bottom_b, 1.0f};
|
||||||
|
|
||||||
|
// Vértice inferior izquierdo
|
||||||
|
bg_vertices[3].position = {0, SCREEN_HEIGHT};
|
||||||
|
bg_vertices[3].tex_coord = {0.0f, 1.0f};
|
||||||
|
bg_vertices[3].color = {bottom_r, bottom_g, bottom_b, 1.0f};
|
||||||
|
|
||||||
|
// Índices para 2 triángulos
|
||||||
|
int bg_indices[6] = {0, 1, 2, 2, 3, 0};
|
||||||
|
|
||||||
|
// Renderizar sin textura (nullptr)
|
||||||
|
SDL_RenderGeometry(renderer, nullptr, bg_vertices, 4, bg_indices, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para añadir un sprite al batch
|
||||||
|
void addSpriteToBatch(float x, float y, float w, float h, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
int vertex_index = static_cast<int>(batch_vertices.size());
|
||||||
|
|
||||||
|
// Crear 4 vértices para el quad (2 triángulos)
|
||||||
|
SDL_Vertex vertices[4];
|
||||||
|
|
||||||
|
// Convertir colores de Uint8 (0-255) a float (0.0-1.0)
|
||||||
|
float rf = r / 255.0f;
|
||||||
|
float gf = g / 255.0f;
|
||||||
|
float bf = b / 255.0f;
|
||||||
|
|
||||||
|
// Vértice superior izquierdo
|
||||||
|
vertices[0].position = {x, y};
|
||||||
|
vertices[0].tex_coord = {0.0f, 0.0f};
|
||||||
|
vertices[0].color = {rf, gf, bf, 1.0f};
|
||||||
|
|
||||||
|
// Vértice superior derecho
|
||||||
|
vertices[1].position = {x + w, y};
|
||||||
|
vertices[1].tex_coord = {1.0f, 0.0f};
|
||||||
|
vertices[1].color = {rf, gf, bf, 1.0f};
|
||||||
|
|
||||||
|
// Vértice inferior derecho
|
||||||
|
vertices[2].position = {x + w, y + h};
|
||||||
|
vertices[2].tex_coord = {1.0f, 1.0f};
|
||||||
|
vertices[2].color = {rf, gf, bf, 1.0f};
|
||||||
|
|
||||||
|
// Vértice inferior izquierdo
|
||||||
|
vertices[3].position = {x, y + h};
|
||||||
|
vertices[3].tex_coord = {0.0f, 1.0f};
|
||||||
|
vertices[3].color = {rf, gf, bf, 1.0f};
|
||||||
|
|
||||||
|
// Añadir vértices al batch
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
batch_vertices.push_back(vertices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Añadir índices para 2 triángulos (6 índices por sprite)
|
||||||
|
// Triángulo 1: 0,1,2
|
||||||
|
batch_indices.push_back(vertex_index + 0);
|
||||||
|
batch_indices.push_back(vertex_index + 1);
|
||||||
|
batch_indices.push_back(vertex_index + 2);
|
||||||
|
|
||||||
|
// Triángulo 2: 2,3,0
|
||||||
|
batch_indices.push_back(vertex_index + 2);
|
||||||
|
batch_indices.push_back(vertex_index + 3);
|
||||||
|
batch_indices.push_back(vertex_index + 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Establece el texto en pantalla mostrando el número de bolas actuales
|
// Establece el texto en pantalla mostrando el número de bolas actuales
|
||||||
void setText()
|
void setText()
|
||||||
{
|
{
|
||||||
@@ -71,7 +220,12 @@ void initBalls(int value)
|
|||||||
const float X = (rand() % (SCREEN_WIDTH / 2)) + (SCREEN_WIDTH / 4); // Posición inicial en X
|
const float X = (rand() % (SCREEN_WIDTH / 2)) + (SCREEN_WIDTH / 4); // Posición inicial en X
|
||||||
const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X
|
const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X
|
||||||
const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y
|
const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y
|
||||||
const Color COLOR = {(rand() % 192) + 32, (rand() % 192) + 32, (rand() % 192) + 32}; // Color aleatorio
|
// Seleccionar color de la paleta del tema actual
|
||||||
|
ThemeColors& theme = themes[static_cast<int>(current_theme)];
|
||||||
|
int color_index = rand() % 8; // 8 colores por tema
|
||||||
|
const Color COLOR = {theme.ball_colors[color_index][0],
|
||||||
|
theme.ball_colors[color_index][1],
|
||||||
|
theme.ball_colors[color_index][2]};
|
||||||
balls.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture));
|
balls.emplace_back(std::make_unique<Ball>(X, VX, VY, COLOR, texture));
|
||||||
}
|
}
|
||||||
setText(); // Actualiza el texto
|
setText(); // Actualiza el texto
|
||||||
@@ -102,7 +256,7 @@ void switchBallsGravity()
|
|||||||
void toggleVSync()
|
void toggleVSync()
|
||||||
{
|
{
|
||||||
vsync_enabled = !vsync_enabled;
|
vsync_enabled = !vsync_enabled;
|
||||||
vsync_text = vsync_enabled ? "VSYNC: ON" : "VSYNC: OFF";
|
vsync_text = vsync_enabled ? "VSYNC ON" : "VSYNC OFF";
|
||||||
|
|
||||||
// Aplicar el cambio de V-Sync al renderizador
|
// Aplicar el cambio de V-Sync al renderizador
|
||||||
SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0);
|
SDL_SetRenderVSync(renderer, vsync_enabled ? 1 : 0);
|
||||||
@@ -231,6 +385,32 @@ void checkEvents()
|
|||||||
show_debug = !show_debug;
|
show_debug = !show_debug;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDLK_T:
|
||||||
|
// Ciclar al siguiente tema
|
||||||
|
current_theme = static_cast<ColorTheme>((static_cast<int>(current_theme) + 1) % 4);
|
||||||
|
initBalls(scenario); // Regenerar bolas con nueva paleta
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F1:
|
||||||
|
current_theme = ColorTheme::SUNSET;
|
||||||
|
initBalls(scenario);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F2:
|
||||||
|
current_theme = ColorTheme::OCEAN;
|
||||||
|
initBalls(scenario);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F3:
|
||||||
|
current_theme = ColorTheme::NEON;
|
||||||
|
initBalls(scenario);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F4:
|
||||||
|
current_theme = ColorTheme::FOREST;
|
||||||
|
initBalls(scenario);
|
||||||
|
break;
|
||||||
|
|
||||||
case SDLK_1:
|
case SDLK_1:
|
||||||
scenario = 0;
|
scenario = 0;
|
||||||
initBalls(scenario);
|
initBalls(scenario);
|
||||||
@@ -305,17 +485,52 @@ void update()
|
|||||||
// Renderiza el contenido en la pantalla
|
// Renderiza el contenido en la pantalla
|
||||||
void render()
|
void render()
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255);
|
// Renderizar fondo degradado en lugar de color sólido
|
||||||
SDL_RenderClear(renderer);
|
renderGradientBackground();
|
||||||
|
|
||||||
|
// Limpiar batches del frame anterior
|
||||||
|
batch_vertices.clear();
|
||||||
|
batch_indices.clear();
|
||||||
|
|
||||||
|
// Recopilar datos de todas las bolas para batch rendering
|
||||||
for (auto &ball : balls)
|
for (auto &ball : balls)
|
||||||
{
|
{
|
||||||
ball->render();
|
// En lugar de ball->render(), obtener datos para batch
|
||||||
|
SDL_FRect pos = ball->getPosition();
|
||||||
|
Color color = ball->getColor();
|
||||||
|
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderizar todas las bolas en una sola llamada
|
||||||
|
if (!batch_vertices.empty())
|
||||||
|
{
|
||||||
|
SDL_RenderGeometry(renderer, texture->getSDLTexture(),
|
||||||
|
batch_vertices.data(), static_cast<int>(batch_vertices.size()),
|
||||||
|
batch_indices.data(), static_cast<int>(batch_indices.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_text)
|
if (show_text)
|
||||||
{
|
{
|
||||||
dbg_print(text_pos, 8, text.c_str(), 255, 255, 255);
|
dbg_print(text_pos, 8, text.c_str(), 255, 255, 255);
|
||||||
|
|
||||||
|
// Mostrar nombre del tema en castellano debajo del número de pelotas
|
||||||
|
std::string theme_names_es[] = {"ATARDECER", "OCEANO", "NEON", "BOSQUE"};
|
||||||
|
std::string theme_name = theme_names_es[static_cast<int>(current_theme)];
|
||||||
|
int theme_text_width = static_cast<int>(theme_name.length() * 8); // 8 píxeles por carácter
|
||||||
|
int theme_x = (SCREEN_WIDTH - theme_text_width) / 2; // Centrar horizontalmente
|
||||||
|
|
||||||
|
// Colores acordes a cada tema
|
||||||
|
int theme_colors[][3] = {
|
||||||
|
{255, 140, 60}, // ATARDECER: Naranja cálido
|
||||||
|
{80, 200, 255}, // OCEANO: Azul océano
|
||||||
|
{255, 60, 255}, // NEON: Magenta brillante
|
||||||
|
{100, 255, 100} // BOSQUE: Verde natural
|
||||||
|
};
|
||||||
|
int theme_idx = static_cast<int>(current_theme);
|
||||||
|
dbg_print(theme_x, 24, theme_name.c_str(),
|
||||||
|
theme_colors[theme_idx][0],
|
||||||
|
theme_colors[theme_idx][1],
|
||||||
|
theme_colors[theme_idx][2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug display (solo si está activado con tecla H)
|
// Debug display (solo si está activado con tecla H)
|
||||||
@@ -332,11 +547,25 @@ void render()
|
|||||||
// Debug: Mostrar valores de la primera pelota (si existe)
|
// Debug: Mostrar valores de la primera pelota (si existe)
|
||||||
if (!balls.empty())
|
if (!balls.empty())
|
||||||
{
|
{
|
||||||
std::string debug_text = "GRAV: " + std::to_string(balls[0]->getGravityForce()) +
|
// Línea 1: Gravedad (solo números enteros)
|
||||||
" VY: " + std::to_string(balls[0]->getVelocityY()) +
|
int grav_int = static_cast<int>(balls[0]->getGravityForce());
|
||||||
" FLOOR: " + (balls[0]->isOnFloor() ? "YES" : "NO");
|
std::string grav_text = "GRAV " + std::to_string(grav_int);
|
||||||
dbg_print(8, 24, debug_text.c_str(), 255, 0, 255); // Magenta para debug
|
dbg_print(8, 24, grav_text.c_str(), 255, 0, 255); // Magenta para debug
|
||||||
|
|
||||||
|
// Línea 2: Velocidad Y (solo números enteros)
|
||||||
|
int vy_int = static_cast<int>(balls[0]->getVelocityY());
|
||||||
|
std::string vy_text = "VY " + std::to_string(vy_int);
|
||||||
|
dbg_print(8, 32, vy_text.c_str(), 255, 0, 255); // Magenta para debug
|
||||||
|
|
||||||
|
// Línea 3: Estado suelo
|
||||||
|
std::string floor_text = balls[0]->isOnFloor() ? "FLOOR YES" : "FLOOR NO";
|
||||||
|
dbg_print(8, 40, floor_text.c_str(), 255, 0, 255); // Magenta para debug
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug: Mostrar tema actual
|
||||||
|
std::string theme_names[] = {"SUNSET", "OCEAN", "NEON", "FOREST"};
|
||||||
|
std::string theme_text = "THEME " + theme_names[static_cast<int>(current_theme)];
|
||||||
|
dbg_print(8, 48, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
|
|||||||
Reference in New Issue
Block a user