canvi de pantalla amb easing

This commit is contained in:
2026-04-06 18:43:59 +02:00
parent eb605e2577
commit ef04500a44
5 changed files with 164 additions and 18 deletions

View File

@@ -29,6 +29,7 @@
#include "game/ui/console.hpp" // Para Console
#include "game/ui/notifier.hpp" // Para Notifier, NotificationText, CHEEVO_NO...
#include "utils/defines.hpp" // Para Tile::SIZE, PlayArea::HEIGHT, RoomBorder::BOTTOM
#include "utils/easing_functions.hpp" // Para Easing::cubicInOut
#include "utils/utils.hpp"
#ifdef _DEBUG
@@ -314,6 +315,9 @@ void Game::updatePlaying(float delta_time) {
// Actualiza los objetos
room_->update(delta_time);
if (transitioning_) {
transition_old_room_->update(delta_time);
}
switch (mode_) {
case Mode::GAME:
#ifdef _DEBUG
@@ -333,6 +337,14 @@ void Game::updatePlaying(float delta_time) {
checkIfPlayerIsAlive();
checkEndGame();
checkSomeCheevos();
// Avanzar transición
if (transitioning_) {
transition_timer_ += delta_time;
if (transition_timer_ >= TRANSITION_DURATION) {
endTransition();
}
}
break;
case Mode::DEMO:
@@ -408,6 +420,11 @@ void Game::updatePostFadeEnding(float delta_time) {
// Cambia al estado especificado y resetea los timers
void Game::transitionToState(State new_state) {
// Limpiar transición de pantalla si estaba activa
if (transitioning_) {
endTransition();
}
// Lógica de ENTRADA según el nuevo estado
if (new_state == State::BLACK_SCREEN) {
// Respawn room y player
@@ -450,25 +467,76 @@ void Game::renderPlaying() {
// Prepara para dibujar el frame
Screen::get()->start();
// Dibuja el mapa de tiles (siempre)
room_->renderMap();
#ifdef _DEBUG
// Si el editor está activo, delegar el renderizado de entidades y statusbar
if (MapEditor::get()->isActive()) {
room_->renderMap();
MapEditor::get()->render();
Screen::get()->render();
return;
}
#endif
// Dibuja los elementos del juego en orden
room_->renderEnemies();
room_->renderItems();
if (mode_ == Mode::GAME) {
player_->render();
if (transitioning_) {
// --- Transición animada entre pantallas ---
const float T = std::min(transition_timer_ / TRANSITION_DURATION, 1.0F);
const float P = Easing::cubicInOut(T);
// Calcular offsets (derivar uno del otro para evitar gap de 1px por truncamiento)
int old_ox = 0;
int old_oy = 0;
int new_ox = 0;
int new_oy = 0;
switch (transition_direction_) {
case Room::Border::RIGHT:
new_ox = static_cast<int>((1.0F - P) * PlayArea::WIDTH);
old_ox = new_ox - PlayArea::WIDTH;
break;
case Room::Border::LEFT:
new_ox = -static_cast<int>((1.0F - P) * PlayArea::WIDTH);
old_ox = new_ox + PlayArea::WIDTH;
break;
case Room::Border::BOTTOM:
new_oy = static_cast<int>((1.0F - P) * PlayArea::HEIGHT);
old_oy = new_oy - PlayArea::HEIGHT;
break;
case Room::Border::TOP:
new_oy = -static_cast<int>((1.0F - P) * PlayArea::HEIGHT);
old_oy = new_oy + PlayArea::HEIGHT;
break;
default:
break;
}
// Renderizar habitación saliente con su offset
Screen::get()->setRenderOffset(old_ox, old_oy);
transition_old_room_->renderMap();
transition_old_room_->renderEnemies();
transition_old_room_->renderItems();
// Renderizar habitación entrante + jugador con su offset
Screen::get()->setRenderOffset(new_ox, new_oy);
room_->renderMap();
room_->renderEnemies();
room_->renderItems();
if (mode_ == Mode::GAME) {
player_->render();
}
// Scoreboard sin offset
Screen::get()->setRenderOffset(0, 0);
scoreboard_->render();
} else {
// --- Renderizado normal ---
room_->renderMap();
room_->renderEnemies();
room_->renderItems();
if (mode_ == Mode::GAME) {
player_->render();
}
scoreboard_->render();
}
scoreboard_->render();
#ifdef _DEBUG
// Debug info
@@ -733,25 +801,56 @@ auto Game::changeRoom(const std::string& room_path) -> bool {
// Comprueba si el jugador esta en el borde de la pantalla
void Game::checkPlayerIsOnBorder() {
// No permitir transiciones encadenadas
if (transitioning_) {
return;
}
if (player_->isOnBorder()) {
const auto BORDER = player_->getBorder();
const auto ROOM_NAME = room_->getRoom(BORDER);
// Si puede cambiar de habitación, cambia
if (changeRoom(ROOM_NAME)) {
player_->switchBorders();
spawn_data_ = player_->getSpawnParams();
// Si no hay habitación adyacente
if (ROOM_NAME == "0") {
if (BORDER == Room::Border::BOTTOM) {
killPlayer();
}
return;
}
// Si ha llegado al fondo y no hay habitación, muere
if (BORDER == Room::Border::BOTTOM) {
killPlayer();
return;
// Guardar la habitación saliente
transition_old_room_ = room_;
transition_direction_ = BORDER;
// Crear nueva habitación y reposicionar jugador
if (changeRoom(ROOM_NAME)) {
player_->switchBorders();
spawn_data_ = player_->getSpawnParams();
// Iniciar transición animada
transitioning_ = true;
transition_timer_ = 0.0F;
} else {
// changeRoom falló, limpiar
transition_old_room_.reset();
transition_direction_ = Room::Border::NONE;
if (BORDER == Room::Border::BOTTOM) {
killPlayer();
}
}
}
}
// Finaliza la transición entre pantallas
void Game::endTransition() {
transitioning_ = false;
transition_timer_ = 0.0F;
transition_old_room_.reset();
transition_direction_ = Room::Border::NONE;
Screen::get()->setRenderOffset(0, 0);
}
// Comprueba las colisiones del jugador con los enemigos
auto Game::checkPlayerAndEnemies() -> bool {
const bool DEATH = room_->enemyCollision(player_->getCollider());

View File

@@ -8,8 +8,8 @@
#include <vector> // Para vector
#include "game/entities/player.hpp" // Para PlayerSpawn
#include "game/gameplay/room.hpp" // Para Room, Room::Border
#include "utils/delta_timer.hpp" // Para DeltaTimer
class Room; // lines 12-12
class RoomTracker; // lines 13-13
class Scoreboard; // lines 14-14
class Surface;
@@ -45,6 +45,7 @@ class Game {
static constexpr float DEMO_ROOM_DURATION = 6.0F; // Duración de cada habitación en modo demo en segundos (400 frames)
static constexpr float FADE_STEP_INTERVAL = 0.05F; // Intervalo entre pasos de fade en segundos
static constexpr float POST_FADE_DELAY = 2.0F; // Duración de la pantalla negra después del fade
static constexpr float TRANSITION_DURATION = 0.5F; // Duración de la transición entre pantallas en segundos
// --- Estructuras ---
struct DemoData {
@@ -80,6 +81,7 @@ class Game {
void checkSomeCheevos(); // Comprueba algunos logros
void checkEndGameCheevos(); // Comprueba los logros de completar el juego
void initPlayer(const Player::SpawnData& spawn_point, std::shared_ptr<Room> room); // Inicializa al jugador
void endTransition(); // Finaliza la transición entre pantallas
void keepMusicPlaying(); // Hace sonar la música
void demoInit(); // DEMO MODE: Inicializa las variables para el modo demo
void demoCheckRoomChange(float delta_time); // DEMO MODE: Comprueba si se ha de cambiar de habitación
@@ -109,6 +111,12 @@ class Game {
float state_time_{0.0F}; // Tiempo acumulado en el estado actual
float fade_accumulator_{0.0F}; // Acumulador de tiempo para el fade
// Transición animada entre pantallas
bool transitioning_{false}; // Indica si hay una transición en curso
float transition_timer_{0.0F}; // Tiempo transcurrido en la transición
std::shared_ptr<Room> transition_old_room_; // Habitación saliente (se mantiene viva durante la transición)
Room::Border transition_direction_{Room::Border::NONE}; // Dirección de la transición
// Variables de demo mode
DemoData demo_; // Variables para el modo demo