79 lines
2.7 KiB
C++
79 lines
2.7 KiB
C++
#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;
|
|
}
|