arreglant balloon.cpp per a deltaTime pur

This commit is contained in:
2025-09-19 14:15:44 +02:00
parent 568b941990
commit d4a0189dc8
11 changed files with 307 additions and 240 deletions

View File

@@ -23,7 +23,7 @@ Balloon::Balloon(const Config& config)
creation_counter_ini_(config.creation_counter),
type_(config.type),
size_(config.size),
speed_(config.speed),
game_tempo_(config.game_tempo),
play_area_(config.play_area),
sound_(config.sound) {
switch (type_) {
@@ -147,9 +147,8 @@ void Balloon::move(float deltaTime) {
}
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;
// DeltaTime puro: velocidad (pixels/ms) * tempo * tiempo (ms)
x_ += vx_ * game_tempo_ * deltaTime;
const int CLIP = 2;
const float MIN_X = play_area_.x - CLIP;
@@ -161,9 +160,8 @@ void Balloon::handleHorizontalMovement(float deltaTime) {
}
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;
// DeltaTime puro: velocidad (pixels/ms) * tempo * tiempo (ms)
y_ += vy_ * game_tempo_ * deltaTime;
if (shouldCheckTopCollision()) {
handleTopCollision();
@@ -219,15 +217,8 @@ void Balloon::handleBottomCollision() {
}
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_;
}
// DeltaTime puro: aceleración (pixels/ms²) * tempo * tiempo (ms)
vy_ += gravity_ * game_tempo_ * deltaTime;
}
void Balloon::playBouncingSound() {
@@ -250,9 +241,8 @@ void Balloon::update(float deltaTime) {
shiftSprite();
shiftColliders();
sprite_->update(deltaTime);
// Convertir deltaTime (milisegundos) a factor de frame (asumiendo 60fps)
float frameFactor = deltaTime / (1000.0f / 60.0f);
counter_ += frameFactor;
// Contador interno con deltaTime puro
counter_ += deltaTime;
}
// Actualiza los estados del globo (time-based)
@@ -264,17 +254,14 @@ void Balloon::updateState(float deltaTime) {
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;
// Cada 166ms (equivalente a 10 frames a 60fps)
movement_accumulator_ += deltaTime;
if (movement_accumulator_ >= 10.0f) {
movement_accumulator_ -= 10.0f;
if (movement_accumulator_ >= 166.0f) {
movement_accumulator_ -= 166.0f;
y_++;
x_ += vx_;
x_ += vx_ * 10.0f; // Movimiento equivalente a 10 frames de velocidad horizontal
// Comprueba no se salga por los laterales
const int MIN_X = play_area_.x;
@@ -282,11 +269,11 @@ void Balloon::updateState(float deltaTime) {
if (x_ < MIN_X || x_ > MAX_X) {
// Corrige y cambia el sentido de la velocidad
x_ -= vx_;
x_ -= vx_ * 10.0f;
vx_ = -vx_;
}
}
creation_counter_ -= frameFactor;
creation_counter_ -= deltaTime;
if (creation_counter_ < 0) creation_counter_ = 0;
}

View File

@@ -36,10 +36,12 @@ class Balloon {
"balloon_pop2.wav",
"balloon_pop3.wav"};
static constexpr float VELX_POSITIVE = 0.7F;
static constexpr float VELX_NEGATIVE = -0.7F;
// Velocidades horizontales en pixels/ms (convertidas desde 0.7 pixels/frame a 60fps)
static constexpr float VELX_POSITIVE = 0.7F / (1000.0F / 60.0F); // ~0.042 pixels/ms
static constexpr float VELX_NEGATIVE = -0.7F / (1000.0F / 60.0F); // ~-0.042 pixels/ms
static constexpr std::array<float, 5> SPEED = {0.60F, 0.70F, 0.80F, 0.90F, 1.00F};
// Multiplicadores de tempo del juego (sin cambios, son puros multiplicadores)
static constexpr std::array<float, 5> GAME_TEMPO = {0.60F, 0.70F, 0.80F, 0.90F, 1.00F};
static constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
static constexpr int POWERBALL_COUNTER = 8;
@@ -74,7 +76,7 @@ class Balloon {
Type type = Type::BALLOON;
Size size = Size::EXTRALARGE;
float vel_x = VELX_POSITIVE;
float speed = SPEED.at(0);
float game_tempo = GAME_TEMPO.at(0);
Uint16 creation_counter = 0;
SDL_FRect play_area = {.x = 0.0F, .y = 0.0F, .w = 0.0F, .h = 0.0F};
std::shared_ptr<Texture> texture = nullptr;
@@ -120,7 +122,7 @@ class Balloon {
// --- Setters ---
void setVelY(float vel_y) { vy_ = vel_y; }
void setSpeed(float speed) { speed_ = speed; }
void setGameTempo(float tempo) { game_tempo_ = tempo; }
void setInvulnerable(bool value) { invulnerable_ = value; }
void setBouncingSound(bool value) { sound_.bouncing_enabled = value; }
void setPoppingSound(bool value) { sound_.poping_enabled = value; }
@@ -263,8 +265,7 @@ class Balloon {
Size size_; // Tamaño de globo
Uint8 menace_; // Amenaza que genera el globo
Uint32 counter_ = 0; // Contador interno
float travel_y_ = 1.0F; // Distancia a recorrer en Y antes de aplicar gravedad
float speed_; // Velocidad del globo
float game_tempo_; // Multiplicador de tempo del juego
float movement_accumulator_ = 0.0f; // Acumulador para movimiento durante creación (deltaTime)
Uint8 power_; // Poder que alberga el globo
SDL_FRect play_area_; // Zona de movimiento del globo

View File

@@ -82,7 +82,7 @@ class BalloonFormations {
private:
// --- Constantes ---
static constexpr int BALLOON_SPAWN_HEIGHT = 208; // Altura desde el suelo en la que aparecen los globos
static constexpr int DEFAULT_CREATION_TIME = 200; // Tiempo base de creación de los globos para las formaciones
static constexpr int DEFAULT_CREATION_TIME = 3334; // Tiempo base de creación de los globos en ms (200 frames × 16.67ms)
// --- Variables ---
std::vector<Formation> formations_; // Vector con todas las formaciones disponibles

View File

@@ -82,11 +82,11 @@ void BalloonManager::render() {
// Crea una formación de globos
void BalloonManager::deployRandomFormation(int stage) {
// Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última
if (balloon_deploy_counter_ == 0) {
if (balloon_deploy_counter_ >= DEFAULT_BALLOON_DEPLOY_COUNTER) {
// En este punto se decide entre crear una powerball o una formación enemiga
if ((rand() % 100 < 15) && (canPowerBallBeCreated())) {
createPowerBall(); // Crea una powerball
balloon_deploy_counter_ = 10; // Da un poco de margen para que se creen mas globos
balloon_deploy_counter_ = -167; // Resetea con pequeño retraso (10 frames = 167ms negativos)
} else {
// Decrementa el contador de despliegues de globos necesarios para la siguiente PowerBall
if (power_ball_counter_ > 0) {
@@ -113,13 +113,13 @@ void BalloonManager::deployRandomFormation(int stage) {
.type = balloon.type,
.size = balloon.size,
.vel_x = balloon.vel_x,
.speed = balloon_speed_,
.game_tempo = balloon_speed_,
.creation_counter = static_cast<Uint16>(creation_time_enabled_ ? balloon.creation_counter : 0)};
createBalloon(config);
}
// Reinicia el contador para el próximo despliegue
balloon_deploy_counter_ = DEFAULT_BALLOON_DEPLOY_COUNTER;
balloon_deploy_counter_ = 0;
}
}
}
@@ -134,7 +134,7 @@ void BalloonManager::deployFormation(int formation_id) {
.type = balloon.type,
.size = balloon.size,
.vel_x = balloon.vel_x,
.speed = balloon_speed_,
.game_tempo = balloon_speed_,
.creation_counter = balloon.creation_counter};
createBalloon(config);
}
@@ -150,7 +150,7 @@ void BalloonManager::deployFormation(int formation_id, float y) {
.type = balloon.type,
.size = balloon.size,
.vel_x = balloon.vel_x,
.speed = balloon_speed_,
.game_tempo = balloon_speed_,
.creation_counter = balloon.creation_counter};
createBalloon(config);
}
@@ -164,12 +164,8 @@ void BalloonManager::freeBalloons() {
// 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;
}
// DeltaTime puro - contador incrementa hasta llegar al umbral
balloon_deploy_counter_ += deltaTime;
}
// Indica si se puede crear una powerball
@@ -214,14 +210,15 @@ void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon,
.y = balloon->getPosY() + ((PARENT_HEIGHT - CHILD_HEIGHT) / 2),
.size = static_cast<Balloon::Size>(static_cast<int>(balloon->getSize()) - 1),
.vel_x = direction == "LEFT" ? Balloon::VELX_NEGATIVE : Balloon::VELX_POSITIVE,
.speed = balloon_speed_,
.game_tempo = balloon_speed_,
.creation_counter = 0};
// Crea el globo
auto b = createBalloon(config);
// Establece parametros
b->setVelY(b->getType() == Balloon::Type::BALLOON ? -2.50F : Balloon::VELX_NEGATIVE * 2.0F);
// Establece parametros (deltaTime puro - valores ya en pixels/ms)
constexpr float VEL_Y_BALLOON_PER_MS = -0.15F; // -2.50F convertido a pixels/ms
b->setVelY(b->getType() == Balloon::Type::BALLOON ? VEL_Y_BALLOON_PER_MS : Balloon::VELX_NEGATIVE * 2.0F);
// Herencia de estados
if (balloon->isStopped()) { b->stop(); }
@@ -248,7 +245,7 @@ void BalloonManager::createPowerBall() {
.type = Balloon::Type::POWERBALL,
.size = Balloon::Size::EXTRALARGE,
.vel_x = VEL_X.at(LUCK),
.speed = balloon_speed_,
.game_tempo = balloon_speed_,
.creation_counter = 0,
.play_area = play_area_,
.texture = balloon_textures_.at(4),
@@ -270,7 +267,7 @@ void BalloonManager::createPowerBall() {
void BalloonManager::setBalloonSpeed(float speed) {
balloon_speed_ = speed;
for (auto &balloon : balloons_) {
balloon->setSpeed(speed);
balloon->setGameTempo(speed);
}
}
@@ -283,7 +280,7 @@ auto BalloonManager::popBalloon(const std::shared_ptr<Balloon> &balloon) -> int
balloon->pop(true);
score = destroyAllBalloons();
power_ball_enabled_ = false;
balloon_deploy_counter_ = 20;
balloon_deploy_counter_ = -334; // Resetea con retraso (20 frames = 334ms negativos)
} else {
score = balloon->getScore();
if (balloon->getSize() != Balloon::Size::SMALL) {
@@ -339,7 +336,7 @@ auto BalloonManager::destroyAllBalloons() -> int {
score += destroyBalloon(balloon);
}
balloon_deploy_counter_ = 300;
balloon_deploy_counter_ = -5000; // Resetea con retraso grande (300 frames = 5000ms negativos)
Screen::get()->flash(Colors::FLASH, 3);
Screen::get()->shake();

View File

@@ -82,7 +82,7 @@ class BalloonManager {
private:
// --- Constantes ---
static const int DEFAULT_BALLOON_DEPLOY_COUNTER = 300;
static const int DEFAULT_BALLOON_DEPLOY_COUNTER = 5000; // 300 frames × 16.67ms = 5000ms
// --- Objetos y punteros ---
Balloons balloons_; // Vector con los globos activos
@@ -96,8 +96,8 @@ class BalloonManager {
// --- Variables de estado ---
SDL_FRect play_area_ = param.game.play_area.rect;
float balloon_speed_ = Balloon::SPEED.at(0);
float default_balloon_speed_ = Balloon::SPEED.at(0);
float balloon_speed_ = Balloon::GAME_TEMPO.at(0);
float default_balloon_speed_ = Balloon::GAME_TEMPO.at(0);
float balloon_deploy_counter_ = 0;
int power_ball_counter_ = 0;
int last_balloon_deploy_ = 0;

View File

@@ -80,11 +80,12 @@ struct BalloonSettings {
grav(g) {}
};
// Valores para deltaTime puro: vel en pixels/ms, grav en pixels/ms² (aceleración)
constexpr std::array<BalloonSettings, 4> SETTINGS = {{
BalloonSettings(2.75F, 0.09F), // Globo 0
BalloonSettings(3.70F, 0.10F), // Globo 1
BalloonSettings(4.70F, 0.10F), // Globo 2
BalloonSettings(5.45F, 0.10F) // Globo 3
BalloonSettings(2.75F / 16.67F, 0.09F / (16.67F * 16.67F)), // Globo 0: vel=0.165 pixels/ms, grav=0.00032 pixels/ms²
BalloonSettings(3.70F / 16.67F, 0.10F / (16.67F * 16.67F)), // Globo 1: vel=0.222 pixels/ms, grav=0.00036 pixels/ms²
BalloonSettings(4.70F / 16.67F, 0.10F / (16.67F * 16.67F)), // Globo 2: vel=0.282 pixels/ms, grav=0.00036 pixels/ms²
BalloonSettings(5.45F / 16.67F, 0.10F / (16.67F * 16.67F)) // Globo 3: vel=0.327 pixels/ms, grav=0.00036 pixels/ms²
}};
constexpr std::array<const char*, 4> COLORS = {

View File

@@ -1546,21 +1546,21 @@ void Game::initDifficultyVars() {
// Variables relacionadas con la dificultad
switch (difficulty_) {
case Difficulty::Code::EASY: {
balloon_manager_->setDefaultBalloonSpeed(Balloon::SPEED.at(0));
balloon_manager_->setDefaultBalloonSpeed(Balloon::GAME_TEMPO.at(0));
difficulty_score_multiplier_ = 0.5F;
scoreboard_->setColor(param.scoreboard.easy_color);
break;
}
case Difficulty::Code::NORMAL: {
balloon_manager_->setDefaultBalloonSpeed(Balloon::SPEED.at(0));
balloon_manager_->setDefaultBalloonSpeed(Balloon::GAME_TEMPO.at(0));
difficulty_score_multiplier_ = 1.0F;
scoreboard_->setColor(param.scoreboard.normal_color);
break;
}
case Difficulty::Code::HARD: {
balloon_manager_->setDefaultBalloonSpeed(Balloon::SPEED.at(4));
balloon_manager_->setDefaultBalloonSpeed(Balloon::GAME_TEMPO.at(4));
difficulty_score_multiplier_ = 1.5F;
scoreboard_->setColor(param.scoreboard.hard_color);
break;
@@ -1813,9 +1813,9 @@ void Game::checkAndUpdateBalloonSpeed() {
for (size_t i = 0; i < std::size(THRESHOLDS); ++i) {
// Si la velocidad actual del globo es la correspondiente al umbral "i" y el porcentaje de progreso ha superado ese umbral
if (balloon_manager_->getBalloonSpeed() == Balloon::SPEED.at(i) && PERCENT > THRESHOLDS.at(i)) {
if (balloon_manager_->getBalloonSpeed() == Balloon::GAME_TEMPO.at(i) && PERCENT > THRESHOLDS.at(i)) {
// Sube la velocidad al siguiente nivel (i + 1)
balloon_manager_->setBalloonSpeed(Balloon::SPEED.at(i + 1));
balloon_manager_->setBalloonSpeed(Balloon::GAME_TEMPO.at(i + 1));
return;
}
}