From 31c84f9676424975a0b459bc0efee93ee0dc8d8a Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 28 Oct 2025 10:52:13 +0100 Subject: [PATCH] migrat Game, Player i Item a time based --- source/game/entities/item.cpp | 16 +++- source/game/entities/item.hpp | 14 ++-- source/game/entities/player.cpp | 132 ++++++++++++++++++-------------- source/game/entities/player.hpp | 40 ++++++---- source/game/gameplay/room.cpp | 6 +- source/game/gameplay/room.hpp | 2 +- source/game/scenes/game.cpp | 88 ++++++++++----------- source/game/scenes/game.hpp | 45 ++++++----- 8 files changed, 190 insertions(+), 153 deletions(-) diff --git a/source/game/entities/item.cpp b/source/game/entities/item.cpp index e87f32e..fff81de 100644 --- a/source/game/entities/item.cpp +++ b/source/game/entities/item.cpp @@ -6,11 +6,11 @@ // Constructor Item::Item(const ItemData &item) : sprite_(std::make_shared(Resource::get()->getSurface(item.tile_set_file), item.x, item.y, ITEM_SIZE, ITEM_SIZE)), - change_color_speed_(4) { + time_accumulator_(static_cast(item.counter) * COLOR_CHANGE_INTERVAL), + is_paused_(false) { // Inicia variables sprite_->setClip((item.tile % 10) * ITEM_SIZE, (item.tile / 10) * ITEM_SIZE, ITEM_SIZE, ITEM_SIZE); collider_ = sprite_->getRect(); - counter_ = item.counter * change_color_speed_; // Inicializa los colores color_.push_back(item.color1); @@ -20,9 +20,19 @@ Item::Item(const ItemData &item) color_.push_back(item.color2); } +// Actualiza las variables del objeto +void Item::update(float delta_time) { + if (is_paused_) { + return; + } + + time_accumulator_ += delta_time; +} + // Pinta el objeto en pantalla void Item::render() const { - const int INDEX = (counter_ / change_color_speed_) % color_.size(); + // Calcula el índice de color basado en el tiempo acumulado + const int INDEX = static_cast(time_accumulator_ / COLOR_CHANGE_INTERVAL) % static_cast(color_.size()); sprite_->render(1, color_.at(INDEX)); } diff --git a/source/game/entities/item.hpp b/source/game/entities/item.hpp index 8941415..1ccc653 100644 --- a/source/game/entities/item.hpp +++ b/source/game/entities/item.hpp @@ -24,15 +24,16 @@ class Item { private: // Constantes static constexpr float ITEM_SIZE = 8; + static constexpr float COLOR_CHANGE_INTERVAL = 0.06F; // Intervalo de cambio de color en segundos (4 frames a 66.67fps) // Objetos y punteros std::shared_ptr sprite_; // SSprite del objeto // Variables - std::vector color_; // Vector con los colores del objeto - int counter_; // Contador interno - SDL_FRect collider_; // Rectangulo de colisión - int change_color_speed_; // Cuanto mas alto, mas tarda en cambiar de color + std::vector color_; // Vector con los colores del objeto + float time_accumulator_; // Acumulador de tiempo para cambio de color + SDL_FRect collider_; // Rectangulo de colisión + bool is_paused_; // Indica si el item está pausado public: // Constructor @@ -45,7 +46,10 @@ class Item { void render() const; // Actualiza las variables del objeto - void update() { counter_++; } + void update(float delta_time); + + // Pausa/despausa el item + void setPaused(bool paused) { is_paused_ = paused; } // Obtiene el rectangulo de colision del objeto auto getCollider() -> SDL_FRect& { return collider_; } diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index c4355c0..bac56d5 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -49,19 +49,21 @@ void Player::render() { } // Actualiza las variables del objeto -void Player::update() { +void Player::update(float delta_time) { if (!is_paused_) { - checkInput(); // Comprueba las entradas y modifica variables - move(); // Recalcula la posición del jugador - animate(); // Establece la animación del jugador - checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación - checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio - checkKillingTiles(); // Comprueba que el jugador no toque ningun tile de los que matan} + checkInput(delta_time); // Comprueba las entradas y modifica variables + move(delta_time); // Recalcula la posición del jugador + animate(delta_time); // Establece la animación del jugador + checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación + checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio + checkKillingTiles(); // Comprueba que el jugador no toque ningun tile de los que matan} } } // Comprueba las entradas y modifica variables -void Player::checkInput() { +void Player::checkInput(float delta_time) { + (void)delta_time; // No usado en este método, pero mantenido para consistencia + // Solo comprueba las entradas de dirección cuando está sobre una superficie if (state_ != PlayerState::STANDING) { return; @@ -70,12 +72,12 @@ void Player::checkInput() { if (!auto_movement_) { // Comprueba las entradas de desplazamiento lateral solo en el caso de no estar enganchado a una superficie automatica if (Input::get()->checkInput(InputAction::LEFT)) { - vx_ = -0.6F; + vx_ = -HORIZONTAL_VELOCITY; sprite_->setFlip(SDL_FLIP_HORIZONTAL); } else if (Input::get()->checkInput(InputAction::RIGHT)) { - vx_ = 0.6F; + vx_ = HORIZONTAL_VELOCITY; sprite_->setFlip(SDL_FLIP_NONE); } @@ -88,7 +90,7 @@ void Player::checkInput() { } } } else { // El movimiento lo proporciona la superficie - vx_ = 0.6F * room_->getAutoSurfaceDirection(); + vx_ = HORIZONTAL_VELOCITY * room_->getAutoSurfaceDirection(); if (vx_ > 0.0F) { sprite_->setFlip(SDL_FLIP_NONE); @@ -105,9 +107,9 @@ void Player::checkInput() { if (isOnFloor() || isOnAutoSurface()) { setState(PlayerState::JUMPING); - vy_ = -MAX_VY; + vy_ = JUMP_VELOCITY; jump_init_pos_ = y_; - jumping_counter_ = 0; + jumping_time_ = 0.0F; } } } @@ -140,34 +142,36 @@ void Player::checkBorders() { } // Comprueba el estado del jugador -void Player::checkState() { +void Player::checkState(float delta_time) { // Actualiza las variables en función del estado if (state_ == PlayerState::FALLING) { vx_ = 0.0F; vy_ = MAX_VY; - falling_counter_++; + falling_time_ += delta_time; playFallSound(); } else if (state_ == PlayerState::STANDING) { - if (previous_state_ == PlayerState::FALLING && falling_counter_ > MAX_FALLING_HEIGHT) { // Si cae de muy alto, el jugador muere + // Calcula la distancia de caída en pixels (velocidad * tiempo) + const float FALLING_DISTANCE = MAX_VY * falling_time_; + if (previous_state_ == PlayerState::FALLING && FALLING_DISTANCE > MAX_FALLING_HEIGHT) { // Si cae de muy alto, el jugador muere is_alive_ = false; } vy_ = 0.0F; - jumping_counter_ = 0; - falling_counter_ = 0; + jumping_time_ = 0.0F; + falling_time_ = 0.0F; if (!isOnFloor() && !isOnAutoSurface() && !isOnDownSlope()) { setState(PlayerState::FALLING); vx_ = 0.0F; vy_ = MAX_VY; - falling_counter_++; + falling_time_ += delta_time; playFallSound(); } } else if (state_ == PlayerState::JUMPING) { - falling_counter_ = 0; - jumping_counter_++; + falling_time_ = 0.0F; + jumping_time_ += delta_time; playJumpSound(); } } @@ -203,25 +207,24 @@ void Player::switchBorders() { } // Aplica gravedad al jugador -void Player::applyGravity() { - constexpr float GRAVITY_FORCE = 0.035F; - +void Player::applyGravity(float delta_time) { // La gravedad solo se aplica cuando el jugador esta saltando // Nunca mientras cae o esta de pie if (state_ == PlayerState::JUMPING) { - vy_ += GRAVITY_FORCE; + vy_ += GRAVITY_FORCE * delta_time; vy_ = std::min(vy_, MAX_VY); } } // Maneja el movimiento horizontal hacia la izquierda -void Player::moveHorizontalLeft() { +void Player::moveHorizontalLeft(float delta_time) { // Crea el rectangulo de proyección en el eje X para ver si colisiona + const float DISPLACEMENT = vx_ * delta_time; SDL_FRect proj; - proj.x = static_cast(x_ + vx_); + proj.x = static_cast(x_ + DISPLACEMENT); proj.y = static_cast(y_); proj.h = HEIGHT; - proj.w = static_cast(std::ceil(std::fabs(vx_))); // Para evitar que tenga un ancho de 0 pixels + proj.w = static_cast(std::ceil(std::fabs(DISPLACEMENT))); // Para evitar que tenga un ancho de 0 pixels #ifdef _DEBUG debug_rect_x_ = proj; @@ -233,7 +236,7 @@ void Player::moveHorizontalLeft() { // Calcula la nueva posición if (POS == -1) { // Si no hay colisión - x_ += vx_; + x_ += DISPLACEMENT; } else { // Si hay colisión lo mueve hasta donde no colisiona x_ = POS + 1; @@ -255,13 +258,14 @@ void Player::moveHorizontalLeft() { } // Maneja el movimiento horizontal hacia la derecha -void Player::moveHorizontalRight() { +void Player::moveHorizontalRight(float delta_time) { // Crea el rectangulo de proyección en el eje X para ver si colisiona + const float DISPLACEMENT = vx_ * delta_time; SDL_FRect proj; proj.x = x_ + WIDTH; proj.y = y_; proj.h = HEIGHT; - proj.w = std::ceil(vx_); // Para evitar que tenga un ancho de 0 pixels + proj.w = std::ceil(DISPLACEMENT); // Para evitar que tenga un ancho de 0 pixels #ifdef _DEBUG debug_rect_x_ = proj; @@ -273,7 +277,7 @@ void Player::moveHorizontalRight() { // Calcula la nueva posición if (POS == -1) { // Si no hay colisión - x_ += vx_; + x_ += DISPLACEMENT; } else { // Si hay colisión lo mueve hasta donde no colisiona x_ = POS - WIDTH; @@ -295,12 +299,13 @@ void Player::moveHorizontalRight() { } // Maneja el movimiento vertical hacia arriba -void Player::moveVerticalUp() { +void Player::moveVerticalUp(float delta_time) { // Crea el rectangulo de proyección en el eje Y para ver si colisiona + const float DISPLACEMENT = vy_ * delta_time; SDL_FRect proj; proj.x = static_cast(x_); - proj.y = static_cast(y_ + vy_); - proj.h = static_cast(std::ceil(std::fabs(vy_))); // Para evitar que tenga una altura de 0 pixels + proj.y = static_cast(y_ + DISPLACEMENT); + proj.h = static_cast(std::ceil(std::fabs(DISPLACEMENT))); // Para evitar que tenga una altura de 0 pixels proj.w = WIDTH; #ifdef _DEBUG @@ -313,7 +318,7 @@ void Player::moveVerticalUp() { // Calcula la nueva posición if (POS == -1) { // Si no hay colisión - y_ += vy_; + y_ += DISPLACEMENT; } else { // Si hay colisión lo mueve hasta donde no colisiona y entra en caída y_ = POS + 1; @@ -322,12 +327,13 @@ void Player::moveVerticalUp() { } // Maneja el movimiento vertical hacia abajo -void Player::moveVerticalDown() { +void Player::moveVerticalDown(float delta_time) { // Crea el rectangulo de proyección en el eje Y para ver si colisiona + const float DISPLACEMENT = vy_ * delta_time; SDL_FRect proj; proj.x = x_; proj.y = y_ + HEIGHT; - proj.h = std::ceil(vy_); // Para evitar que tenga una altura de 0 pixels + proj.h = std::ceil(DISPLACEMENT); // Para evitar que tenga una altura de 0 pixels proj.w = WIDTH; #ifdef _DEBUG @@ -362,7 +368,7 @@ void Player::moveVerticalDown() { } else { // No está saltando y no hay colisón con una rampa // Calcula la nueva posición - y_ += vy_; + y_ += DISPLACEMENT; #ifdef _DEBUG debug_color_ = static_cast(PaletteColor::RED); #endif @@ -370,16 +376,16 @@ void Player::moveVerticalDown() { } else { // Esta saltando y no hay colisión con los muros // Calcula la nueva posición - y_ += vy_; + y_ += DISPLACEMENT; } } } // Recalcula la posición del jugador y su animación -void Player::move() { +void Player::move(float delta_time) { last_position_ = {.x = x_, .y = y_}; // Guarda la posicion actual antes de modificarla - applyGravity(); // Aplica gravedad al jugador - checkState(); // Comprueba el estado del jugador + applyGravity(delta_time); // Aplica gravedad al jugador + checkState(delta_time); // Comprueba el estado del jugador #ifdef _DEBUG debug_color_ = static_cast(PaletteColor::GREEN); @@ -387,9 +393,9 @@ void Player::move() { // Movimiento horizontal if (vx_ < 0.0F) { - moveHorizontalLeft(); + moveHorizontalLeft(delta_time); } else if (vx_ > 0.0F) { - moveHorizontalRight(); + moveHorizontalRight(delta_time); } // Si ha salido del suelo, el jugador cae @@ -405,9 +411,9 @@ void Player::move() { // Movimiento vertical if (vy_ < 0.0F) { - moveVerticalUp(); + moveVerticalUp(delta_time); } else if (vy_ > 0.0F) { - moveVerticalDown(); + moveVerticalDown(delta_time); } placeSprite(); // Coloca el sprite en la nueva posición @@ -420,9 +426,9 @@ void Player::move() { } // Establece la animación del jugador -void Player::animate() { +void Player::animate(float delta_time) { if (vx_ != 0) { - sprite_->update(); + sprite_->update(delta_time); } } @@ -434,7 +440,7 @@ void Player::checkJumpEnd() { // Si alcanza la altura de salto inicial, pasa al estado de caída setState(PlayerState::FALLING); vy_ = MAX_VY; - jumping_counter_ = 0; + jumping_time_ = 0.0F; } } } @@ -442,24 +448,31 @@ void Player::checkJumpEnd() { // Calcula y reproduce el sonido de salto void Player::playJumpSound() { - if (jumping_counter_ % 4 == 0) { - JA_PlaySound(jumping_sound_[jumping_counter_ / 4]); - } + const int SOUND_INDEX = static_cast(jumping_time_ / SOUND_INTERVAL); + const int PREVIOUS_INDEX = static_cast((jumping_time_ - SOUND_INTERVAL) / SOUND_INTERVAL); + // Solo reproduce el sonido cuando cambia de índice + if (SOUND_INDEX != PREVIOUS_INDEX && SOUND_INDEX < static_cast(jumping_sound_.size())) { + JA_PlaySound(jumping_sound_[SOUND_INDEX]); #ifdef _DEBUG - Debug::get()->add("JUMP: " + std::to_string(jumping_counter_ / 4)); + Debug::get()->add("JUMP: " + std::to_string(SOUND_INDEX)); #endif + } } // Calcula y reproduce el sonido de caer void Player::playFallSound() { - if (falling_counter_ % 4 == 0) { - JA_PlaySound(falling_sound_[std::min((falling_counter_ / 4), (int)falling_sound_.size() - 1)]); - } + const int SOUND_INDEX = static_cast(falling_time_ / SOUND_INTERVAL); + const int PREVIOUS_INDEX = static_cast((falling_time_ - SOUND_INTERVAL) / SOUND_INTERVAL); + // Solo reproduce el sonido cuando cambia de índice + if (SOUND_INDEX != PREVIOUS_INDEX) { + const int CLAMPED_INDEX = std::min(SOUND_INDEX, static_cast(falling_sound_.size()) - 1); + JA_PlaySound(falling_sound_[CLAMPED_INDEX]); #ifdef _DEBUG - Debug::get()->add("FALL: " + std::to_string(falling_counter_ / 4)); + Debug::get()->add("FALL: " + std::to_string(CLAMPED_INDEX)); #endif + } } // Comprueba si el jugador tiene suelo debajo de los pies @@ -597,7 +610,8 @@ void Player::setState(PlayerState value) { previous_state_ = state_; state_ = value; - checkState(); + // Llama a checkState con delta_time 0 porque esto es un cambio de estado inmediato + checkState(0.0F); } // Inicializa los sonidos de salto y caida diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index 928858a..87153d6 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -66,10 +66,18 @@ struct PlayerData { class Player { private: // Constantes - static constexpr int WIDTH = 8; // Ancho del jugador - static constexpr int HEIGHT = 16; // ALto del jugador - static constexpr int MAX_FALLING_HEIGHT = BLOCK * 4; // Altura maxima permitida de caída. - static constexpr float MAX_VY = 1.2F; // Velocidad máxima que puede alcanzar al desplazarse en vertical + static constexpr int WIDTH = 8; // Ancho del jugador + static constexpr int HEIGHT = 16; // ALto del jugador + static constexpr int MAX_FALLING_HEIGHT = BLOCK * 4; // Altura maxima permitida de caída en pixels + + // Constantes de física (per-second values) + static constexpr float HORIZONTAL_VELOCITY = 40.0F; // Velocidad horizontal en pixels/segundo (0.6 * 66.67fps) + static constexpr float MAX_VY = 80.0F; // Velocidad vertical máxima en pixels/segundo (1.2 * 66.67fps) + static constexpr float JUMP_VELOCITY = -80.0F; // Velocidad inicial del salto en pixels/segundo + static constexpr float GRAVITY_FORCE = 155.6F; // Fuerza de gravedad en pixels/segundo² (0.035 * 66.67²) + + // Constantes de sonido + static constexpr float SOUND_INTERVAL = 0.06F; // Intervalo entre sonidos de salto/caída en segundos (4 frames a 66.67fps) // Objetos y punteros std::shared_ptr room_; // Objeto encargado de gestionar cada habitación del juego @@ -96,8 +104,8 @@ class Player { int jump_init_pos_; // Valor del eje Y en el que se inicia el salto std::vector jumping_sound_; // Vecor con todos los sonidos del salto std::vector falling_sound_; // Vecor con todos los sonidos de la caída - int jumping_counter_ = 0; // Cuenta el tiempo de salto - int falling_counter_ = 0; // Cuenta el tiempo de caida + float jumping_time_ = 0.0F; // Tiempo acumulado de salto en segundos + float falling_time_ = 0.0F; // Tiempo acumulado de caída en segundos #ifdef _DEBUG SDL_FRect debug_rect_x_; // Rectangulo de desplazamiento para el modo debug @@ -107,34 +115,34 @@ class Player { #endif // Comprueba las entradas y modifica variables - void checkInput(); + void checkInput(float delta_time); // Comprueba si se halla en alguno de los cuatro bordes void checkBorders(); // Comprueba el estado del jugador - void checkState(); + void checkState(float delta_time); // Aplica gravedad al jugador - void applyGravity(); + void applyGravity(float delta_time); // Recalcula la posición del jugador y su animación - void move(); + void move(float delta_time); // Maneja el movimiento horizontal hacia la izquierda - void moveHorizontalLeft(); + void moveHorizontalLeft(float delta_time); // Maneja el movimiento horizontal hacia la derecha - void moveHorizontalRight(); + void moveHorizontalRight(float delta_time); // Maneja el movimiento vertical hacia arriba - void moveVerticalUp(); + void moveVerticalUp(float delta_time); // Maneja el movimiento vertical hacia abajo - void moveVerticalDown(); + void moveVerticalDown(float delta_time); // Establece la animación del jugador - void animate(); + void animate(float delta_time); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio void checkJumpEnd(); @@ -194,7 +202,7 @@ public: void render(); // Actualiza las variables del objeto - void update(); + void update(float delta_time); // Indica si el jugador esta en uno de los cuatro bordes de la pantalla [[nodiscard]] auto getOnBorder() const -> bool { return is_on_border_; } diff --git a/source/game/gameplay/room.cpp b/source/game/gameplay/room.cpp index 32eb800..7439969 100644 --- a/source/game/gameplay/room.cpp +++ b/source/game/gameplay/room.cpp @@ -471,13 +471,13 @@ void Room::renderItems() { } // Actualiza las variables y objetos de la habitación -void Room::update() { +void Room::update(float delta_time) { if (is_paused_) { // Si está en modo pausa no se actualiza nada return; } - // Actualiza el contador + // Actualiza el contador (mantenido para compatibilidad temporalmente) counter_++; // Actualiza los tiles animados @@ -490,7 +490,7 @@ void Room::update() { for (const auto& item : items_) { // Actualiza los items - item->update(); + item->update(delta_time); } } diff --git a/source/game/gameplay/room.hpp b/source/game/gameplay/room.hpp index 6902e82..17216bc 100644 --- a/source/game/gameplay/room.hpp +++ b/source/game/gameplay/room.hpp @@ -192,7 +192,7 @@ class Room { void renderItems(); // Actualiza las variables y objetos de la habitación - void update(); + void update(float delta_time); // Devuelve la cadena del fichero de la habitación contigua segun el borde auto getRoom(RoomBorder border) -> std::string; diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 0d1fc5a..4a9a435 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -115,42 +115,39 @@ void Game::run() { // Actualiza el juego, las variables, comprueba la entrada, etc. void Game::update() { - // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego - if (SDL_GetTicks() - ticks_ > GAME_SPEED) { - // Actualiza el contador de ticks - ticks_ = SDL_GetTicks(); + // Calcula el delta time + const float DELTA_TIME = delta_timer_.tick(); - // Comprueba el teclado - checkInput(); + // Comprueba el teclado + checkInput(); #ifdef _DEBUG - Debug::get()->clear(); + Debug::get()->clear(); #endif - // Actualiza los objetos - room_->update(); - if (mode_ == GameMode::GAME) { - player_->update(); - checkPlayerIsOnBorder(); - checkPlayerAndItems(); - checkPlayerAndEnemies(); - checkIfPlayerIsAlive(); - checkGameOver(); - checkEndGame(); - checkRestoringJail(); - checkSomeCheevos(); - } - demoCheckRoomChange(); - scoreboard_->update(); - keepMusicPlaying(); - updateBlackScreen(); - - Screen::get()->update(); - -#ifdef _DEBUG - updateDebugInfo(); -#endif + // Actualiza los objetos + room_->update(DELTA_TIME); + if (mode_ == GameMode::GAME) { + player_->update(DELTA_TIME); + checkPlayerIsOnBorder(); + checkPlayerAndItems(); + checkPlayerAndEnemies(); + checkIfPlayerIsAlive(); + checkGameOver(); + checkEndGame(); + checkRestoringJail(DELTA_TIME); + checkSomeCheevos(); } + demoCheckRoomChange(DELTA_TIME); + scoreboard_->update(); + keepMusicPlaying(); + updateBlackScreen(DELTA_TIME); + + Screen::get()->update(DELTA_TIME); + +#ifdef _DEBUG + updateDebugInfo(); +#endif } // Pinta los objetos en pantalla @@ -336,7 +333,7 @@ void Game::checkIfPlayerIsAlive() { // Comprueba si ha terminado la partida void Game::checkGameOver() { - if (board_->lives < 0 && black_screen_counter_ > 17) { + if (board_->lives < 0 && black_screen_time_ > GAME_OVER_THRESHOLD) { SceneManager::current = SceneManager::Scene::GAME_OVER; } } @@ -379,12 +376,12 @@ void Game::setBlackScreen() { } // Actualiza las variables relativas a la pantalla en negro -void Game::updateBlackScreen() { +void Game::updateBlackScreen(float delta_time) { if (black_screen_) { - black_screen_counter_++; - if (black_screen_counter_ > 20) { + black_screen_time_ += delta_time; + if (black_screen_time_ > BLACK_SCREEN_DURATION) { black_screen_ = false; - black_screen_counter_ = 0; + black_screen_time_ = 0.0F; player_->setPaused(false); room_->setPaused(false); @@ -458,20 +455,19 @@ void Game::togglePause() { } // Da vidas al jugador cuando está en la Jail -void Game::checkRestoringJail() { +void Game::checkRestoringJail(float delta_time) { if (room_->getName() != "THE JAIL" || board_->lives == 9) { + jail_restore_time_ = 0.0F; // Reset timer cuando no está en la Jail return; } - static int counter_ = 0; - if (!paused_) { - counter_++; + jail_restore_time_ += delta_time; } // Incrementa el numero de vidas - if (counter_ == 100) { - counter_ = 0; + if (jail_restore_time_ >= JAIL_RESTORE_INTERVAL) { + jail_restore_time_ -= JAIL_RESTORE_INTERVAL; // Mantiene el excedente para precisión board_->lives++; JA_PlaySound(Resource::get()->getSound("death.wav")); @@ -599,17 +595,17 @@ void Game::keepMusicPlaying() { // DEMO MODE: Inicializa las variables para el modo demo void Game::demoInit() { if (mode_ == GameMode::DEMO) { - demo_ = DemoData(0, 400, 0, {"04.room", "54.room", "20.room", "09.room", "05.room", "11.room", "31.room", "44.room"}); + demo_ = DemoData(0.0F, 0, {"04.room", "54.room", "20.room", "09.room", "05.room", "11.room", "31.room", "44.room"}); current_room_ = demo_.rooms.front(); } } // DEMO MODE: Comprueba si se ha de cambiar de habitación -void Game::demoCheckRoomChange() { +void Game::demoCheckRoomChange(float delta_time) { if (mode_ == GameMode::DEMO) { - demo_.counter++; - if (demo_.counter == demo_.room_time) { - demo_.counter = 0; + demo_.time_accumulator += delta_time; + if (demo_.time_accumulator >= DEMO_ROOM_DURATION) { + demo_.time_accumulator = 0.0F; demo_.room_index++; if (demo_.room_index == (int)demo_.rooms.size()) { SceneManager::current = SceneManager::Scene::LOGO; diff --git a/source/game/scenes/game.hpp b/source/game/scenes/game.hpp index 941499d..a889ace 100644 --- a/source/game/scenes/game.hpp +++ b/source/game/scenes/game.hpp @@ -8,6 +8,7 @@ #include // Para vector #include "game/entities/player.hpp" // Para PlayerSpawn +#include "utils/delta_timer.hpp" // Para DeltaTimer class Room; // lines 12-12 class RoomTracker; // lines 13-13 class Scoreboard; // lines 14-14 @@ -22,24 +23,27 @@ enum class GameMode { class Game { private: + // Constantes de tiempo + static constexpr float BLACK_SCREEN_DURATION = 0.30F; // Duración de la pantalla negra en segundos (20 frames a 66.67fps) + static constexpr float GAME_OVER_THRESHOLD = 0.255F; // Tiempo antes del game over en segundos (17 frames a 66.67fps) + static constexpr float DEMO_ROOM_DURATION = 6.0F; // Duración de cada habitación en modo demo en segundos (400 frames) + static constexpr float JAIL_RESTORE_INTERVAL = 1.5F; // Intervalo de restauración de vidas en la Jail en segundos (100 frames) + // Estructuras struct DemoData { - int counter; // Contador para el modo demo - int room_time; // Tiempo que se muestra cada habitación + float time_accumulator; // Acumulador de tiempo para el modo demo int room_index; // Índice para el vector de habitaciones std::vector rooms; // Listado con los mapas de la demo // Constructor por defecto DemoData() - : counter(0), - room_time(0), + : time_accumulator(0.0F), room_index(0), rooms({}) {} // Constructor parametrizado - DemoData(int counter, int room_time, int room_index, const std::vector& rooms) - : counter(counter), - room_time(room_time), + DemoData(float time_accumulator, int room_index, const std::vector& rooms) + : time_accumulator(time_accumulator), room_index(room_index), rooms(rooms) {} }; @@ -54,16 +58,17 @@ class Game { std::shared_ptr room_name_surface_; // Textura para escribir el nombre de la habitación // Variables - GameMode mode_; // Modo del juego - DemoData demo_; // Variables para el modo demo - Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa - std::string current_room_; // Fichero de la habitación actual - PlayerSpawn spawn_point_; // Lugar de la habitación donde aparece el jugador - bool paused_ = false; // Indica si el juego se encuentra en pausa - bool black_screen_ = false; // Indica si la pantalla está en negro. Se utiliza para la muerte del jugador - int black_screen_counter_ = 0; // Contador para temporizar la pantalla en negro - int total_items_; // Cantidad total de items que hay en el mapeado del juego - SDL_FRect room_name_rect_; // Rectangulo donde pintar la textura con el nombre de la habitación + GameMode mode_; // Modo del juego + DemoData demo_; // Variables para el modo demo + DeltaTimer delta_timer_; // Timer para calcular delta time + std::string current_room_; // Fichero de la habitación actual + PlayerSpawn spawn_point_; // Lugar de la habitación donde aparece el jugador + bool paused_ = false; // Indica si el juego se encuentra en pausa + bool black_screen_ = false; // Indica si la pantalla está en negro. Se utiliza para la muerte del jugador + float black_screen_time_ = 0.0F; // Tiempo acumulado en pantalla negra en segundos + int total_items_; // Cantidad total de items que hay en el mapeado del juego + SDL_FRect room_name_rect_; // Rectangulo donde pintar la textura con el nombre de la habitación + float jail_restore_time_ = 0.0F; // Tiempo acumulado para restauración de vidas en la Jail // Actualiza el juego, las variables, comprueba la entrada, etc. void update(); @@ -116,7 +121,7 @@ class Game { void setBlackScreen(); // Actualiza las variables relativas a la pantalla en negro - void updateBlackScreen(); + void updateBlackScreen(float delta_time); // Dibuja la pantalla negra void renderBlackScreen() const; @@ -134,7 +139,7 @@ class Game { void togglePause(); // Da vidas al jugador cuando está en la Jail - void checkRestoringJail(); + void checkRestoringJail(float delta_time); // Inicializa el diccionario de las estadísticas void initStats(); @@ -161,7 +166,7 @@ class Game { void demoInit(); // DEMO MODE: Comprueba si se ha de cambiar de habitación - void demoCheckRoomChange(); + void demoCheckRoomChange(float delta_time); public: // Constructor