From a50223fcd7cdcdc17d219a7729e2ecef510cebb3 Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 7 Apr 2026 13:36:18 +0200 Subject: [PATCH] proves --- source/game/entities/player.cpp | 134 +++++++++++++----- source/game/entities/player.hpp | 15 +- source/game/scenes/game.cpp | 241 ++++++++++++++++++-------------- source/game/scenes/game.hpp | 10 +- 4 files changed, 257 insertions(+), 143 deletions(-) diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index fceb5b8..f79b3da 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -66,7 +66,8 @@ void Player::update(float delta_time) { checkFalling(); // 6. Kill tiles - if (room_->getTileCollider().touchesKillTile(x_, y_, WIDTH, HEIGHT)) { + auto [ktc, kox, koy] = getCollisionContext(); + if (ktc.touchesKillTile(x_ + kox, y_ + koy, WIDTH, HEIGHT)) { markAsDead(); } @@ -190,11 +191,11 @@ void Player::handleJumpAndDrop() { // Drop-through: plataforma passable if (wanna_down_ && state_ == State::ON_GROUND) { - const auto& tc = room_->getTileCollider(); - float foot_y = y_ + HEIGHT; + auto [tc, ox, oy] = getCollisionContext(); + float foot_y = (y_ + oy) + HEIGHT; int foot_row = static_cast(foot_y) / Tile::SIZE; - int left_col = static_cast(x_) / Tile::SIZE; - int right_col = static_cast(x_ + WIDTH - 1) / Tile::SIZE; + int left_col = static_cast(x_ + ox) / Tile::SIZE; + int right_col = static_cast((x_ + ox) + WIDTH - 1) / Tile::SIZE; for (int col = left_col; col <= right_col; ++col) { if (tc.getTileAt(col, foot_row) == TileCollider::Tile::PASSABLE) { @@ -225,19 +226,19 @@ void Player::moveHorizontal(float delta_time) { return; } - const auto& tc = room_->getTileCollider(); + auto [tc, ox, oy] = getCollisionContext(); float new_x = x_ + (vx_ * delta_time); // Colisión con paredes if (vx_ < 0.0F) { - float wall = tc.checkWallLeft(new_x, y_, WIDTH, HEIGHT); + float wall = tc.checkWallLeft(new_x + ox, y_ + oy, WIDTH, HEIGHT); if (wall != Collision::NONE) { - new_x = wall; + new_x = wall - ox; } } else { - float wall = tc.checkWallRight(new_x, y_, WIDTH, HEIGHT); + float wall = tc.checkWallRight(new_x + ox, y_ + oy, WIDTH, HEIGHT); if (wall != Collision::NONE) { - new_x = wall - WIDTH; + new_x = wall - WIDTH - ox; } } @@ -259,18 +260,18 @@ void Player::moveHorizontal(float delta_time) { // actual y la inferior (las slopes en escalera bajan una fila por tile). // Si no encuentra slope, llama a exitSlope(). void Player::followSlope() { - const auto& tc = room_->getTileCollider(); + auto [tc, ox, oy] = getCollisionContext(); // SLOPE_L (\): pie izquierdo. SLOPE_R (/): pie derecho. - float foot_x = (slope_type_ == TileCollider::Tile::SLOPE_L) ? x_ : x_ + WIDTH - 1; + float foot_x = (slope_type_ == TileCollider::Tile::SLOPE_L) ? (x_ + ox) : (x_ + ox) + WIDTH - 1; // Calcular Y en la slope actual float surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x); - y_ = surface_y - HEIGHT; + y_ = surface_y - HEIGHT - oy; // Comprobar si hemos salido del tile actual int foot_tile_x = static_cast(foot_x) / Tile::SIZE; - int foot_tile_y = static_cast(y_ + HEIGHT) / Tile::SIZE; + int foot_tile_y = static_cast((y_ + oy) + HEIGHT) / Tile::SIZE; if (foot_tile_x != slope_tile_x_ || foot_tile_y != slope_tile_y_) { // Buscar slope en el tile calculado y en el de abajo (la escalera de slopes @@ -282,7 +283,7 @@ void Player::followSlope() { slope_tile_y_ = row; slope_type_ = new_tile; surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x); - y_ = surface_y - HEIGHT; + y_ = surface_y - HEIGHT - oy; return; } } @@ -295,16 +296,16 @@ void Player::followSlope() { // entre filas cuando se sale por el extremo inferior de la slope). // Si hay suelo, snapea al borde del tile. Si no, empieza a caer. void Player::exitSlope() { - const auto& tc = room_->getTileCollider(); - float foot_y = y_ + HEIGHT; + auto [tc, ox, oy] = getCollisionContext(); + float foot_y = (y_ + oy) + HEIGHT; // Comprobar suelo en la fila actual y la siguiente (al salir por abajo de una slope, // los pies pueden estar en el último pixel de la fila, justo antes del suelo) for (int check = 0; check <= 1; ++check) { float check_y = foot_y + check; - if (tc.hasGroundBelow(x_, check_y, WIDTH)) { + if (tc.hasGroundBelow(x_ + ox, check_y, WIDTH)) { int row = static_cast(check_y) / Tile::SIZE; - y_ = static_cast(row * Tile::SIZE) - HEIGHT; + y_ = static_cast(row * Tile::SIZE) - HEIGHT - oy; transitionToState(State::ON_GROUND); return; } @@ -318,12 +319,12 @@ void Player::exitSlope() { // Las slopes en escalera están una fila arriba del suelo, así que checkSlopeBelow // también mira la fila superior. void Player::detectSlopeEntry() { - const auto& tc = room_->getTileCollider(); - float foot_y = y_ + HEIGHT; + auto [tc, ox, oy] = getCollisionContext(); + float foot_y = (y_ + oy) + HEIGHT; - auto slope = tc.checkSlopeBelow(x_, foot_y, WIDTH); + auto slope = tc.checkSlopeBelow(x_ + ox, foot_y, WIDTH); if (slope.on_slope) { - y_ = slope.surface_y - HEIGHT; + y_ = slope.surface_y - HEIGHT - oy; slope_tile_x_ = slope.tile_x; slope_tile_y_ = slope.tile_y; slope_type_ = slope.type; @@ -338,27 +339,27 @@ void Player::detectSlopeEntry() { void Player::moveVertical(float delta_time) { if (state_ != State::ON_AIR) { return; } - const auto& tc = room_->getTileCollider(); + auto [tc, ox, oy] = getCollisionContext(); float displacement = vy_ * delta_time; if (vy_ < 0.0F) { // Subiendo: comprobar techo float new_y = y_ + displacement; - float ceiling = tc.checkCeiling(x_, new_y, WIDTH); + float ceiling = tc.checkCeiling(x_ + ox, new_y + oy, WIDTH); if (ceiling != Collision::NONE) { - y_ = ceiling; + y_ = ceiling - oy; vy_ = 0.0F; } else { y_ = new_y; } } else if (vy_ > 0.0F) { // Bajando: comprobar suelo - float foot_y = y_ + HEIGHT; + float foot_y = (y_ + oy) + HEIGHT; float new_foot_y = foot_y + displacement; - auto hit = tc.checkFloor(x_, foot_y, WIDTH, new_foot_y); + auto hit = tc.checkFloor(x_ + ox, foot_y, WIDTH, new_foot_y); if (hit.y != Collision::NONE) { - y_ = hit.y - HEIGHT; + y_ = hit.y - HEIGHT - oy; if (hit.type == TileCollider::Tile::SLOPE_L || hit.type == TileCollider::Tile::SLOPE_R) { slope_tile_x_ = hit.tile_x; slope_tile_y_ = hit.tile_y; @@ -383,7 +384,7 @@ void Player::moveVertical(float delta_time) { void Player::checkFalling() { if (state_ == State::ON_AIR) { return; } - const auto& tc = room_->getTileCollider(); + auto [tc, ox, oy] = getCollisionContext(); if (state_ == State::ON_SLOPE) { // Verificar que el tile de slope sigue existiendo @@ -396,8 +397,8 @@ void Player::checkFalling() { } // ON_GROUND: comprobar si sigue habiendo suelo - float foot_y = y_ + HEIGHT; - if (!tc.hasGroundBelow(x_, foot_y, WIDTH)) { + float foot_y = (y_ + oy) + HEIGHT; + if (!tc.hasGroundBelow(x_ + ox, foot_y, WIDTH)) { vy_ = 0.0F; transitionToState(State::ON_AIR); } @@ -445,8 +446,10 @@ auto Player::handleBorders() const -> Room::Border { return Room::Border::NONE; } -void Player::switchBorders() { - switch (border_) { +// Reposiciona al jugador al hacer commit definitivo a la room adyacente. +// Se llama cuando el rectángulo completo del jugador ha salido de bounds. +void Player::commitToRoom(Room::Border border) { + switch (border) { case Room::Border::TOP: y_ += PlayArea::HEIGHT; last_grounded_position_ = static_cast(y_); @@ -468,6 +471,69 @@ void Player::switchBorders() { syncSpriteAndCollider(); } +void Player::setAdjacentRoom(std::shared_ptr room, Room::Border direction) { + adjacent_room_ = std::move(room); + adjacent_direction_ = direction; +} + +void Player::clearAdjacentRoom() { + adjacent_room_.reset(); + adjacent_direction_ = Room::Border::NONE; +} + +auto Player::isFullyOutOfBounds() const -> bool { + switch (adjacent_direction_) { + case Room::Border::TOP: + return (y_ + HEIGHT) <= PlayArea::TOP; + case Room::Border::BOTTOM: + return y_ >= PlayArea::BOTTOM; + case Room::Border::LEFT: + return (x_ + WIDTH) <= PlayArea::LEFT; + case Room::Border::RIGHT: + return x_ >= PlayArea::RIGHT; + default: + return false; + } +} + +// Devuelve el TileCollider correcto y los offsets de traducción de coordenadas +// según en qué room está el centro del jugador. +auto Player::getCollisionContext() const -> CollisionContext { + if (!adjacent_room_) { + return {room_->getTileCollider(), 0.0F, 0.0F}; + } + + const float CENTER_X = x_ + (WIDTH / 2.0F); + const float CENTER_Y = y_ + (HEIGHT / 2.0F); + + switch (adjacent_direction_) { + case Room::Border::TOP: + if (CENTER_Y < PlayArea::TOP) { + return {adjacent_room_->getTileCollider(), 0.0F, static_cast(PlayArea::HEIGHT)}; + } + break; + case Room::Border::BOTTOM: + if (CENTER_Y > PlayArea::BOTTOM) { + return {adjacent_room_->getTileCollider(), 0.0F, -static_cast(PlayArea::HEIGHT)}; + } + break; + case Room::Border::LEFT: + if (CENTER_X < PlayArea::LEFT) { + return {adjacent_room_->getTileCollider(), static_cast(PlayArea::WIDTH), 0.0F}; + } + break; + case Room::Border::RIGHT: + if (CENTER_X > PlayArea::RIGHT) { + return {adjacent_room_->getTileCollider(), -static_cast(PlayArea::WIDTH), 0.0F}; + } + break; + default: + break; + } + + return {room_->getTileCollider(), 0.0F, 0.0F}; +} + // ============================================================================ // Geometría y renderizado // ============================================================================ diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index 0f8f7b2..c758499 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -63,7 +63,7 @@ class Player { void update(float delta_time); [[nodiscard]] auto isOnBorder() const -> bool { return border_ != Room::Border::NONE; } [[nodiscard]] auto getBorder() const -> Room::Border { return border_; } - void switchBorders(); + void commitToRoom(Room::Border border); auto getRect() -> SDL_FRect { return {.x = x_, .y = y_, .w = WIDTH, .h = HEIGHT}; } auto getCollider() -> SDL_FRect& { return collider_box_; } auto getSpawnParams() -> SpawnData { return {.x = x_, .y = y_, .vx = vx_, .vy = vy_, .last_grounded_position = last_grounded_position_, .state = state_, .flip = sprite_->getFlip()}; } @@ -71,6 +71,9 @@ class Player { void setSkin(const std::string& skin_name); static auto skinToAnimationPath(const std::string& skin_name) -> std::string; void setRoom(std::shared_ptr room) { room_ = std::move(room); } + void setAdjacentRoom(std::shared_ptr room, Room::Border direction); + void clearAdjacentRoom(); + [[nodiscard]] auto isFullyOutOfBounds() const -> bool; [[nodiscard]] auto isAlive() const -> bool { return is_alive_; } void setPaused(bool value) { is_paused_ = value; } void setIgnoreInput(bool value) { ignore_input_ = value; } @@ -86,8 +89,18 @@ class Player { static constexpr int WIDTH = 12; static constexpr int HEIGHT = 24; + // --- Contexto de colisión (selección de room + traducción de coordenadas) --- + struct CollisionContext { + const TileCollider& tc; + float offset_x; + float offset_y; + }; + auto getCollisionContext() const -> CollisionContext; + // --- Objetos y punteros --- std::shared_ptr room_; + std::shared_ptr adjacent_room_; + Room::Border adjacent_direction_{Room::Border::NONE}; std::unique_ptr sprite_; // --- Posición y física --- diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 4d5761a..961f551 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -28,7 +28,6 @@ #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 @@ -309,8 +308,8 @@ void Game::updatePlaying(float delta_time) { // Actualiza los objetos room_->update(delta_time); - if (transitioning_) { - transition_old_room_->update(delta_time); + if (transitioning_ && transition_adjacent_room_) { + transition_adjacent_room_->update(delta_time); } switch (mode_) { case Mode::GAME: @@ -325,37 +324,14 @@ void Game::updatePlaying(float delta_time) { #else player_->update(delta_time); #endif - // Si durante una transición el jugador cruza de vuelta por el borde opuesto, - // abortar la transición y volver a la habitación anterior - if (transitioning_ && player_->isOnBorder()) { - const auto BORDER = player_->getBorder(); - const bool FELL_BACK = - (transition_direction_ == Room::Border::TOP && BORDER == Room::Border::BOTTOM) || - (transition_direction_ == Room::Border::BOTTOM && BORDER == Room::Border::TOP) || - (transition_direction_ == Room::Border::LEFT && BORDER == Room::Border::RIGHT) || - (transition_direction_ == Room::Border::RIGHT && BORDER == Room::Border::LEFT); - - if (FELL_BACK) { - room_ = transition_old_room_; - player_->setRoom(room_); - player_->switchBorders(); - spawn_data_ = player_->getSpawnParams(); - current_room_ = transition_old_room_path_; - setScoreBoardColor(); - endTransition(); - } - } checkPlayerIsOnBorder(); checkPlayerAndItems(); checkPlayerAndEnemies(); checkIfPlayerIsAlive(); - // Avanzar transición + // Actualizar cámara de transición if (transitioning_) { - transition_timer_ += delta_time; - if (transition_timer_ >= TRANSITION_DURATION) { - endTransition(); - } + updateTransitionCamera(delta_time); } break; @@ -491,44 +467,11 @@ void Game::renderPlaying() { if (transitioning_) { // --- Transición animada entre pantallas --- - const float T = std::min(transition_timer_ / TRANSITION_DURATION, 1.0F); - const float P = Easing::cubicInOut(T); + int cam_x = static_cast(camera_offset_x_); + int cam_y = static_cast(camera_offset_y_); - // 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((1.0F - P) * PlayArea::WIDTH); - old_ox = new_ox - PlayArea::WIDTH; - break; - case Room::Border::LEFT: - new_ox = -static_cast((1.0F - P) * PlayArea::WIDTH); - old_ox = new_ox + PlayArea::WIDTH; - break; - case Room::Border::BOTTOM: - new_oy = static_cast((1.0F - P) * PlayArea::HEIGHT); - old_oy = new_oy - PlayArea::HEIGHT; - break; - case Room::Border::TOP: - new_oy = -static_cast((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); + // Renderizar habitación principal con offset de cámara + Screen::get()->setRenderOffset(cam_x, cam_y); room_->renderMap(); room_->renderEnemies(); room_->renderItems(); @@ -536,6 +479,23 @@ void Game::renderPlaying() { player_->render(); } + // Renderizar habitación adyacente desplazada + if (transition_adjacent_room_) { + int adj_x = cam_x; + int adj_y = cam_y; + switch (transition_direction_) { + case Room::Border::TOP: adj_y -= PlayArea::HEIGHT; break; + case Room::Border::BOTTOM: adj_y += PlayArea::HEIGHT; break; + case Room::Border::LEFT: adj_x -= PlayArea::WIDTH; break; + case Room::Border::RIGHT: adj_x += PlayArea::WIDTH; break; + default: break; + } + Screen::get()->setRenderOffset(adj_x, adj_y); + transition_adjacent_room_->renderMap(); + transition_adjacent_room_->renderEnemies(); + transition_adjacent_room_->renderItems(); + } + // Scoreboard sin offset Screen::get()->setRenderOffset(0, 0); scoreboard_->render(); @@ -813,59 +773,134 @@ 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 (transition_just_ended_) { - transition_just_ended_ = false; - return; - } - - if (player_->isOnBorder()) { - const auto BORDER = player_->getBorder(); - const auto ROOM_NAME = room_->getRoom(BORDER); - - // Si no hay habitación adyacente - if (ROOM_NAME == "0") { - if (BORDER == Room::Border::BOTTOM) { - killPlayer(); - } - return; + if (!player_->isOnBorder()) { + // Si hay transición activa y el jugador ha vuelto completamente dentro de bounds, + // comprobar si la cámara también ha vuelto para cancelar la transición + if (transitioning_ && std::abs(camera_offset_x_) < 1.0F && std::abs(camera_offset_y_) < 1.0F) { + endTransition(); } + return; + } - // Guardar la habitación saliente - transition_old_room_ = room_; - transition_old_room_path_ = current_room_; - transition_direction_ = BORDER; + const auto BORDER = player_->getBorder(); - // Crear nueva habitación y reposicionar jugador - if (changeRoom(ROOM_NAME)) { - player_->switchBorders(); + // Si ya hay transición activa, comprobar si el jugador hace commit a la room adyacente + if (transitioning_) { + // ¿El jugador ha salido completamente por el lado de la transición? + if (player_->isFullyOutOfBounds()) { + // Commit: la room adyacente pasa a ser la room principal + room_ = transition_adjacent_room_; + player_->setRoom(room_); + player_->commitToRoom(transition_direction_); + current_room_ = transition_adjacent_room_path_; spawn_data_ = player_->getSpawnParams(); + setScoreBoardColor(); - // Iniciar transición animada - transitioning_ = true; - transition_timer_ = 0.0F; - } else { - // changeRoom falló, limpiar - transition_old_room_.reset(); + // Ajustar cámara: restar el desplazamiento de una pantalla completa + switch (transition_direction_) { + case Room::Border::TOP: camera_offset_y_ -= PlayArea::HEIGHT; break; + case Room::Border::BOTTOM: camera_offset_y_ += PlayArea::HEIGHT; break; + case Room::Border::LEFT: camera_offset_x_ -= PlayArea::WIDTH; break; + case Room::Border::RIGHT: camera_offset_x_ += PlayArea::WIDTH; break; + default: break; + } + + // Limpiar transición (pero la cámara sigue animándose hacia 0) + player_->clearAdjacentRoom(); + transition_adjacent_room_.reset(); + transition_adjacent_room_path_.clear(); transition_direction_ = Room::Border::NONE; - if (BORDER == Room::Border::BOTTOM) { - killPlayer(); + // La cámara aún no está en 0, así que mantenemos transitioning_ = true + // Se resolverá cuando la cámara llegue a 0 y el jugador esté dentro de bounds + if (std::abs(camera_offset_x_) < 1.0F && std::abs(camera_offset_y_) < 1.0F) { + endTransition(); } } + return; + } + + // No hay transición activa — iniciar una nueva + const auto ROOM_NAME = room_->getRoom(BORDER); + + // Si no hay habitación adyacente + if (ROOM_NAME == "0") { + if (BORDER == Room::Border::BOTTOM) { + killPlayer(); + } + return; + } + + // Cargar room adyacente + auto adjacent_room = std::make_shared(ROOM_NAME, scoreboard_data_); + transition_adjacent_room_ = adjacent_room; + transition_adjacent_room_path_ = ROOM_NAME; + transition_direction_ = BORDER; + + // Pasar la room adyacente al player para colisiones + player_->setAdjacentRoom(adjacent_room, BORDER); + + // Iniciar transición (NO cambiar room_, NO reposicionar jugador) + transitioning_ = true; + + if (room_tracker_->addRoom(ROOM_NAME)) { + scoreboard_data_->rooms++; + Options::stats.rooms = scoreboard_data_->rooms; + } +} + +// Actualiza la cámara durante la transición: sigue al jugador con inercia +void Game::updateTransitionCamera(float delta_time) { + // Calcular el offset objetivo basado en la posición del jugador + float target_x = 0.0F; + float target_y = 0.0F; + + const auto RECT = player_->getRect(); + const float CENTER_X = RECT.x + (RECT.w / 2.0F); + const float CENTER_Y = RECT.y + (RECT.h / 2.0F); + + if (transition_direction_ == Room::Border::TOP || transition_direction_ == Room::Border::BOTTOM) { + if (CENTER_Y < PlayArea::TOP) { + target_y = static_cast(PlayArea::HEIGHT); + } else if (CENTER_Y > PlayArea::BOTTOM) { + target_y = -static_cast(PlayArea::HEIGHT); + } + } else if (transition_direction_ == Room::Border::LEFT || transition_direction_ == Room::Border::RIGHT) { + if (CENTER_X < PlayArea::LEFT) { + target_x = static_cast(PlayArea::WIDTH); + } else if (CENTER_X > PlayArea::RIGHT) { + target_x = -static_cast(PlayArea::WIDTH); + } + } + + // Interpolar la cámara hacia el objetivo con velocidad constante + constexpr float CAMERA_SPEED = 500.0F; + auto lerp_towards = [delta_time](float current, float target) -> float { + const float DIFF = target - current; + if (std::abs(DIFF) < 1.0F) { return target; } + const float STEP = CAMERA_SPEED * delta_time; + if (std::abs(DIFF) <= STEP) { return target; } + return current + (DIFF > 0.0F ? STEP : -STEP); + }; + + camera_offset_x_ = lerp_towards(camera_offset_x_, target_x); + camera_offset_y_ = lerp_towards(camera_offset_y_, target_y); + + // Si no hay room adyacente pendiente, la cámara vuelve a 0, y al llegar terminamos + if (!transition_adjacent_room_ && + std::abs(camera_offset_x_) < 1.0F && std::abs(camera_offset_y_) < 1.0F) { + endTransition(); } } // Finaliza la transición entre pantallas void Game::endTransition() { transitioning_ = false; - transition_just_ended_ = true; - transition_timer_ = 0.0F; - transition_old_room_.reset(); - transition_old_room_path_.clear(); + camera_offset_x_ = 0.0F; + camera_offset_y_ = 0.0F; + player_->clearAdjacentRoom(); + transition_adjacent_room_.reset(); + transition_adjacent_room_path_.clear(); transition_direction_ = Room::Border::NONE; Screen::get()->setRenderOffset(0, 0); } diff --git a/source/game/scenes/game.hpp b/source/game/scenes/game.hpp index c262cfd..5683513 100644 --- a/source/game/scenes/game.hpp +++ b/source/game/scenes/game.hpp @@ -45,7 +45,6 @@ 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 { @@ -78,6 +77,7 @@ class Game { void togglePause(); // Pone el juego en pausa void initPlayer(const Player::SpawnData& spawn_point, std::shared_ptr room); // Inicializa al jugador void endTransition(); // Finaliza la transición entre pantallas + void updateTransitionCamera(float delta_time); // Actualiza la cámara durante la transición 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 @@ -108,11 +108,11 @@ class Game { // 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 transition_old_room_; // Habitación saliente (se mantiene viva durante la transición) + std::shared_ptr transition_adjacent_room_; // Room adyacente durante la transición + std::string transition_adjacent_room_path_; // Path de la room adyacente Room::Border transition_direction_{Room::Border::NONE}; // Dirección de la transición - std::string transition_old_room_path_; // Path de la habitación saliente (para poder restaurarla) - bool transition_just_ended_{false}; // Cooldown de 1 frame tras finalizar transición + float camera_offset_x_{0.0F}; // Offset actual de la cámara (pixeles) + float camera_offset_y_{0.0F}; // Offset actual de la cámara (pixeles) // Variables de demo mode DemoData demo_; // Variables para el modo demo