Implementar zoom por profundidad Z con perspectiva 3D + toggle
NUEVAS CARACTERÍSTICAS: - Zoom por profundidad Z: Escala sprites según distancia (0.5x-1.5x) - Toggle con Numpad / (KP_DIVIDE) para activar/desactivar perspectiva - Fix transición figura→física: Reset automático de depth_scale a 1.0 - Texto informativo: "DEPTH ZOOM ON/OFF" IMPLEMENTACIÓN TÉCNICA: - Ball class: Nueva variable depth_scale_ (0.5-1.5) - Ball class: Getters/setters getDepthScale() / setDepthScale() - Engine::addSpriteToBatch(): Parámetro scale con valor defecto 1.0 - Engine::addSpriteToBatch(): Cálculo de vértices escalados centrados - Engine::updateShape(): Cálculo depth_scale = 0.5 + z_normalized * 1.0 - Engine::render(): Pasa depth_scale al batch en modo SHAPE - Engine::toggleShapeMode(): Reset depth_scale en salida de figura - Engine: Variable depth_zoom_enabled_ (true por defecto) - Batch rendering: Mantiene performance (sin llamadas individuales) EFECTO VISUAL: - Pelotas lejanas (Z-): Pequeñas (50%) y oscuras - Pelotas medias (Z=0): Normales (100%) y brillo medio - Pelotas cercanas (Z+): Grandes (150%) y brillantes - Perspectiva 3D realista combinada con Z-sorting CONTROLES: - Numpad /: Toggle zoom por profundidad (solo en modo SHAPE) - Por defecto: ACTIVADO para máximo realismo 3D README ACTUALIZADO: - Añadida tecla KP_/ a tabla de controles - Actualizada sección "Características Técnicas" - Añadida línea "Zoom por profundidad" en características - Actualizada sección "Uso" con control de perspectiva 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -346,6 +346,17 @@ void Engine::handleEvents() {
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_KP_DIVIDE:
|
||||
if (current_mode_ == SimulationMode::SHAPE) {
|
||||
depth_zoom_enabled_ = !depth_zoom_enabled_;
|
||||
text_ = depth_zoom_enabled_ ? "DEPTH ZOOM ON" : "DEPTH ZOOM OFF";
|
||||
int text_width = static_cast<int>(text_.length() * 8);
|
||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
||||
text_init_time_ = SDL_GetTicks();
|
||||
show_text_ = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_1:
|
||||
scenario_ = 0;
|
||||
initBalls(scenario_);
|
||||
@@ -443,6 +454,7 @@ void Engine::render() {
|
||||
SDL_FRect pos = balls_[idx]->getPosition();
|
||||
Color color = balls_[idx]->getColor();
|
||||
float brightness = balls_[idx]->getDepthBrightness();
|
||||
float depth_scale = balls_[idx]->getDepthScale();
|
||||
|
||||
// Mapear brightness de 0-1 a rango MIN-MAX
|
||||
float brightness_factor = (ROTOBALL_MIN_BRIGHTNESS + brightness *
|
||||
@@ -453,14 +465,14 @@ void Engine::render() {
|
||||
int g_mod = static_cast<int>(color.g * brightness_factor);
|
||||
int b_mod = static_cast<int>(color.b * brightness_factor);
|
||||
|
||||
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, r_mod, g_mod, b_mod);
|
||||
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, r_mod, g_mod, b_mod, depth_scale);
|
||||
}
|
||||
} else {
|
||||
// MODO PHYSICS: Renderizar en orden normal del vector
|
||||
// MODO PHYSICS: Renderizar en orden normal del vector (sin escala de profundidad)
|
||||
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);
|
||||
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, color.r, color.g, color.b, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,7 +786,7 @@ void Engine::renderGradientBackground() {
|
||||
SDL_RenderGeometry(renderer_, nullptr, bg_vertices, 4, bg_indices, 6);
|
||||
}
|
||||
|
||||
void Engine::addSpriteToBatch(float x, float y, float w, float h, int r, int g, int b) {
|
||||
void Engine::addSpriteToBatch(float x, float y, float w, float h, int r, int g, int b, float scale) {
|
||||
int vertex_index = static_cast<int>(batch_vertices_.size());
|
||||
|
||||
// Crear 4 vértices para el quad (2 triángulos)
|
||||
@@ -785,23 +797,29 @@ void Engine::addSpriteToBatch(float x, float y, float w, float h, int r, int g,
|
||||
float gf = g / 255.0f;
|
||||
float bf = b / 255.0f;
|
||||
|
||||
// Aplicar escala al tamaño (centrado en el punto x, y)
|
||||
float scaled_w = w * scale;
|
||||
float scaled_h = h * scale;
|
||||
float offset_x = (w - scaled_w) / 2.0f; // Offset para centrar
|
||||
float offset_y = (h - scaled_h) / 2.0f;
|
||||
|
||||
// Vértice superior izquierdo
|
||||
vertices[0].position = {x, y};
|
||||
vertices[0].position = {x + offset_x, y + offset_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].position = {x + offset_x + scaled_w, y + offset_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].position = {x + offset_x + scaled_w, y + offset_y + scaled_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].position = {x + offset_x, y + offset_y + scaled_h};
|
||||
vertices[3].tex_coord = {0.0f, 1.0f};
|
||||
vertices[3].color = {rf, gf, bf, 1.0f};
|
||||
|
||||
@@ -1010,9 +1028,10 @@ void Engine::toggleShapeMode(bool force_gravity_on_exit) {
|
||||
// Volver a modo física normal
|
||||
current_mode_ = SimulationMode::PHYSICS;
|
||||
|
||||
// Desactivar atracción - las pelotas conservan su velocidad tangencial actual
|
||||
// Desactivar atracción y resetear escala de profundidad
|
||||
for (auto& ball : balls_) {
|
||||
ball->enableRotoBallAttraction(false);
|
||||
ball->setDepthScale(1.0f); // Reset escala a 100% (evita "pop" visual)
|
||||
}
|
||||
|
||||
// Activar gravedad al salir (solo si se especifica)
|
||||
@@ -1120,6 +1139,11 @@ void Engine::updateShape() {
|
||||
float z_normalized = (z_3d + shape_size) / (2.0f * shape_size);
|
||||
z_normalized = std::max(0.0f, std::min(1.0f, z_normalized));
|
||||
balls_[i]->setDepthBrightness(z_normalized);
|
||||
|
||||
// Calcular escala según profundidad Z (perspectiva) - solo si está activado
|
||||
// 0.0 (fondo) → 0.5x, 0.5 (medio) → 1.0x, 1.0 (frente) → 1.5x
|
||||
float depth_scale = depth_zoom_enabled_ ? (0.5f + z_normalized * 1.0f) : 1.0f;
|
||||
balls_[i]->setDepthScale(depth_scale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user