delta-time: balloon.cpp

delta-time: balloon_manager.cpp
delta-time: credits.cpp
This commit is contained in:
2025-09-16 22:38:48 +02:00
parent a96a17e11b
commit a15e29344f
7 changed files with 367 additions and 50 deletions

View File

@@ -135,7 +135,7 @@ void Balloon::render() {
} }
} }
// Actualiza la posición y estados del globo // Actualiza la posición y estados del globo (frame-based)
void Balloon::move() { void Balloon::move() {
if (isStopped()) { if (isStopped()) {
return; return;
@@ -146,6 +146,17 @@ void Balloon::move() {
applyGravity(); applyGravity();
} }
// Actualiza la posición y estados del globo (time-based)
void Balloon::move(float deltaTime) {
if (isStopped()) {
return;
}
handleHorizontalMovement(deltaTime);
handleVerticalMovement(deltaTime);
applyGravity(deltaTime);
}
void Balloon::handleHorizontalMovement() { void Balloon::handleHorizontalMovement() {
x_ += vx_ * speed_; x_ += vx_ * speed_;
@@ -158,6 +169,20 @@ void Balloon::handleHorizontalMovement() {
} }
} }
void Balloon::handleHorizontalMovement(float deltaTime) {
// Convertir deltaTime (milisegundos) a factor de frame (asumiendo 60fps)
float frameFactor = deltaTime / (1000.0f / 60.0f);
x_ += vx_ * speed_ * frameFactor;
const int CLIP = 2;
const float MIN_X = play_area_.x - CLIP;
const float MAX_X = play_area_.x + play_area_.w - w_ + CLIP;
if (isOutOfHorizontalBounds(MIN_X, MAX_X)) {
handleHorizontalBounce(MIN_X, MAX_X);
}
}
void Balloon::handleVerticalMovement() { void Balloon::handleVerticalMovement() {
y_ += vy_ * speed_; y_ += vy_ * speed_;
@@ -168,6 +193,18 @@ void Balloon::handleVerticalMovement() {
handleBottomCollision(); handleBottomCollision();
} }
void Balloon::handleVerticalMovement(float deltaTime) {
// Convertir deltaTime (milisegundos) a factor de frame (asumiendo 60fps)
float frameFactor = deltaTime / (1000.0f / 60.0f);
y_ += vy_ * speed_ * frameFactor;
if (shouldCheckTopCollision()) {
handleTopCollision();
}
handleBottomCollision();
}
auto Balloon::isOutOfHorizontalBounds(float min_x, float max_x) const -> bool { auto Balloon::isOutOfHorizontalBounds(float min_x, float max_x) const -> bool {
return x_ < min_x || x_ > max_x; return x_ < min_x || x_ > max_x;
} }
@@ -230,6 +267,18 @@ void Balloon::applyGravity() {
} }
} }
void Balloon::applyGravity(float deltaTime) {
// Convertir deltaTime (milisegundos) a factor de frame (asumiendo 60fps)
float frameFactor = deltaTime / (1000.0f / 60.0f);
travel_y_ += speed_ * frameFactor;
if (travel_y_ >= 1.0F) {
travel_y_ -= 1.0F;
vy_ += gravity_;
}
}
void Balloon::playBouncingSound() { void Balloon::playBouncingSound() {
if (sound_.enabled && sound_.bouncing_enabled) { if (sound_.enabled && sound_.bouncing_enabled) {
Audio::get()->playSound(sound_.bouncing_file); Audio::get()->playSound(sound_.bouncing_file);
@@ -242,7 +291,7 @@ void Balloon::playPoppingSound() {
} }
} }
// Actualiza al globo a su posicion, animación y controla los contadores // Actualiza al globo a su posicion, animación y controla los contadores (frame-based)
void Balloon::update() { void Balloon::update() {
move(); move();
updateState(); updateState();
@@ -253,7 +302,20 @@ void Balloon::update() {
++counter_; ++counter_;
} }
// Actualiza los estados del globo // Actualiza al globo a su posicion, animación y controla los contadores (time-based)
void Balloon::update(float deltaTime) {
move(deltaTime);
updateState(deltaTime);
updateBounceEffect();
shiftSprite();
shiftColliders();
sprite_->update(deltaTime);
// Convertir deltaTime (milisegundos) a factor de frame (asumiendo 60fps)
float frameFactor = deltaTime / (1000.0f / 60.0f);
counter_ += frameFactor;
}
// Actualiza los estados del globo (frame-based)
void Balloon::updateState() { void Balloon::updateState() {
// Si se está creando // Si se está creando
if (isBeingCreated()) { if (isBeingCreated()) {
@@ -263,7 +325,7 @@ void Balloon::updateState() {
if (creation_counter_ > 0) { if (creation_counter_ > 0) {
// Desplaza lentamente el globo hacia abajo y hacia un lado // Desplaza lentamente el globo hacia abajo y hacia un lado
if (creation_counter_ % 10 == 0) { if (static_cast<int>(creation_counter_) % 10 == 0) {
y_++; y_++;
x_ += vx_; x_ += vx_;
@@ -290,6 +352,51 @@ void Balloon::updateState() {
} }
} }
// Actualiza los estados del globo (time-based)
void Balloon::updateState(float deltaTime) {
// Si se está creando
if (isBeingCreated()) {
// Actualiza el valor de las variables
stop();
setInvulnerable(true);
if (creation_counter_ > 0) {
// Convertir deltaTime (milisegundos) a factor de frame (asumiendo 60fps)
float frameFactor = deltaTime / (1000.0f / 60.0f);
// Desplaza lentamente el globo hacia abajo y hacia un lado
// Cada 10 frames (aproximadamente cada 166ms a 60fps)
movement_accumulator_ += frameFactor;
if (movement_accumulator_ >= 10.0f) {
movement_accumulator_ -= 10.0f;
y_++;
x_ += vx_;
// Comprueba no se salga por los laterales
const int MIN_X = play_area_.x;
const int MAX_X = play_area_.w - w_;
if (x_ < MIN_X || x_ > MAX_X) {
// Corrige y cambia el sentido de la velocidad
x_ -= vx_;
vx_ = -vx_;
}
}
creation_counter_ -= frameFactor;
if (creation_counter_ < 0) creation_counter_ = 0;
}
else {
// El contador ha llegado a cero
being_created_ = false;
start();
setInvulnerable(false);
setAnimation();
}
}
}
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
void Balloon::setAnimation() { void Balloon::setAnimation() {
std::string creating_animation; std::string creating_animation;

View File

@@ -87,11 +87,13 @@ class Balloon {
~Balloon() = default; ~Balloon() = default;
// --- Métodos principales --- // --- Métodos principales ---
void alignTo(int x); // Centra el globo en la posición X void alignTo(int x); // Centra el globo en la posición X
void render(); // Pinta el globo en la pantalla void render(); // Pinta el globo en la pantalla
void move(); // Actualiza la posición y estados del globo void move(); // Actualiza la posición y estados del globo (frame-based)
void update(); // Actualiza el globo (posición, animación, contadores) void move(float deltaTime); // Actualiza la posición y estados del globo (time-based)
void stop(); // Detiene el globo void update(); // Actualiza el globo (posición, animación, contadores) (frame-based)
void update(float deltaTime); // Actualiza el globo (posición, animación, contadores) (time-based)
void stop(); // Detiene el globo
void start(); // Pone el globo en movimiento void start(); // Pone el globo en movimiento
void pop(bool should_sound = false); // Explota el globo void pop(bool should_sound = false); // Explota el globo
@@ -256,8 +258,8 @@ class Balloon {
bool stopped_; // Si el globo está parado bool stopped_; // Si el globo está parado
bool use_reversed_colors_ = false; // Si se usa el color alternativo bool use_reversed_colors_ = false; // Si se usa el color alternativo
Circle collider_; // Círculo de colisión Circle collider_; // Círculo de colisión
Uint16 creation_counter_; // Temporizador de creación float creation_counter_; // Temporizador de creación
Uint16 creation_counter_ini_; // Valor inicial del temporizador de creación float creation_counter_ini_; // Valor inicial del temporizador de creación
Uint16 score_; // Puntos al destruir el globo Uint16 score_; // Puntos al destruir el globo
Type type_; // Tipo de globo Type type_; // Tipo de globo
Size size_; // Tamaño de globo Size size_; // Tamaño de globo
@@ -265,6 +267,7 @@ class Balloon {
Uint32 counter_ = 0; // Contador interno Uint32 counter_ = 0; // Contador interno
float travel_y_ = 1.0F; // Distancia a recorrer en Y antes de aplicar gravedad float travel_y_ = 1.0F; // Distancia a recorrer en Y antes de aplicar gravedad
float speed_; // Velocidad del globo float speed_; // Velocidad del globo
float movement_accumulator_ = 0.0f; // Acumulador para movimiento durante creación (deltaTime)
Uint8 power_; // Poder que alberga el globo Uint8 power_; // Poder que alberga el globo
SDL_FRect play_area_; // Zona de movimiento del globo SDL_FRect play_area_; // Zona de movimiento del globo
Sound sound_; // Configuración de sonido del globo Sound sound_; // Configuración de sonido del globo
@@ -280,9 +283,12 @@ class Balloon {
void playPoppingSound(); // Reproduce el sonido de reventar void playPoppingSound(); // Reproduce el sonido de reventar
// --- Movimiento y física --- // --- Movimiento y física ---
void handleHorizontalMovement(); // Maneja el movimiento horizontal void handleHorizontalMovement(); // Maneja el movimiento horizontal (frame-based)
void handleVerticalMovement(); // Maneja el movimiento vertical void handleHorizontalMovement(float deltaTime); // Maneja el movimiento horizontal (time-based)
void applyGravity(); // Aplica la gravedad al objeto void handleVerticalMovement(); // Maneja el movimiento vertical (frame-based)
void handleVerticalMovement(float deltaTime); // Maneja el movimiento vertical (time-based)
void applyGravity(); // Aplica la gravedad al objeto (frame-based)
void applyGravity(float deltaTime); // Aplica la gravedad al objeto (time-based)
// --- Rebote --- // --- Rebote ---
void enableBounceEffect(); // Activa el efecto de rebote void enableBounceEffect(); // Activa el efecto de rebote
@@ -297,5 +303,6 @@ class Balloon {
void handleBottomCollision(); // Maneja la colisión inferior void handleBottomCollision(); // Maneja la colisión inferior
// --- Lógica de estado --- // --- Lógica de estado ---
void updateState(); // Actualiza los estados del globo void updateState(); // Actualiza los estados del globo (frame-based)
void updateState(float deltaTime); // Actualiza los estados del globo (time-based)
}; };

View File

@@ -62,7 +62,7 @@ void BalloonManager::init() {
explosions_->addTexture(3, explosions_textures_.at(3), explosions_animations_.at(3)); explosions_->addTexture(3, explosions_textures_.at(3), explosions_animations_.at(3));
} }
// Actualiza // Actualiza (frame-based)
void BalloonManager::update() { void BalloonManager::update() {
for (const auto &balloon : balloons_) { for (const auto &balloon : balloons_) {
balloon->update(); balloon->update();
@@ -71,6 +71,15 @@ void BalloonManager::update() {
explosions_->update(); explosions_->update();
} }
// Actualiza (time-based)
void BalloonManager::update(float deltaTime) {
for (const auto &balloon : balloons_) {
balloon->update(deltaTime);
}
updateBalloonDeployCounter(deltaTime);
explosions_->update(); // Explosions aún no migrado a deltaTime
}
// Renderiza los objetos // Renderiza los objetos
void BalloonManager::render() { void BalloonManager::render() {
for (auto &balloon : balloons_) { for (auto &balloon : balloons_) {
@@ -162,13 +171,23 @@ void BalloonManager::freeBalloons() {
balloons_.erase(result.begin(), balloons_.end()); balloons_.erase(result.begin(), balloons_.end());
} }
// Actualiza la variable enemyDeployCounter // Actualiza la variable enemyDeployCounter (frame-based)
void BalloonManager::updateBalloonDeployCounter() { void BalloonManager::updateBalloonDeployCounter() {
if (balloon_deploy_counter_ > 0) { if (balloon_deploy_counter_ > 0) {
--balloon_deploy_counter_; --balloon_deploy_counter_;
} }
} }
// Actualiza la variable enemyDeployCounter (time-based)
void BalloonManager::updateBalloonDeployCounter(float deltaTime) {
if (balloon_deploy_counter_ > 0) {
// Convertir deltaTime (milisegundos) a factor de frame (asumiendo 60fps)
float frameFactor = deltaTime / (1000.0f / 60.0f);
balloon_deploy_counter_ -= frameFactor;
if (balloon_deploy_counter_ < 0) balloon_deploy_counter_ = 0;
}
}
// Indica si se puede crear una powerball // Indica si se puede crear una powerball
auto BalloonManager::canPowerBallBeCreated() -> bool { return (!power_ball_enabled_) && (calculateScreenPower() > Balloon::POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); } auto BalloonManager::canPowerBallBeCreated() -> bool { return (!power_ball_enabled_) && (calculateScreenPower() > Balloon::POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); }

View File

@@ -28,8 +28,9 @@ class BalloonManager {
~BalloonManager() = default; ~BalloonManager() = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(); // Actualiza el estado de los globos void update(); // Actualiza el estado de los globos (frame-based)
void render(); // Renderiza los globos en pantalla void update(float deltaTime); // Actualiza el estado de los globos (time-based)
void render(); // Renderiza los globos en pantalla
// --- Gestión de globos --- // --- Gestión de globos ---
void freeBalloons(); // Libera globos que ya no sirven void freeBalloons(); // Libera globos que ya no sirven
@@ -49,7 +50,8 @@ class BalloonManager {
void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos
void updateBalloonDeployCounter(); // Actualiza el contador de despliegue void updateBalloonDeployCounter(); // Actualiza el contador de despliegue (frame-based)
void updateBalloonDeployCounter(float deltaTime); // Actualiza el contador de despliegue (time-based)
auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una PowerBall auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una PowerBall
auto calculateScreenPower() -> int; // Calcula el poder de los globos en pantalla auto calculateScreenPower() -> int; // Calcula el poder de los globos en pantalla
@@ -98,7 +100,7 @@ class BalloonManager {
SDL_FRect play_area_ = param.game.play_area.rect; SDL_FRect play_area_ = param.game.play_area.rect;
float balloon_speed_ = Balloon::SPEED.at(0); float balloon_speed_ = Balloon::SPEED.at(0);
float default_balloon_speed_ = Balloon::SPEED.at(0); float default_balloon_speed_ = Balloon::SPEED.at(0);
int balloon_deploy_counter_ = 0; float balloon_deploy_counter_ = 0;
int power_ball_counter_ = 0; int power_ball_counter_ = 0;
int last_balloon_deploy_ = 0; int last_balloon_deploy_ = 0;
bool power_ball_enabled_ = false; bool power_ball_enabled_ = false;

View File

@@ -42,7 +42,7 @@ Director::Director(int argc, std::span<char *> argv) {
Section::name = Section::Name::GAME; Section::name = Section::Name::GAME;
Section::options = Section::Options::GAME_PLAY_1P; Section::options = Section::Options::GAME_PLAY_1P;
#elif _DEBUG #elif _DEBUG
Section::name = Section::Name::LOGO; Section::name = Section::Name::CREDITS;
Section::options = Section::Options::GAME_PLAY_1P; Section::options = Section::Options::GAME_PLAY_1P;
#else // NORMAL GAME #else // NORMAL GAME
Section::name = Section::Name::LOGO; Section::name = Section::Name::LOGO;

View File

@@ -78,20 +78,31 @@ Credits::~Credits() {
Options::gamepad_manager.clearPlayers(); Options::gamepad_manager.clearPlayers();
} }
// Calcula el deltatime
auto Credits::calculateDeltaTime() -> float {
const Uint64 current_time = SDL_GetTicks();
const float delta_time = static_cast<float>(current_time - last_time_);
last_time_ = current_time;
return delta_time;
}
// Bucle principal // Bucle principal
void Credits::run() { void Credits::run() {
last_time_ = SDL_GetTicks();
while (Section::name == Section::Name::CREDITS) { while (Section::name == Section::Name::CREDITS) {
checkInput(); checkInput();
update(); const float delta_time = calculateDeltaTime();
update(delta_time);
checkEvents(); // Tiene que ir antes del render checkEvents(); // Tiene que ir antes del render
render(); render();
} }
} }
// Actualiza las variables // Actualiza las variables (frame-based)
void Credits::update() { void Credits::update() {
if (SDL_GetTicks() - ticks_ > param.game.speed) { if (SDL_GetTicks() - last_time_ > param.game.speed) {
ticks_ = SDL_GetTicks(); last_time_ = SDL_GetTicks();
const int REPEAT = want_to_pass_ ? 4 : 1; const int REPEAT = want_to_pass_ ? 4 : 1;
for (int i = 0; i < REPEAT; ++i) { for (int i = 0; i < REPEAT; ++i) {
tiled_bg_->update(); tiled_bg_->update();
@@ -111,6 +122,28 @@ void Credits::update() {
Audio::update(); Audio::update();
} }
// Actualiza las variables (time-based)
void Credits::update(float deltaTime) {
const float multiplier = want_to_pass_ ? 4.0f : 1.0f;
const float adjusted_delta_time = deltaTime * multiplier;
tiled_bg_->update(adjusted_delta_time);
cycleColors();
balloon_manager_->update(adjusted_delta_time);
updateTextureDstRects(adjusted_delta_time);
throwBalloons(adjusted_delta_time);
updatePlayers(adjusted_delta_time);
updateAllFades(adjusted_delta_time);
// Convertir deltaTime a factor de frame (asumiendo 60fps)
const float frameFactor = adjusted_delta_time / (1000.0f / 60.0f);
counter_ += frameFactor;
Screen::get()->update();
fillCanvas();
Audio::update();
}
// Dibuja Credits::en patalla // Dibuja Credits::en patalla
void Credits::render() { void Credits::render() {
static auto *const SCREEN = Screen::get(); static auto *const SCREEN = Screen::get();
@@ -277,9 +310,9 @@ void Credits::fillCanvas() {
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp); SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
} }
// Actualiza el destino de los rectangulos de las texturas // Actualiza el destino de los rectangulos de las texturas (frame-based)
void Credits::updateTextureDstRects() { void Credits::updateTextureDstRects() {
if (counter_ % 10 == 0) { if (static_cast<int>(counter_) % 10 == 0) {
// Comprueba la posición de la textura con los titulos de credito // Comprueba la posición de la textura con los titulos de credito
if (credits_rect_dst_.y + credits_rect_dst_.h > play_area_.y) { if (credits_rect_dst_.y + credits_rect_dst_.h > play_area_.y) {
--credits_rect_dst_.y; --credits_rect_dst_.y;
@@ -306,7 +339,42 @@ void Credits::updateTextureDstRects() {
} }
} }
// Tira globos al escenario // Actualiza el destino de los rectangulos de las texturas (time-based)
void Credits::updateTextureDstRects(float deltaTime) {
constexpr float TEXTURE_UPDATE_INTERVAL = 10 * (1000.0f / 60.0f); // 166.67ms (cada 10 frames)
static float texture_accumulator = 0.0f;
texture_accumulator += deltaTime;
if (texture_accumulator >= TEXTURE_UPDATE_INTERVAL) {
texture_accumulator -= TEXTURE_UPDATE_INTERVAL;
// Comprueba la posición de la textura con los titulos de credito
if (credits_rect_dst_.y + credits_rect_dst_.h > play_area_.y) {
--credits_rect_dst_.y;
}
// Comprueba la posición de la textura con el mini_logo
if (mini_logo_rect_dst_.y == mini_logo_final_pos_) {
mini_logo_on_position_ = true;
// Si el jugador quiere pasar los titulos de credito, el fade se inicia solo
if (want_to_pass_) {
fading_ = true;
}
// Se activa el contador para evitar que la sección sea infinita
if (counter_prevent_endless_ == 1000) {
fading_ = true;
} else {
++counter_prevent_endless_;
}
} else {
--mini_logo_rect_dst_.y;
}
}
}
// Tira globos al escenario (frame-based)
void Credits::throwBalloons() { void Credits::throwBalloons() {
constexpr int SPEED = 200; constexpr int SPEED = 200;
const std::vector<int> SETS = {0, 63, 25, 67, 17, 75, 13, 50}; const std::vector<int> SETS = {0, 63, 25, 67, 17, 75, 13, 50};
@@ -315,12 +383,41 @@ void Credits::throwBalloons() {
return; return;
} }
if (counter_ % SPEED == 0) { if (static_cast<int>(counter_) % SPEED == 0) {
const int INDEX = (counter_ / SPEED) % SETS.size(); const int INDEX = (static_cast<int>(counter_) / SPEED) % SETS.size();
balloon_manager_->deployFormation(SETS.at(INDEX), -60); balloon_manager_->deployFormation(SETS.at(INDEX), -60);
} }
if (counter_ % (SPEED * 4) == 0 && counter_ > 0) { if (static_cast<int>(counter_) % (SPEED * 4) == 0 && counter_ > 0) {
balloon_manager_->createPowerBall();
}
}
// Tira globos al escenario (time-based)
void Credits::throwBalloons(float deltaTime) {
constexpr int SPEED = 200;
const std::vector<int> SETS = {0, 63, 25, 67, 17, 75, 13, 50};
constexpr float BALLOON_INTERVAL = SPEED * (1000.0f / 60.0f); // 3333.33ms (cada 200 frames)
constexpr float POWERBALL_INTERVAL = (SPEED * 4) * (1000.0f / 60.0f); // 13333.33ms (cada 800 frames)
if (counter_ > ((SETS.size() - 1) * SPEED) * 3) {
return;
}
static float balloon_accumulator = 0.0f;
static float powerball_accumulator = 0.0f;
balloon_accumulator += deltaTime;
powerball_accumulator += deltaTime;
if (balloon_accumulator >= BALLOON_INTERVAL) {
balloon_accumulator -= BALLOON_INTERVAL;
const int INDEX = (static_cast<int>(counter_ / SPEED)) % SETS.size();
balloon_manager_->deployFormation(SETS.at(INDEX), -60);
}
if (powerball_accumulator >= POWERBALL_INTERVAL && counter_ > 0) {
powerball_accumulator -= POWERBALL_INTERVAL;
balloon_manager_->createPowerBall(); balloon_manager_->createPowerBall();
} }
} }
@@ -392,12 +489,12 @@ void Credits::initPlayers() {
} }
} }
// Actualiza los rectangulos negros // Actualiza los rectangulos negros (frame-based)
void Credits::updateBlackRects() { void Credits::updateBlackRects() {
static int current_step_ = steps_; static int current_step_ = steps_;
if (top_black_rect_.h != param.game.game_area.center_y - 1 && bottom_black_rect_.y != param.game.game_area.center_y + 1) { if (top_black_rect_.h != param.game.game_area.center_y - 1 && bottom_black_rect_.y != param.game.game_area.center_y + 1) {
// Si los rectangulos superior e inferior no han llegado al centro // Si los rectangulos superior e inferior no han llegado al centro
if (counter_ % 4 == 0) { if (static_cast<int>(counter_) % 4 == 0) {
// Incrementa la altura del rectangulo superior // Incrementa la altura del rectangulo superior
top_black_rect_.h = std::min(top_black_rect_.h + 1, param.game.game_area.center_y - 1); top_black_rect_.h = std::min(top_black_rect_.h + 1, param.game.game_area.center_y - 1);
@@ -435,6 +532,57 @@ void Credits::updateBlackRects() {
} }
} }
// Actualiza los rectangulos negros (time-based)
void Credits::updateBlackRects(float deltaTime) {
static float current_step_ = static_cast<float>(steps_);
constexpr float BLACK_RECT_INTERVAL = 4 * (1000.0f / 60.0f); // 66.67ms (cada 4 frames)
static float black_rect_accumulator = 0.0f;
if (top_black_rect_.h != param.game.game_area.center_y - 1 && bottom_black_rect_.y != param.game.game_area.center_y + 1) {
// Si los rectangulos superior e inferior no han llegado al centro
black_rect_accumulator += deltaTime;
if (black_rect_accumulator >= BLACK_RECT_INTERVAL) {
black_rect_accumulator -= BLACK_RECT_INTERVAL;
// Incrementa la altura del rectangulo superior
top_black_rect_.h = std::min(top_black_rect_.h + 1, param.game.game_area.center_y - 1);
// Incrementa la altura y modifica la posición del rectangulo inferior
++bottom_black_rect_.h;
bottom_black_rect_.y = std::max(bottom_black_rect_.y - 1, param.game.game_area.center_y + 1);
--current_step_;
setVolume(static_cast<int>(initial_volume_ * current_step_ / steps_));
}
} else {
// Si los rectangulos superior e inferior han llegado al centro
if (left_black_rect_.w != param.game.game_area.center_x && right_black_rect_.x != param.game.game_area.center_x) {
constexpr int SPEED = 2;
// Si los rectangulos izquierdo y derecho no han llegado al centro
// Incrementa la anchura del rectangulo situado a la izquierda
left_black_rect_.w = std::min(left_black_rect_.w + SPEED, param.game.game_area.center_x);
// Incrementa la anchura y modifica la posición del rectangulo situado a la derecha
right_black_rect_.w += SPEED;
right_black_rect_.x = std::max(right_black_rect_.x - SPEED, param.game.game_area.center_x);
--current_step_;
setVolume(static_cast<int>(initial_volume_ * current_step_ / steps_));
} else {
// Si los rectangulos izquierdo y derecho han llegado al centro
setVolume(0);
Audio::get()->stopMusic();
if (counter_pre_fade_ == 400) {
fade_out_->activate();
} else {
// Convertir deltaTime a factor de frame
const float frameFactor = deltaTime / (1000.0f / 60.0f);
counter_pre_fade_ += frameFactor;
}
}
}
}
// Actualiza el rectangulo rojo // Actualiza el rectangulo rojo
void Credits::updateRedRect() { void Credits::updateRedRect() {
border_rect_.x = left_black_rect_.x + left_black_rect_.w; border_rect_.x = left_black_rect_.x + left_black_rect_.w;
@@ -443,7 +591,7 @@ void Credits::updateRedRect() {
border_rect_.h = bottom_black_rect_.y - border_rect_.y + 1; border_rect_.h = bottom_black_rect_.y - border_rect_.y + 1;
} }
// Actualiza el estado de fade // Actualiza el estado de fade (frame-based)
void Credits::updateAllFades() { void Credits::updateAllFades() {
if (fading_) { if (fading_) {
updateBlackRects(); updateBlackRects();
@@ -461,6 +609,24 @@ void Credits::updateAllFades() {
} }
} }
// Actualiza el estado de fade (time-based)
void Credits::updateAllFades(float deltaTime) {
if (fading_) {
updateBlackRects(deltaTime);
updateRedRect();
}
fade_in_->update(); // Fade aún no migrado a deltaTime
if (fade_in_->hasEnded()) {
Audio::get()->playMusic("credits.ogg");
}
fade_out_->update(); // Fade aún no migrado a deltaTime
if (fade_out_->hasEnded()) {
Section::name = Section::Name::HI_SCORE_TABLE;
}
}
// Establece el nivel de volumen // Establece el nivel de volumen
void Credits::setVolume(int amount) { void Credits::setVolume(int amount) {
Options::audio.music.volume = std::clamp(amount, 0, 100); Options::audio.music.volume = std::clamp(amount, 0, 100);
@@ -508,13 +674,20 @@ void Credits::cycleColors() {
tiled_bg_->setColor(color_); tiled_bg_->setColor(color_);
} }
// Actualza los jugadores // Actualza los jugadores (frame-based)
void Credits::updatePlayers() { void Credits::updatePlayers() {
for (auto &player : players_) { for (auto &player : players_) {
player->update(); player->update();
} }
} }
// Actualza los jugadores (time-based)
void Credits::updatePlayers(float deltaTime) {
for (auto &player : players_) {
player->update(deltaTime);
}
}
// Renderiza los jugadores // Renderiza los jugadores
void Credits::renderPlayers() { void Credits::renderPlayers() {
for (auto const &player : players_) { for (auto const &player : players_) {

View File

@@ -25,6 +25,12 @@ class Credits {
// --- Bucle principal --- // --- Bucle principal ---
void run(); void run();
private:
// --- Métodos del bucle principal ---
void update(); // Actualización principal de la lógica (frame-based)
void update(float deltaTime); // Actualización principal de la lógica (time-based)
auto calculateDeltaTime() -> float; // Calcula el deltatime
private: private:
// --- Constantes de clase --- // --- Constantes de clase ---
static constexpr int PLAY_AREA_HEIGHT = 200; static constexpr int PLAY_AREA_HEIGHT = 200;
@@ -41,10 +47,10 @@ class Credits {
SDL_Texture *canvas_; // Textura donde se dibuja todo SDL_Texture *canvas_; // Textura donde se dibuja todo
// --- Temporización y contadores --- // --- Temporización y contadores ---
Uint64 ticks_ = 0; // Control de velocidad del programa Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime
Uint32 counter_ = 0; // Contador principal de lógica float counter_ = 0; // Contador principal de lógica
Uint32 counter_pre_fade_ = 0; // Activación del fundido final float counter_pre_fade_ = 0; // Activación del fundido final
Uint32 counter_prevent_endless_ = 0; // Prevención de bucle infinito float counter_prevent_endless_ = 0; // Prevención de bucle infinito
// --- Variables de estado --- // --- Variables de estado ---
bool fading_ = false; // Estado del fade final bool fading_ = false; // Estado del fade final
@@ -101,8 +107,6 @@ class Credits {
// Borde para la ventana // Borde para la ventana
SDL_FRect border_rect_ = play_area_; // Delimitador de ventana SDL_FRect border_rect_ = play_area_; // Delimitador de ventana
// --- Métodos del bucle principal ---
void update(); // Actualización principal de la lógica
void render(); // Renderizado de la escena void render(); // Renderizado de la escena
static void checkEvents(); // Manejo de eventos static void checkEvents(); // Manejo de eventos
void checkInput(); // Procesamiento de entrada void checkInput(); // Procesamiento de entrada
@@ -110,19 +114,24 @@ class Credits {
// --- Métodos de renderizado --- // --- Métodos de renderizado ---
void fillTextTexture(); // Crear textura de texto de créditos void fillTextTexture(); // Crear textura de texto de créditos
void fillCanvas(); // Renderizar todos los sprites y fondos void fillCanvas(); // Renderizar todos los sprites y fondos
void updateTextureDstRects(); // Actualizar destinos de texturas
void renderPlayers(); // Renderiza los jugadores void renderPlayers(); // Renderiza los jugadores
// --- Métodos de lógica del juego --- // --- Métodos de lógica del juego ---
void throwBalloons(); // Lanzar globos al escenario void throwBalloons(); // Lanzar globos al escenario (frame-based)
void initPlayers(); // Inicializar jugadores void throwBalloons(float deltaTime); // Lanzar globos al escenario (time-based)
void updateAllFades(); // Actualizar estados de fade void initPlayers(); // Inicializar jugadores
void cycleColors(); // Cambiar colores de fondo void updateAllFades(); // Actualizar estados de fade (frame-based)
void updatePlayers(); // Actualza los jugadores void updateAllFades(float deltaTime); // Actualizar estados de fade (time-based)
void cycleColors(); // Cambiar colores de fondo
void updatePlayers(); // Actualza los jugadores (frame-based)
void updatePlayers(float deltaTime); // Actualza los jugadores (time-based)
// --- Métodos de interfaz --- // --- Métodos de interfaz ---
void updateBlackRects(); // Actualizar rectángulos negros (letterbox) void updateBlackRects(); // Actualizar rectángulos negros (letterbox) (frame-based)
void updateRedRect(); // Actualizar rectángulo rojo (borde) void updateBlackRects(float deltaTime); // Actualizar rectángulos negros (letterbox) (time-based)
void updateRedRect(); // Actualizar rectángulo rojo (borde)
void updateTextureDstRects(); // Actualizar destinos de texturas (frame-based)
void updateTextureDstRects(float deltaTime); // Actualizar destinos de texturas (time-based)
// --- Métodos de audio --- // --- Métodos de audio ---
static void setVolume(int amount); // Establecer volumen static void setVolume(int amount); // Establecer volumen