treballant en PixelReveal
This commit is contained in:
@@ -34,7 +34,7 @@ enum class Options {
|
||||
|
||||
// --- Variables de estado globales ---
|
||||
#ifdef _DEBUG
|
||||
inline Scene current = Scene::GAME; // Escena actual
|
||||
inline Scene current = Scene::ENDING; // Escena actual
|
||||
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
|
||||
#else
|
||||
inline Scene current = Scene::LOGO; // Escena actual
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <algorithm> // Para min
|
||||
|
||||
#include "core/audio/audio.hpp" // Para Audio
|
||||
#include "core/input/global_inputs.hpp" // Para check
|
||||
#include "core/input/input.hpp" // Para Input
|
||||
#include "core/rendering/pixel_reveal.hpp" // Para PixelReveal
|
||||
#include "core/rendering/screen.hpp" // Para Screen
|
||||
#include "core/rendering/surface.hpp" // Para Surface
|
||||
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||
@@ -19,10 +18,12 @@
|
||||
#include "utils/delta_timer.hpp" // Para DeltaTimer
|
||||
#include "utils/utils.hpp" // Para PaletteColor
|
||||
|
||||
// Destructor
|
||||
Credits::~Credits() = default;
|
||||
|
||||
// Constructor
|
||||
Credits::Credits()
|
||||
: text_surface_(std::make_shared<Surface>(Options::game.width, Options::game.height)),
|
||||
cover_surface_(std::make_shared<Surface>(Options::game.width, Options::game.height)),
|
||||
shining_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimationData("shine.yaml"))),
|
||||
delta_timer_(std::make_unique<DeltaTimer>()) {
|
||||
// Configura la escena
|
||||
@@ -115,24 +116,8 @@ void Credits::fillTexture() {
|
||||
// Recoloca el sprite del brillo
|
||||
shining_sprite_->setPosX(POS_X + 2);
|
||||
|
||||
// Rellena la textura que cubre el texto con color transparente
|
||||
cover_surface_->clear(static_cast<Uint8>(PaletteColor::TRANSPARENT));
|
||||
|
||||
// Los primeros 8 pixels crea una malla
|
||||
auto color = static_cast<Uint8>(PaletteColor::BLACK);
|
||||
for (int i = 0; i < 256; i += 2) {
|
||||
cover_surface_->putPixel(i, 0, color);
|
||||
cover_surface_->putPixel(i, 2, color);
|
||||
cover_surface_->putPixel(i, 4, color);
|
||||
cover_surface_->putPixel(i, 6, color);
|
||||
|
||||
cover_surface_->putPixel(i + 1, 5, color);
|
||||
cover_surface_->putPixel(i + 1, 7, color);
|
||||
}
|
||||
|
||||
// El resto se rellena de color sólido
|
||||
SDL_FRect rect = {0, 8, 256, 192};
|
||||
cover_surface_->fillRect(&rect, color);
|
||||
// Crea el efecto de revelado pixel a pixel
|
||||
pixel_reveal_ = std::make_unique<PixelReveal>(Options::game.width, Options::game.height, PIXELS_PER_SECOND, STEP_DURATION, REVEAL_STEPS);
|
||||
}
|
||||
|
||||
// Actualiza las variables
|
||||
@@ -145,6 +130,8 @@ void Credits::update() {
|
||||
|
||||
updateState(DELTA_TIME); // Actualiza la máquina de estados
|
||||
|
||||
pixel_reveal_->update(reveal_time_); // Actualiza el efecto de revelado
|
||||
|
||||
// Actualiza el sprite con el brillo si está después del tiempo de inicio
|
||||
if (reveal_time_ > SHINE_START_TIME) {
|
||||
shining_sprite_->update(DELTA_TIME);
|
||||
@@ -239,11 +226,8 @@ void Credits::render() {
|
||||
// Dibuja la textura con el texto en pantalla
|
||||
text_surface_->render(0, 0);
|
||||
|
||||
// Dibuja la textura que cubre el texto
|
||||
// OFFSET basado en reveal_time_ (que se congela durante pausas, como counter_ original)
|
||||
const float OFFSET = std::min(reveal_time_ * REVEAL_SPEED / 8.0F, 192.0F / 2.0F);
|
||||
SDL_FRect src_rect = {0.0F, 0.0F, 256.0F, 192.0F - (OFFSET * 2.0F)};
|
||||
cover_surface_->render(0, static_cast<int>(OFFSET * 2.0F), &src_rect);
|
||||
// Dibuja la máscara de revelado pixel a pixel
|
||||
pixel_reveal_->render(0, 0);
|
||||
|
||||
// Dibuja el sprite con el brillo
|
||||
if (reveal_time_ > SHINE_START_TIME) {
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
#include <vector> // Para vector
|
||||
class SurfaceAnimatedSprite; // lines 11-11
|
||||
class Surface;
|
||||
class PixelReveal;
|
||||
class DeltaTimer;
|
||||
|
||||
class Credits {
|
||||
public:
|
||||
// --- Constructor y Destructor ---
|
||||
Credits();
|
||||
~Credits() = default;
|
||||
~Credits();
|
||||
|
||||
// --- Bucle principal ---
|
||||
void run();
|
||||
@@ -47,7 +48,9 @@ class Credits {
|
||||
static constexpr float TOTAL_DURATION = 20.0F; // 1200 frames @ 60fps
|
||||
static constexpr float SHINE_START_TIME = 12.833F; // 770 frames @ 60fps
|
||||
static constexpr float FADE_OUT_START = 19.167F; // 1150 frames @ 60fps
|
||||
static constexpr float REVEAL_SPEED = 60.0F; // counter equivalente por segundo @ 60fps
|
||||
static constexpr float PIXELS_PER_SECOND = 15.0F; // Filas reveladas por segundo (REVEAL_SPEED/8*2 = 60/8*2 = 15)
|
||||
static constexpr float STEP_DURATION = 2.0F / 60.0F; // Segundos por paso de revelado (2 frames @ 60fps)
|
||||
static constexpr int REVEAL_STEPS = 16; // Pasos de revelado por fila (más pasos = efecto más visible)
|
||||
|
||||
// --- Métodos privados ---
|
||||
void update(); // Actualiza las variables
|
||||
@@ -62,7 +65,7 @@ class Credits {
|
||||
// --- Variables miembro ---
|
||||
// Recursos gráficos
|
||||
std::shared_ptr<Surface> text_surface_; // Textura para dibujar el texto
|
||||
std::shared_ptr<Surface> cover_surface_; // Textura para cubrir el texto
|
||||
std::unique_ptr<PixelReveal> pixel_reveal_; // Efecto de revelado pixel a pixel
|
||||
std::shared_ptr<SurfaceAnimatedSprite> shining_sprite_; // Sprite para el brillo del corazón
|
||||
|
||||
// Temporizadores y estado
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "core/audio/audio.hpp" // Para Audio
|
||||
#include "core/input/global_inputs.hpp" // Para check
|
||||
#include "core/input/input.hpp" // Para Input
|
||||
#include "core/rendering/pixel_reveal.hpp" // Para PixelReveal
|
||||
#include "core/rendering/screen.hpp" // Para Screen
|
||||
#include "core/rendering/surface.hpp" // Para Surface
|
||||
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||
@@ -34,6 +35,9 @@ Ending::Ending()
|
||||
fillCoverTexture(); // Rellena la textura para la cortinilla
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Ending::~Ending() = default;
|
||||
|
||||
// Actualiza el objeto
|
||||
void Ending::update() {
|
||||
const float DELTA_TIME = delta_timer_->tick();
|
||||
@@ -60,8 +64,9 @@ void Ending::render() {
|
||||
// Skip rendering durante WARMING_UP
|
||||
if (state_ != State::WARMING_UP) {
|
||||
// Dibuja las imagenes de la escena
|
||||
sprite_pics_.at(current_scene_).image_sprite->render();
|
||||
sprite_pics_.at(current_scene_).cover_sprite->render();
|
||||
const auto& pic = sprite_pics_.at(current_scene_);
|
||||
pic.image_sprite->render();
|
||||
pic.pixel_reveal->render(pic.pos_x, pic.pos_y);
|
||||
|
||||
// Dibuja los textos de la escena
|
||||
for (const auto& ti : scenes_.at(current_scene_).text_index) {
|
||||
@@ -69,8 +74,9 @@ void Ending::render() {
|
||||
const float TRIGGER_TIME = static_cast<float>(ti.trigger) / 60.0F;
|
||||
|
||||
if (state_time_ > TRIGGER_TIME) {
|
||||
sprite_texts_.at(ti.index).image_sprite->render();
|
||||
sprite_texts_.at(ti.index).cover_sprite->render();
|
||||
const auto& txt = sprite_texts_.at(ti.index);
|
||||
txt.image_sprite->render();
|
||||
txt.pixel_reveal->render(txt.pos_x, txt.pos_y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,42 +225,14 @@ void Ending::iniTexts() {
|
||||
|
||||
// Crea el sprite
|
||||
st.image_sprite = std::make_shared<SurfaceSprite>(st.image_surface, 0, 0, st.image_surface->getWidth(), st.image_surface->getHeight());
|
||||
st.image_sprite->setPosition((Options::game.width - st.image_surface->getWidth()) / 2, txt.pos);
|
||||
st.pos_x = static_cast<int>((Options::game.width - st.image_surface->getWidth()) / 2);
|
||||
st.pos_y = txt.pos;
|
||||
st.image_sprite->setPosition(st.pos_x, st.pos_y);
|
||||
|
||||
// Crea la cover_surface
|
||||
st.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8);
|
||||
Screen::get()->setRendererSurface(st.cover_surface);
|
||||
// Crea el efecto de revelado pixel a pixel
|
||||
st.pixel_reveal = std::make_unique<PixelReveal>(static_cast<int>(WIDTH), static_cast<int>(HEIGHT), TEXT_PIXELS_PER_SECOND, STEP_DURATION, REVEAL_STEPS);
|
||||
|
||||
// Rellena la cover_surface con color transparente
|
||||
st.cover_surface->clear(static_cast<Uint8>(PaletteColor::TRANSPARENT));
|
||||
|
||||
// Crea una malla de 8 pixels de alto
|
||||
auto surface = Screen::get()->getRendererSurface();
|
||||
auto color = static_cast<Uint8>(PaletteColor::BLACK);
|
||||
for (int i = 0; i < WIDTH; i += 2) {
|
||||
surface->putPixel(i, 0, color);
|
||||
surface->putPixel(i, 2, color);
|
||||
surface->putPixel(i, 4, color);
|
||||
surface->putPixel(i, 6, color);
|
||||
|
||||
surface->putPixel(i + 1, 5, color);
|
||||
surface->putPixel(i + 1, 7, color);
|
||||
}
|
||||
|
||||
// El resto se rellena de color sólido
|
||||
SDL_FRect rect = {0, 8, WIDTH, HEIGHT};
|
||||
surface->fillRect(&rect, color);
|
||||
|
||||
// Crea el sprite
|
||||
st.cover_sprite = std::make_shared<SurfaceSprite>(st.cover_surface, 0, 0, st.cover_surface->getWidth(), st.cover_surface->getHeight() - 8);
|
||||
st.cover_sprite->setPosition((Options::game.width - st.cover_surface->getWidth()) / 2, txt.pos);
|
||||
st.cover_sprite->setClip(0, 8, st.cover_surface->getWidth(), st.cover_surface->getHeight());
|
||||
|
||||
// Inicializa variables
|
||||
st.cover_clip_desp = 8;
|
||||
st.cover_clip_height = HEIGHT;
|
||||
|
||||
sprite_texts_.push_back(st);
|
||||
sprite_texts_.push_back(std::move(st));
|
||||
Screen::get()->setRendererSurface(previuos_renderer);
|
||||
}
|
||||
}
|
||||
@@ -283,45 +261,15 @@ void Ending::iniPics() {
|
||||
const float HEIGHT = sp.image_surface->getHeight();
|
||||
|
||||
// Crea el sprite
|
||||
sp.pos_x = static_cast<int>((Options::game.width - WIDTH) / 2);
|
||||
sp.pos_y = pic.pos;
|
||||
sp.image_sprite = std::make_shared<SurfaceSprite>(sp.image_surface, 0, 0, WIDTH, HEIGHT);
|
||||
sp.image_sprite->setPosition((Options::game.width - WIDTH) / 2, pic.pos);
|
||||
sp.image_sprite->setPosition(sp.pos_x, sp.pos_y);
|
||||
|
||||
// Crea la cover_surface
|
||||
sp.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8);
|
||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
||||
Screen::get()->setRendererSurface(sp.cover_surface);
|
||||
// Crea el efecto de revelado pixel a pixel
|
||||
sp.pixel_reveal = std::make_unique<PixelReveal>(static_cast<int>(WIDTH), static_cast<int>(HEIGHT), IMAGE_PIXELS_PER_SECOND, STEP_DURATION, REVEAL_STEPS);
|
||||
|
||||
// Rellena la cover_surface con color transparente
|
||||
sp.cover_surface->clear(static_cast<Uint8>(PaletteColor::TRANSPARENT));
|
||||
|
||||
// Crea una malla en los primeros 8 pixels
|
||||
auto surface = Screen::get()->getRendererSurface();
|
||||
auto color = static_cast<Uint8>(PaletteColor::BLACK);
|
||||
for (int i = 0; i < WIDTH; i += 2) {
|
||||
surface->putPixel(i, 0, color);
|
||||
surface->putPixel(i, 2, color);
|
||||
surface->putPixel(i, 4, color);
|
||||
surface->putPixel(i, 6, color);
|
||||
|
||||
surface->putPixel(i + 1, 5, color);
|
||||
surface->putPixel(i + 1, 7, color);
|
||||
}
|
||||
|
||||
// El resto se rellena de color sólido
|
||||
SDL_FRect rect = {0.0F, 8.0F, WIDTH, HEIGHT};
|
||||
surface->fillRect(&rect, color);
|
||||
|
||||
// Crea el sprite
|
||||
sp.cover_sprite = std::make_shared<SurfaceSprite>(sp.cover_surface, 0, 0, sp.cover_surface->getWidth(), sp.cover_surface->getHeight() - 8);
|
||||
sp.cover_sprite->setPosition((Options::game.width - sp.cover_surface->getWidth()) / 2, pic.pos);
|
||||
sp.cover_sprite->setClip(0, 8, sp.cover_surface->getWidth(), sp.cover_surface->getHeight());
|
||||
|
||||
// Inicializa variables
|
||||
sp.cover_clip_desp = 8;
|
||||
sp.cover_clip_height = HEIGHT;
|
||||
|
||||
sprite_pics_.push_back(sp);
|
||||
Screen::get()->setRendererSurface(previuos_renderer);
|
||||
sprite_pics_.push_back(std::move(sp));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,68 +374,18 @@ void Ending::updateSpriteCovers() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Actualiza la cortinilla de los textos
|
||||
// Actualiza el revelado de los textos
|
||||
for (const auto& ti : scenes_.at(current_scene_).text_index) {
|
||||
// Convertir trigger de frames a segundos @ 60fps
|
||||
const float TRIGGER_TIME = static_cast<float>(ti.trigger) / 60.0F;
|
||||
|
||||
if (state_time_ > TRIGGER_TIME) {
|
||||
// Tiempo transcurrido desde que se activó el trigger
|
||||
const float TIME_SINCE_TRIGGER = state_time_ - TRIGGER_TIME;
|
||||
|
||||
// Píxeles revelados: tiempo * velocidad
|
||||
const float PIXELS_REVEALED = TIME_SINCE_TRIGGER * TEXT_REVEAL_SPEED;
|
||||
|
||||
// Obtiene el sprite
|
||||
auto sprite_text = sprite_texts_.at(ti.index);
|
||||
|
||||
// Obtener altura inicial de la superficie
|
||||
const float INITIAL_HEIGHT = sprite_text.image_surface->getHeight();
|
||||
const float Y_INITIAL = sprite_text.image_sprite->getY();
|
||||
|
||||
// Fase 1: Revelar malla decorativa (8 píxeles)
|
||||
if (PIXELS_REVEALED < 8.0F) {
|
||||
sprite_text.cover_clip_desp = static_cast<int>(8.0F - PIXELS_REVEALED);
|
||||
sprite_text.cover_clip_height = static_cast<int>(INITIAL_HEIGHT);
|
||||
sprite_text.cover_sprite->setY(Y_INITIAL);
|
||||
}
|
||||
// Fase 2: Revelar contenido
|
||||
else {
|
||||
sprite_text.cover_clip_desp = 0;
|
||||
const int CONTENT_PIXELS = PIXELS_REVEALED - 8.0F;
|
||||
sprite_text.cover_clip_height = std::max(0, static_cast<int>(INITIAL_HEIGHT - CONTENT_PIXELS));
|
||||
sprite_text.cover_sprite->setY(Y_INITIAL + static_cast<int>(CONTENT_PIXELS));
|
||||
}
|
||||
|
||||
sprite_text.cover_sprite->setClip(
|
||||
0,
|
||||
sprite_text.cover_clip_desp,
|
||||
sprite_text.cover_sprite->getWidth(),
|
||||
sprite_text.cover_clip_height);
|
||||
sprite_texts_.at(ti.index).pixel_reveal->update(TIME_SINCE_TRIGGER);
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza la cortinilla de las imágenes (revelación continua desde el inicio de la escena)
|
||||
auto sprite_pics = sprite_pics_.at(current_scene_);
|
||||
const float PIXELS_REVEALED = state_time_ * IMAGE_REVEAL_SPEED;
|
||||
const float INITIAL_HEIGHT = sprite_pics.image_surface->getHeight();
|
||||
const float Y_INITIAL = sprite_pics.image_sprite->getY();
|
||||
|
||||
// Fase 1: Revelar malla decorativa (8 píxeles)
|
||||
if (PIXELS_REVEALED < 8.0F) {
|
||||
sprite_pics.cover_clip_desp = static_cast<int>(8.0F - PIXELS_REVEALED);
|
||||
sprite_pics.cover_clip_height = static_cast<int>(INITIAL_HEIGHT);
|
||||
sprite_pics.cover_sprite->setY(Y_INITIAL);
|
||||
}
|
||||
// Fase 2: Revelar contenido
|
||||
else {
|
||||
sprite_pics.cover_clip_desp = 0;
|
||||
const int CONTENT_PIXELS = PIXELS_REVEALED - 8.0F;
|
||||
sprite_pics.cover_clip_height = std::max(0, static_cast<int>(INITIAL_HEIGHT - CONTENT_PIXELS));
|
||||
sprite_pics.cover_sprite->setY(Y_INITIAL + static_cast<int>(CONTENT_PIXELS));
|
||||
}
|
||||
|
||||
sprite_pics.cover_sprite->setClip(0, sprite_pics.cover_clip_desp, sprite_pics.cover_sprite->getWidth(), sprite_pics.cover_clip_height);
|
||||
// Actualiza el revelado de la imagen (desde el inicio de la escena)
|
||||
sprite_pics_.at(current_scene_).pixel_reveal->update(state_time_);
|
||||
}
|
||||
|
||||
// Comprueba si se ha de cambiar de escena
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
#include <vector> // Para vector
|
||||
class SurfaceSprite; // lines 8-8
|
||||
class Surface; // lines 9-9
|
||||
class PixelReveal;
|
||||
class DeltaTimer;
|
||||
|
||||
class Ending {
|
||||
public:
|
||||
// --- Constructor y Destructor ---
|
||||
Ending();
|
||||
~Ending() = default;
|
||||
~Ending();
|
||||
|
||||
// --- Bucle principal ---
|
||||
void run();
|
||||
@@ -34,10 +35,9 @@ class Ending {
|
||||
struct EndingSurface {
|
||||
std::shared_ptr<Surface> image_surface; // Surface a mostrar
|
||||
std::shared_ptr<SurfaceSprite> image_sprite; // SSprite para mostrar la textura
|
||||
std::shared_ptr<Surface> cover_surface; // Surface que cubre a la otra textura
|
||||
std::shared_ptr<SurfaceSprite> cover_sprite; // SSprite para mostrar la textura que cubre a la otra textura
|
||||
int cover_clip_desp{0}; // Desplazamiento del spriteClip de la textura de cobertura
|
||||
int cover_clip_height{0}; // Altura del spriteClip de la textura de cobertura
|
||||
std::unique_ptr<PixelReveal> pixel_reveal; // Efecto de revelado pixel a pixel
|
||||
int pos_x{0}; // Posición X de renderizado
|
||||
int pos_y{0}; // Posición Y de renderizado
|
||||
};
|
||||
|
||||
struct TextAndPosition {
|
||||
@@ -64,8 +64,10 @@ class Ending {
|
||||
static constexpr float SCENE_2_DURATION = 16.667F; // 1000 frames @ 60fps
|
||||
static constexpr float SCENE_3_DURATION = 13.333F; // 800 frames @ 60fps
|
||||
static constexpr float SCENE_4_DURATION = 16.667F; // 1000 frames @ 60fps
|
||||
static constexpr float TEXT_REVEAL_SPEED = 30.0F; // 2px cada 4 frames @ 60fps
|
||||
static constexpr float IMAGE_REVEAL_SPEED = 60.0F; // 2px cada 2 frames @ 60fps
|
||||
static constexpr float TEXT_PIXELS_PER_SECOND = 30.0F; // Filas de texto reveladas por segundo
|
||||
static constexpr float IMAGE_PIXELS_PER_SECOND = 60.0F; // Filas de imagen reveladas por segundo
|
||||
static constexpr float STEP_DURATION = 2.0F / 60.0F; // Segundos por paso de revelado (2 frames @ 60fps)
|
||||
static constexpr int REVEAL_STEPS = 10; // Pasos de revelado por fila (más pasos = efecto más visible)
|
||||
static constexpr float TEXT_LAPSE = 1.333F; // 80 frames @ 60fps
|
||||
static constexpr float FADEOUT_START_OFFSET = 1.667F; // Inicio fade-out 100 frames antes del fin
|
||||
static constexpr float ENDING_DURATION = 2.0F; // Duración del estado ENDING (2 segundos)
|
||||
|
||||
Reference in New Issue
Block a user