forked from jaildesigner-jailgames/jaildoctors_dilemma
afegit pixel_reveal a credits i a ending
This commit is contained in:
@@ -2,13 +2,14 @@
|
||||
|
||||
#include <algorithm> // Para min
|
||||
#include <numeric> // Para iota
|
||||
#include <queue> // Para queue (BFS en modo ORDERED)
|
||||
#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)
|
||||
PixelReveal::PixelReveal(int width, int height, float pixels_per_second, float step_duration, int num_steps, bool reverse, RevealMode mode)
|
||||
: cover_surface_(std::make_shared<Surface>(width, height)),
|
||||
reveal_order_(height),
|
||||
row_step_(height, 0),
|
||||
@@ -16,16 +17,51 @@ PixelReveal::PixelReveal(int width, int height, float pixels_per_second, float s
|
||||
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));
|
||||
num_steps_(num_steps),
|
||||
reverse_(reverse),
|
||||
mode_(mode) {
|
||||
// En modo normal: empieza negro sólido (se irá revelando a transparente)
|
||||
// En modo inverso: empieza transparente (se irá cubriendo de negro)
|
||||
const auto INITIAL_COLOR = reverse_ ? static_cast<Uint8>(PaletteColor::TRANSPARENT) : static_cast<Uint8>(PaletteColor::BLACK);
|
||||
cover_surface_->clear(INITIAL_COLOR);
|
||||
|
||||
// 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);
|
||||
if (mode_ == RevealMode::ORDERED) {
|
||||
// Calcula offsets por bisección BFS: 0, N/2, N/4, 3N/4, ...
|
||||
std::vector<int> offsets;
|
||||
offsets.push_back(0);
|
||||
std::queue<std::pair<int, int>> bq;
|
||||
bq.push({0, num_steps_});
|
||||
while (static_cast<int>(offsets.size()) < num_steps_) {
|
||||
auto [lo, hi] = bq.front();
|
||||
bq.pop();
|
||||
if (hi - lo <= 1) {
|
||||
continue;
|
||||
}
|
||||
const int MID = (lo + hi) / 2;
|
||||
offsets.push_back(MID);
|
||||
bq.push({lo, MID});
|
||||
bq.push({MID, hi});
|
||||
}
|
||||
// Genera el orden: para cada offset, todas las columnas col = offset, offset+N, offset+2N, ...
|
||||
std::vector<int> ordered_cols;
|
||||
ordered_cols.reserve(width_);
|
||||
for (const int off : offsets) {
|
||||
for (int col = off; col < width_; col += num_steps_) {
|
||||
ordered_cols.push_back(col);
|
||||
}
|
||||
}
|
||||
// Todas las filas usan el mismo orden (sin aleatoriedad)
|
||||
for (int r = 0; r < height_; r++) {
|
||||
reveal_order_[r] = ordered_cols;
|
||||
}
|
||||
} else {
|
||||
// Modo RANDOM: orden aleatorio 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +70,8 @@ PixelReveal::~PixelReveal() = default;
|
||||
|
||||
// Actualiza el estado del revelado
|
||||
void PixelReveal::update(float time_active) {
|
||||
const auto TRANSPARENT = static_cast<Uint8>(PaletteColor::TRANSPARENT);
|
||||
// En modo normal revela (pone transparente); en modo inverso cubre (pone negro)
|
||||
const auto PIXEL_COLOR = reverse_ ? static_cast<Uint8>(PaletteColor::BLACK) : static_cast<Uint8>(PaletteColor::TRANSPARENT);
|
||||
|
||||
for (int r = 0; r < height_; r++) {
|
||||
const float T_START = static_cast<float>(r) / pixels_per_second_;
|
||||
@@ -47,14 +84,14 @@ void PixelReveal::update(float time_active) {
|
||||
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
|
||||
// Procesa 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);
|
||||
cover_surface_->putPixel(COL, r, PIXEL_COLOR);
|
||||
}
|
||||
}
|
||||
row_step_[r] = STEPS;
|
||||
|
||||
@@ -6,11 +6,15 @@
|
||||
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.
|
||||
// Cada fila se revela en num_steps pasos, con píxeles en orden aleatorio u ordenado (bisección).
|
||||
class PixelReveal {
|
||||
public:
|
||||
// Modo de revelado: aleatorio por fila o en orden de bisección (dithering ordenado 1D)
|
||||
enum class RevealMode { RANDOM,
|
||||
ORDERED };
|
||||
|
||||
// Constructor
|
||||
PixelReveal(int width, int height, float pixels_per_second, float step_duration, int num_steps = 4);
|
||||
PixelReveal(int width, int height, float pixels_per_second, float step_duration, int num_steps = 4, bool reverse = false, RevealMode mode = RevealMode::RANDOM);
|
||||
|
||||
// Destructor definido en el .cpp para que unique_ptr<Surface> funcione con forward declaration
|
||||
~PixelReveal();
|
||||
@@ -25,12 +29,14 @@ class PixelReveal {
|
||||
[[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_)
|
||||
std::shared_ptr<Surface> cover_surface_; // Máscara negra que se va haciendo transparente
|
||||
std::vector<std::vector<int>> reveal_order_; // Orden de columnas por fila (aleatorio u ordenado por bisección)
|
||||
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
|
||||
bool reverse_; // Si true: transparente → negro (ocultar); si false: negro → transparente (revelar)
|
||||
RevealMode mode_; // Modo de revelado: aleatorio u ordenado por bisección
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user