treballant en PixelReveal

This commit is contained in:
2026-03-19 08:20:03 +01:00
parent c4d4a3b930
commit 31bbaf997f
8 changed files with 167 additions and 165 deletions

View File

@@ -0,0 +1,78 @@
#include "core/rendering/pixel_reveal.hpp"
#include <algorithm> // Para min
#include <numeric> // Para iota
#include <random> // Para mt19937, shuffle
#include "core/rendering/surface.hpp" // Para Surface
#include "utils/utils.hpp" // Para PaletteColor
// Constructor
PixelReveal::PixelReveal(int width, int height, float pixels_per_second, float step_duration, int num_steps)
: cover_surface_(std::make_shared<Surface>(width, height)),
reveal_order_(height),
row_step_(height, 0),
width_(width),
height_(height),
pixels_per_second_(pixels_per_second),
step_duration_(step_duration),
num_steps_(num_steps) {
// Rellena la máscara con negro sólido
cover_surface_->clear(static_cast<Uint8>(PaletteColor::BLACK));
// Genera el orden aleatorio de columnas por fila usando la fila como semilla (reproducible)
for (int r = 0; r < height_; r++) {
reveal_order_[r].resize(width_);
std::iota(reveal_order_[r].begin(), reveal_order_[r].end(), 0);
std::mt19937 rng(static_cast<unsigned int>(r));
std::shuffle(reveal_order_[r].begin(), reveal_order_[r].end(), rng);
}
}
// Destructor
PixelReveal::~PixelReveal() = default;
// Actualiza el estado del revelado
void PixelReveal::update(float time_active) {
const auto TRANSPARENT = static_cast<Uint8>(PaletteColor::TRANSPARENT);
for (int r = 0; r < height_; r++) {
const float T_START = static_cast<float>(r) / pixels_per_second_;
const float TIME_IN_ROW = time_active - T_START;
if (TIME_IN_ROW < 0.0F) {
continue; // Esta fila aún no ha empezado
}
const int STEPS = std::min(num_steps_, static_cast<int>(TIME_IN_ROW / step_duration_));
if (STEPS > row_step_[r]) {
// Revela los píxeles de los pasos pendientes
for (int step = row_step_[r]; step < STEPS; step++) {
const int START_IDX = step * width_ / num_steps_;
const int END_IDX = (step == num_steps_ - 1) ? width_ : (step + 1) * width_ / num_steps_;
for (int idx = START_IDX; idx < END_IDX; idx++) {
const int COL = reveal_order_[r][idx];
cover_surface_->putPixel(COL, r, TRANSPARENT);
}
}
row_step_[r] = STEPS;
}
}
}
// Dibuja la máscara en la posición indicada
void PixelReveal::render(int dst_x, int dst_y) const {
cover_surface_->render(dst_x, dst_y);
}
// Indica si el revelado ha completado todas las filas
bool PixelReveal::isComplete() const {
for (const int step : row_step_) {
if (step < num_steps_) {
return false;
}
}
return true;
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include <memory> // Para shared_ptr
#include <vector> // Para vector
class Surface;
// Efecto de revelado pixel a pixel por filas, de arriba a abajo.
// Cada fila se revela en num_steps pasos, con píxeles aleatorios en cada paso.
class PixelReveal {
public:
// Constructor
PixelReveal(int width, int height, float pixels_per_second, float step_duration, int num_steps = 4);
// Destructor definido en el .cpp para que unique_ptr<Surface> funcione con forward declaration
~PixelReveal();
// Actualiza el estado del revelado según el tiempo transcurrido
void update(float time_active);
// Dibuja la máscara de revelado en la posición indicada
void render(int dst_x, int dst_y) const;
// Indica si el revelado ha completado todas las filas
[[nodiscard]] bool isComplete() const;
private:
std::shared_ptr<Surface> cover_surface_; // Máscara negra que se va haciendo transparente
std::vector<std::vector<int>> reveal_order_; // Orden aleatorio de columnas por fila
std::vector<int> row_step_; // Paso actual de revelado por fila (0..num_steps_)
int width_;
int height_;
float pixels_per_second_; // Filas reveladas por segundo
float step_duration_; // Segundos por paso dentro de una fila
int num_steps_; // Número de pasos de revelado por fila
};