time-based: Game::update(dt_s) sense gate, propaga dt a totes les entitats i sub-comptadors (counter_/death/stage/time-stopped/enemy-deploy/shake/game-completed)
This commit is contained in:
@@ -393,15 +393,13 @@ void Player::setAlive(bool value) {
|
|||||||
if (!value) {
|
if (!value) {
|
||||||
death_sprite_->setPosX(head_sprite_->getRect().x);
|
death_sprite_->setPosX(head_sprite_->getRect().x);
|
||||||
death_sprite_->setPosY(head_sprite_->getRect().y);
|
death_sprite_->setPosY(head_sprite_->getRect().y);
|
||||||
// MovingSprite comparteix vx/vy/ax/ay entre frame-based i time-based.
|
// Física del cadàver en px/s i px/s² — Game crida Player::update(dt_s)
|
||||||
// De moment fixem els valors en px/frame perquè Game encara crida
|
// que delega a death_sprite_->update(dt_s) (time-based).
|
||||||
// Player::update() frame-based. Quan Game flippi a time-based caldrà
|
death_sprite_->setAccelY(DEATH_ACCEL_Y_PX_PER_S2);
|
||||||
// canviar a px/s (12.0 / -396.0 / +-198.0) — vegeu DEATH_*_PX_PER_S2/S.
|
death_sprite_->setVelY(DEATH_VEL_Y_PX_PER_S);
|
||||||
death_sprite_->setAccelY(0.2F);
|
death_sprite_->setVelX(DEATH_VEL_X_PX_PER_S);
|
||||||
death_sprite_->setVelY(-6.6F);
|
|
||||||
death_sprite_->setVelX(3.3F);
|
|
||||||
if (rand() % 2 == 0) {
|
if (rand() % 2 == 0) {
|
||||||
death_sprite_->setVelX(-3.3F);
|
death_sprite_->setVelX(-DEATH_VEL_X_PX_PER_S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+383
-64
@@ -20,13 +20,14 @@
|
|||||||
#include "core/rendering/texture.h" // for Texture
|
#include "core/rendering/texture.h" // for Texture
|
||||||
#include "core/resources/asset.h" // for Asset
|
#include "core/resources/asset.h" // for Asset
|
||||||
#include "core/resources/resource.h"
|
#include "core/resources/resource.h"
|
||||||
#include "game/defaults.hpp" // for PLAY_AREA_CENTER_X, BLOCK, PLAY_AREA_CEN...
|
#include "core/system/delta_time.hpp" // for DeltaTime
|
||||||
#include "game/entities/balloon.h" // for Balloon, Balloon::VELX_NEGATIVE, BALLOON_...
|
#include "game/defaults.hpp" // for PLAY_AREA_CENTER_X, BLOCK, PLAY_AREA_CEN...
|
||||||
#include "game/entities/bullet.h" // for Bullet, Bullet::Kind::LEFT, Bullet::Kind::RIGHT, BULLE...
|
#include "game/entities/balloon.h" // for Balloon, Balloon::VELX_NEGATIVE, BALLOON_...
|
||||||
#include "game/entities/item.h" // for Item
|
#include "game/entities/bullet.h" // for Bullet, Bullet::Kind::LEFT, Bullet::Kind::RIGHT, BULLE...
|
||||||
#include "game/entities/player.h" // for Player
|
#include "game/entities/item.h" // for Item
|
||||||
#include "game/options.hpp" // for Options
|
#include "game/entities/player.h" // for Player
|
||||||
#include "game/ui/menu.h" // for Menu
|
#include "game/options.hpp" // for Options
|
||||||
|
#include "game/ui/menu.h" // for Menu
|
||||||
namespace Ja {
|
namespace Ja {
|
||||||
struct Sound;
|
struct Sound;
|
||||||
} // namespace Ja
|
} // namespace Ja
|
||||||
@@ -102,6 +103,9 @@ Game::Game(int num_players, int current_stage, SDL_Renderer *renderer, bool demo
|
|||||||
|
|
||||||
// Inicializa las variables necesarias para la sección 'Game'
|
// Inicializa las variables necesarias para la sección 'Game'
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
// Reset del rellotge perquè el primer dt_s no inclogui el temps de càrrega.
|
||||||
|
DeltaTime::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::~Game() {
|
Game::~Game() {
|
||||||
@@ -200,18 +204,27 @@ void Game::init() {
|
|||||||
|
|
||||||
game_completed_ = false;
|
game_completed_ = false;
|
||||||
game_completed_counter_ = 0;
|
game_completed_counter_ = 0;
|
||||||
|
game_completed_counter_s_ = 0.0F;
|
||||||
section_->name = SECTION_PROG_GAME;
|
section_->name = SECTION_PROG_GAME;
|
||||||
section_->subsection = SUBSECTION_GAME_PLAY_1P;
|
section_->subsection = SUBSECTION_GAME_PLAY_1P;
|
||||||
menace_current_ = 0;
|
menace_current_ = 0;
|
||||||
menace_threshold_ = 0;
|
menace_threshold_ = 0;
|
||||||
hi_score_achieved_ = false;
|
hi_score_achieved_ = false;
|
||||||
stage_bitmap_counter_ = STAGE_COUNTER;
|
stage_bitmap_counter_ = STAGE_COUNTER;
|
||||||
|
stage_bitmap_counter_s_ = STAGE_COUNTER / 60.0F;
|
||||||
death_counter_ = Player::DEATH_COUNTER;
|
death_counter_ = Player::DEATH_COUNTER;
|
||||||
|
death_counter_s_ = Player::DEATH_COUNTER / 60.0F;
|
||||||
time_stopped_ = false;
|
time_stopped_ = false;
|
||||||
time_stopped_counter_ = 0;
|
time_stopped_counter_ = 0;
|
||||||
|
time_stopped_counter_s_ = 0.0F;
|
||||||
counter_ = 0;
|
counter_ = 0;
|
||||||
|
elapsed_s_ = 0.0F;
|
||||||
last_enemy_deploy_ = 0;
|
last_enemy_deploy_ = 0;
|
||||||
enemy_deploy_counter_ = 0;
|
enemy_deploy_counter_ = 0;
|
||||||
|
enemy_deploy_counter_s_ = 0.0F;
|
||||||
|
enemy_deploy_phase_s_ = 0.0F;
|
||||||
|
shake_phase_s_ = 0.0F;
|
||||||
|
helper_counter_s_ = 0.0F;
|
||||||
enemy_speed_ = default_enemy_speed_;
|
enemy_speed_ = default_enemy_speed_;
|
||||||
effect_.flash = false;
|
effect_.flash = false;
|
||||||
effect_.shake = false;
|
effect_.shake = false;
|
||||||
@@ -284,15 +297,15 @@ void Game::init() {
|
|||||||
// Con los globos creados, calcula el nivel de amenaza
|
// Con los globos creados, calcula el nivel de amenaza
|
||||||
evaluateAndSetMenace();
|
evaluateAndSetMenace();
|
||||||
|
|
||||||
// Inicializa el bitmap de 1000 puntos
|
// Inicializa el bitmap de 1000 puntos (px/s i px/s²; -0.5 px/frame → -30 px/s)
|
||||||
n1000_sprite_->setPosX(0);
|
n1000_sprite_->setPosX(0);
|
||||||
n1000_sprite_->setPosY(0);
|
n1000_sprite_->setPosY(0);
|
||||||
n1000_sprite_->setWidth(26);
|
n1000_sprite_->setWidth(26);
|
||||||
n1000_sprite_->setHeight(9);
|
n1000_sprite_->setHeight(9);
|
||||||
n1000_sprite_->setVelX(0.0F);
|
n1000_sprite_->setVelX(0.0F);
|
||||||
n1000_sprite_->setVelY(-0.5F);
|
n1000_sprite_->setVelY(-30.0F);
|
||||||
n1000_sprite_->setAccelX(0.0F);
|
n1000_sprite_->setAccelX(0.0F);
|
||||||
n1000_sprite_->setAccelY(-0.1F);
|
n1000_sprite_->setAccelY(-360.0F);
|
||||||
n1000_sprite_->setSpriteClip(0, 0, 26, 9);
|
n1000_sprite_->setSpriteClip(0, 0, 26, 9);
|
||||||
n1000_sprite_->setEnabled(false);
|
n1000_sprite_->setEnabled(false);
|
||||||
n1000_sprite_->setEnabledCounter(0);
|
n1000_sprite_->setEnabledCounter(0);
|
||||||
@@ -305,9 +318,9 @@ void Game::init() {
|
|||||||
n2500_sprite_->setWidth(28);
|
n2500_sprite_->setWidth(28);
|
||||||
n2500_sprite_->setHeight(9);
|
n2500_sprite_->setHeight(9);
|
||||||
n2500_sprite_->setVelX(0.0F);
|
n2500_sprite_->setVelX(0.0F);
|
||||||
n2500_sprite_->setVelY(-0.5F);
|
n2500_sprite_->setVelY(-30.0F);
|
||||||
n2500_sprite_->setAccelX(0.0F);
|
n2500_sprite_->setAccelX(0.0F);
|
||||||
n2500_sprite_->setAccelY(-0.1F);
|
n2500_sprite_->setAccelY(-360.0F);
|
||||||
n2500_sprite_->setSpriteClip(26, 0, 28, 9);
|
n2500_sprite_->setSpriteClip(26, 0, 28, 9);
|
||||||
n2500_sprite_->setEnabled(false);
|
n2500_sprite_->setEnabled(false);
|
||||||
n2500_sprite_->setEnabledCounter(0);
|
n2500_sprite_->setEnabledCounter(0);
|
||||||
@@ -320,9 +333,9 @@ void Game::init() {
|
|||||||
n5000_sprite_->setWidth(28);
|
n5000_sprite_->setWidth(28);
|
||||||
n5000_sprite_->setHeight(9);
|
n5000_sprite_->setHeight(9);
|
||||||
n5000_sprite_->setVelX(0.0F);
|
n5000_sprite_->setVelX(0.0F);
|
||||||
n5000_sprite_->setVelY(-0.5F);
|
n5000_sprite_->setVelY(-30.0F);
|
||||||
n5000_sprite_->setAccelX(0.0F);
|
n5000_sprite_->setAccelX(0.0F);
|
||||||
n5000_sprite_->setAccelY(-0.1F);
|
n5000_sprite_->setAccelY(-360.0F);
|
||||||
n5000_sprite_->setSpriteClip(54, 0, 28, 9);
|
n5000_sprite_->setSpriteClip(54, 0, 28, 9);
|
||||||
n5000_sprite_->setEnabled(false);
|
n5000_sprite_->setEnabled(false);
|
||||||
n5000_sprite_->setEnabledCounter(0);
|
n5000_sprite_->setEnabledCounter(0);
|
||||||
@@ -1450,6 +1463,26 @@ void Game::updatePlayers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza las variables del jugador (time-based)
|
||||||
|
void Game::updatePlayers(float dt_s) {
|
||||||
|
for (auto *player : players_) {
|
||||||
|
player->update(dt_s);
|
||||||
|
|
||||||
|
if (checkPlayerBalloonCollision(player)) {
|
||||||
|
if (player->isAlive()) {
|
||||||
|
if (demo_.enabled) {
|
||||||
|
section_->name = SECTION_PROG_TITLE;
|
||||||
|
section_->subsection = SUBSECTION_TITLE_INSTRUCTIONS;
|
||||||
|
} else {
|
||||||
|
killPlayer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPlayerItemCollision(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dibuja a los jugadores
|
// Dibuja a los jugadores
|
||||||
void Game::renderPlayers() {
|
void Game::renderPlayers() {
|
||||||
for (auto *player : players_) {
|
for (auto *player : players_) {
|
||||||
@@ -1497,6 +1530,45 @@ void Game::updateStage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza las variables de la fase (time-based)
|
||||||
|
void Game::updateStage(float dt_s) {
|
||||||
|
if (stage_[current_stage_].current_power >= stage_[current_stage_].power_to_complete) {
|
||||||
|
current_stage_++;
|
||||||
|
last_stage_reached_ = current_stage_;
|
||||||
|
if (current_stage_ == 10) {
|
||||||
|
game_completed_ = true;
|
||||||
|
current_stage_ = 9;
|
||||||
|
stage_[current_stage_].current_power = 0;
|
||||||
|
destroyAllBalloons();
|
||||||
|
stage_[current_stage_].current_power = 0;
|
||||||
|
menace_current_ = 255;
|
||||||
|
for (auto *player : players_) {
|
||||||
|
if (player->isAlive()) {
|
||||||
|
player->addScore(1000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateHiScore();
|
||||||
|
Audio::get()->stopMusic();
|
||||||
|
}
|
||||||
|
Audio::get()->playSound(stage_change_sound_);
|
||||||
|
stage_bitmap_counter_ = 0;
|
||||||
|
stage_bitmap_counter_s_ = 0.0F;
|
||||||
|
enemy_speed_ = default_enemy_speed_;
|
||||||
|
setBalloonSpeed(enemy_speed_);
|
||||||
|
effect_.flash = true;
|
||||||
|
effect_.shake = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stage_bitmap_counter_s_ < (STAGE_COUNTER / 60.0F)) {
|
||||||
|
stage_bitmap_counter_s_ += dt_s;
|
||||||
|
}
|
||||||
|
stage_bitmap_counter_ = std::min<int>(STAGE_COUNTER, static_cast<int>(stage_bitmap_counter_s_ * 60.0F));
|
||||||
|
|
||||||
|
if (game_completed_) {
|
||||||
|
stage_bitmap_counter_ = std::min<int>(stage_bitmap_counter_, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza el estado de muerte
|
// Actualiza el estado de muerte
|
||||||
void Game::updateDeath() {
|
void Game::updateDeath() {
|
||||||
// Comprueba si todos los jugadores estan muertos
|
// Comprueba si todos los jugadores estan muertos
|
||||||
@@ -1523,6 +1595,39 @@ void Game::updateDeath() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza el estado de muerte (time-based). Detecta el creuament dels llindars
|
||||||
|
// 250/200/180/120/60 (en frames) per a reproduir els bubbles als mateixos moments.
|
||||||
|
void Game::updateDeath(float dt_s) {
|
||||||
|
bool all_dead = true;
|
||||||
|
for (const auto *player : players_) {
|
||||||
|
all_dead &= (!player->isAlive());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!all_dead) { return; }
|
||||||
|
|
||||||
|
if (death_counter_s_ <= 0.0F) {
|
||||||
|
section_->subsection = SUBSECTION_GAME_GAMEOVER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float PREV_S = death_counter_s_;
|
||||||
|
death_counter_s_ = std::max(0.0F, death_counter_s_ - dt_s);
|
||||||
|
death_counter_ = static_cast<Uint16>(death_counter_s_ * 60.0F);
|
||||||
|
|
||||||
|
auto crossed = [&](float threshold_frames) {
|
||||||
|
const float TS = threshold_frames / 60.0F;
|
||||||
|
return (PREV_S > TS) && (death_counter_s_ <= TS);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (crossed(250.0F) || crossed(200.0F) || crossed(180.0F) || crossed(120.0F) || crossed(60.0F)) {
|
||||||
|
if (!demo_.enabled) {
|
||||||
|
const Uint8 INDEX = rand() % 4;
|
||||||
|
Ja::Sound *sound[4] = {bubble1_sound_, bubble2_sound_, bubble3_sound_, bubble4_sound_};
|
||||||
|
Audio::get()->playSound(sound[INDEX]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Renderiza el fade final cuando se acaba la partida
|
// Renderiza el fade final cuando se acaba la partida
|
||||||
void Game::renderDeathFade(int counter) { // Counter debe ir de 0 a 150
|
void Game::renderDeathFade(int counter) { // Counter debe ir de 0 a 150
|
||||||
SDL_SetRenderDrawColor(renderer_, 0x27, 0x27, 0x36, 255);
|
SDL_SetRenderDrawColor(renderer_, 0x27, 0x27, 0x36, 255);
|
||||||
@@ -1555,6 +1660,13 @@ void Game::updateBalloons() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza los globos (time-based)
|
||||||
|
void Game::updateBalloons(float dt_s) {
|
||||||
|
for (auto *balloon : balloons_) {
|
||||||
|
balloon->update(dt_s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pinta en pantalla todos los globos activos
|
// Pinta en pantalla todos los globos activos
|
||||||
void Game::renderBalloons() {
|
void Game::renderBalloons() {
|
||||||
for (auto *balloon : balloons_) {
|
for (auto *balloon : balloons_) {
|
||||||
@@ -1914,6 +2026,17 @@ void Game::moveBullets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mueve las balas activas (time-based)
|
||||||
|
void Game::moveBullets(float dt_s) {
|
||||||
|
for (auto *bullet : bullets_) {
|
||||||
|
if (bullet->isEnabled()) {
|
||||||
|
if (bullet->move(dt_s) == Bullet::MoveResult::OUT) {
|
||||||
|
players_[bullet->getOwner()]->decScoreMultiplier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pinta las balas activas
|
// Pinta las balas activas
|
||||||
void Game::renderBullets() {
|
void Game::renderBullets() {
|
||||||
for (auto *bullet : bullets_) {
|
for (auto *bullet : bullets_) {
|
||||||
@@ -1954,6 +2077,19 @@ void Game::updateItems() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza los items (time-based)
|
||||||
|
void Game::updateItems(float dt_s) {
|
||||||
|
for (auto *item : items_) {
|
||||||
|
if (item->isEnabled()) {
|
||||||
|
item->update(dt_s);
|
||||||
|
if (item->isOnFloor()) {
|
||||||
|
Audio::get()->playSound(coffee_machine_sound_);
|
||||||
|
effect_.shake = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pinta los items activos
|
// Pinta los items activos
|
||||||
void Game::renderItems() {
|
void Game::renderItems() {
|
||||||
for (auto *item : items_) {
|
for (auto *item : items_) {
|
||||||
@@ -2079,6 +2215,30 @@ void Game::updateShakeEffect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza el efecto de agitar la pantalla (time-based). Decrementa
|
||||||
|
// `shake_counter` a cadència fixa de 60Hz amb un acumulador de fase
|
||||||
|
// (independent del framerate) — el render de `updateBackground` segueix
|
||||||
|
// llegint la paritat del counter per fer vibrar els edificis.
|
||||||
|
void Game::updateShakeEffect(float dt_s) {
|
||||||
|
if (!effect_.shake) {
|
||||||
|
shake_phase_s_ = 0.0F;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
constexpr float STEP_S = 1.0F / 60.0F;
|
||||||
|
shake_phase_s_ += dt_s;
|
||||||
|
while (shake_phase_s_ >= STEP_S) {
|
||||||
|
shake_phase_s_ -= STEP_S;
|
||||||
|
if (effect_.shake_counter > 0) {
|
||||||
|
effect_.shake_counter--;
|
||||||
|
} else {
|
||||||
|
effect_.shake = false;
|
||||||
|
effect_.shake_counter = SHAKE_COUNTER;
|
||||||
|
shake_phase_s_ = 0.0F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Crea un SmartSprite para arrojar el item café al recibir un impacto
|
// Crea un SmartSprite para arrojar el item café al recibir un impacto
|
||||||
void Game::throwCoffee(int x, int y) {
|
void Game::throwCoffee(int x, int y) {
|
||||||
auto *ss = new SmartSprite(item_textures_[4], renderer_);
|
auto *ss = new SmartSprite(item_textures_[4], renderer_);
|
||||||
@@ -2088,10 +2248,12 @@ void Game::throwCoffee(int x, int y) {
|
|||||||
ss->setPosY(y - 8);
|
ss->setPosY(y - 8);
|
||||||
ss->setWidth(16);
|
ss->setWidth(16);
|
||||||
ss->setHeight(16);
|
ss->setHeight(16);
|
||||||
ss->setVelX(-1.0F + ((rand() % 5) * 0.5F));
|
// Conversió a px/s i px/s² (era -1..1 px/frame i 0.2 px/frame²)
|
||||||
ss->setVelY(-4.0F);
|
const float VX_PX_PER_S = (-1.0F + (static_cast<float>(rand() % 5) * 0.5F)) * 60.0F;
|
||||||
|
ss->setVelX(VX_PX_PER_S);
|
||||||
|
ss->setVelY(-240.0F);
|
||||||
ss->setAccelX(0.0F);
|
ss->setAccelX(0.0F);
|
||||||
ss->setAccelY(0.2F);
|
ss->setAccelY(720.0F);
|
||||||
ss->setDestX(x + (ss->getVelX() * 50));
|
ss->setDestX(x + (ss->getVelX() * 50));
|
||||||
ss->setDestY(GAMECANVAS_HEIGHT + 1);
|
ss->setDestY(GAMECANVAS_HEIGHT + 1);
|
||||||
ss->setEnabled(true);
|
ss->setEnabled(true);
|
||||||
@@ -2109,6 +2271,13 @@ void Game::updateSmartSprites() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza los SmartSprites (time-based)
|
||||||
|
void Game::updateSmartSprites(float dt_s) {
|
||||||
|
for (auto *ss : smart_sprites_) {
|
||||||
|
ss->update(dt_s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pinta los SmartSprites activos
|
// Pinta los SmartSprites activos
|
||||||
void Game::renderSmartSprites() {
|
void Game::renderSmartSprites() {
|
||||||
for (auto *ss : smart_sprites_) {
|
for (auto *ss : smart_sprites_) {
|
||||||
@@ -2196,11 +2365,13 @@ auto Game::isTimeStopped() const -> bool {
|
|||||||
// Establece el valor de la variable
|
// Establece el valor de la variable
|
||||||
void Game::setTimeStoppedCounter(Uint16 value) {
|
void Game::setTimeStoppedCounter(Uint16 value) {
|
||||||
time_stopped_counter_ = value;
|
time_stopped_counter_ = value;
|
||||||
|
time_stopped_counter_s_ = static_cast<float>(value) / 60.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Incrementa el valor de la variable
|
// Incrementa el valor de la variable
|
||||||
void Game::incTimeStoppedCounter(Uint16 value) {
|
void Game::incTimeStoppedCounter(Uint16 value) {
|
||||||
time_stopped_counter_ += value;
|
time_stopped_counter_ += value;
|
||||||
|
time_stopped_counter_s_ += static_cast<float>(value) / 60.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza y comprueba el valor de la variable
|
// Actualiza y comprueba el valor de la variable
|
||||||
@@ -2215,6 +2386,18 @@ void Game::updateTimeStoppedCounter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza y comprueba el valor de la variable (time-based)
|
||||||
|
void Game::updateTimeStoppedCounter(float dt_s) {
|
||||||
|
if (!isTimeStopped()) { return; }
|
||||||
|
if (time_stopped_counter_s_ > 0.0F) {
|
||||||
|
time_stopped_counter_s_ = std::max(0.0F, time_stopped_counter_s_ - dt_s);
|
||||||
|
time_stopped_counter_ = static_cast<Uint16>(time_stopped_counter_s_ * 60.0F);
|
||||||
|
stopAllBalloons(TIME_STOPPED_COUNTER);
|
||||||
|
} else {
|
||||||
|
disableTimeStopItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza la variable enemyDeployCounter
|
// Actualiza la variable enemyDeployCounter
|
||||||
void Game::updateEnemyDeployCounter() {
|
void Game::updateEnemyDeployCounter() {
|
||||||
if (enemy_deploy_counter_ > 0) {
|
if (enemy_deploy_counter_ > 0) {
|
||||||
@@ -2222,6 +2405,19 @@ void Game::updateEnemyDeployCounter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza enemy_deploy_counter_ (time-based). El comptador es decrementa
|
||||||
|
// a cadència fixa de 60Hz amb un acumulador de fase: és un comptador
|
||||||
|
// discret consultat per `canPowerBallBeCreated()` i altres.
|
||||||
|
void Game::updateEnemyDeployCounter(float dt_s) {
|
||||||
|
if (enemy_deploy_counter_ <= 0) { return; }
|
||||||
|
constexpr float STEP_S = 1.0F / 60.0F;
|
||||||
|
enemy_deploy_phase_s_ += dt_s;
|
||||||
|
while (enemy_deploy_phase_s_ >= STEP_S && enemy_deploy_counter_ > 0) {
|
||||||
|
enemy_deploy_phase_s_ -= STEP_S;
|
||||||
|
enemy_deploy_counter_--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza el juego
|
// Actualiza el juego
|
||||||
void Game::update() {
|
void Game::update() {
|
||||||
// Actualiza el audio
|
// Actualiza el audio
|
||||||
@@ -2299,6 +2495,48 @@ void Game::update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza el juego (time-based). Sense el gate del SDL_GetTicks: la cadència
|
||||||
|
// la dicta dt_s, propagat des de iterate() via DeltaTime::tick(). El comptador
|
||||||
|
// global `counter_` queda derivat de `elapsed_s_*60` perquè els lectors
|
||||||
|
// existents (render de l'herba, paths del get_ready, etc.) segueixin valuant.
|
||||||
|
void Game::update(float dt_s) {
|
||||||
|
Audio::update();
|
||||||
|
|
||||||
|
updateDeathShake();
|
||||||
|
updateDeathSequence();
|
||||||
|
|
||||||
|
if (death_sequence_.phase == DeathPhase::SHAKING || death_sequence_.phase == DeathPhase::WAITING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acumulador i derivació del comptador legacy
|
||||||
|
elapsed_s_ += dt_s;
|
||||||
|
counter_ = static_cast<Uint32>(elapsed_s_ * 60.0F);
|
||||||
|
|
||||||
|
checkGameInput();
|
||||||
|
updatePlayers(dt_s);
|
||||||
|
updateBackground(dt_s);
|
||||||
|
updateBalloons(dt_s);
|
||||||
|
moveBullets(dt_s);
|
||||||
|
updateItems(dt_s);
|
||||||
|
updateStage(dt_s);
|
||||||
|
updateDeath(dt_s);
|
||||||
|
updateSmartSprites(dt_s);
|
||||||
|
updateTimeStoppedCounter(dt_s);
|
||||||
|
updateEnemyDeployCounter(dt_s);
|
||||||
|
updateShakeEffect(dt_s);
|
||||||
|
updateHelper(dt_s);
|
||||||
|
checkBulletBalloonCollision();
|
||||||
|
updateMenace();
|
||||||
|
updateBalloonSpeed();
|
||||||
|
updateGameCompleted(dt_s);
|
||||||
|
|
||||||
|
freeBullets();
|
||||||
|
freeBalloons();
|
||||||
|
freeItems();
|
||||||
|
freeSmartSprites();
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza el fondo
|
// Actualiza el fondo
|
||||||
void Game::updateBackground() {
|
void Game::updateBackground() {
|
||||||
if (!game_completed_) { // Si el juego no esta completo, la velocidad de las nubes es igual a los globos explotados
|
if (!game_completed_) { // Si el juego no esta completo, la velocidad de las nubes es igual a los globos explotados
|
||||||
@@ -2314,13 +2552,13 @@ void Game::updateBackground() {
|
|||||||
// Calcula la velocidad en función de los globos explotados y el total de globos a explotar para acabar el juego
|
// Calcula la velocidad en función de los globos explotados y el total de globos a explotar para acabar el juego
|
||||||
const float SPEED = (-0.2F) + (-3.00F * ((float)clouds_speed_ / (float)total_power_to_complete_game_));
|
const float SPEED = (-0.2F) + (-3.00F * ((float)clouds_speed_ / (float)total_power_to_complete_game_));
|
||||||
|
|
||||||
// Aplica la velocidad calculada a las nubes
|
// Aplica la velocidad calculada a las nubes (px/frame)
|
||||||
clouds1_a_->setVelX(SPEED);
|
clouds1_a_->setVelX(SPEED);
|
||||||
clouds1_b_->setVelX(SPEED);
|
clouds1_b_->setVelX(SPEED);
|
||||||
clouds2_a_->setVelX(SPEED / 2);
|
clouds2_a_->setVelX(SPEED / 2);
|
||||||
clouds2_b_->setVelX(SPEED / 2);
|
clouds2_b_->setVelX(SPEED / 2);
|
||||||
|
|
||||||
// Mueve las nubes
|
// Mueve las nubes (frame-based)
|
||||||
clouds1_a_->move();
|
clouds1_a_->move();
|
||||||
clouds1_b_->move();
|
clouds1_b_->move();
|
||||||
clouds2_a_->move();
|
clouds2_a_->move();
|
||||||
@@ -2357,6 +2595,53 @@ void Game::updateBackground() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza el fondo (time-based). Velocitats dels núvols expressades com a
|
||||||
|
// px/frame (la conversió a px/s la fa cloud->move(dt_s) multiplicant per 60
|
||||||
|
// internament — perquè MovingSprite comparteix vx_ entre frame i time-based,
|
||||||
|
// aquí passem la mateixa "velocitat per frame" * 60).
|
||||||
|
void Game::updateBackground(float dt_s) {
|
||||||
|
if (!game_completed_) {
|
||||||
|
clouds_speed_ = balloons_popped_;
|
||||||
|
} else {
|
||||||
|
if (clouds_speed_ > 400) {
|
||||||
|
clouds_speed_ -= 25;
|
||||||
|
} else {
|
||||||
|
clouds_speed_ = 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Velocitat per frame (mateixa fórmula); en time-based la passem com a px/s.
|
||||||
|
const float SPEED_PX_PER_FRAME = (-0.2F) + (-3.00F * ((float)clouds_speed_ / (float)total_power_to_complete_game_));
|
||||||
|
const float SPEED_PX_PER_S = SPEED_PX_PER_FRAME * 60.0F;
|
||||||
|
|
||||||
|
clouds1_a_->setVelX(SPEED_PX_PER_S);
|
||||||
|
clouds1_b_->setVelX(SPEED_PX_PER_S);
|
||||||
|
clouds2_a_->setVelX(SPEED_PX_PER_S / 2.0F);
|
||||||
|
clouds2_b_->setVelX(SPEED_PX_PER_S / 2.0F);
|
||||||
|
|
||||||
|
clouds1_a_->move(dt_s);
|
||||||
|
clouds1_b_->move(dt_s);
|
||||||
|
clouds2_a_->move(dt_s);
|
||||||
|
clouds2_b_->move(dt_s);
|
||||||
|
|
||||||
|
if (clouds1_a_->getPosX() < -clouds1_a_->getWidth()) { clouds1_a_->setPosX(clouds1_a_->getWidth()); }
|
||||||
|
if (clouds1_b_->getPosX() < -clouds1_b_->getWidth()) { clouds1_b_->setPosX(clouds1_b_->getWidth()); }
|
||||||
|
if (clouds2_a_->getPosX() < -clouds2_a_->getWidth()) { clouds2_a_->setPosX(clouds2_a_->getWidth()); }
|
||||||
|
if (clouds2_b_->getPosX() < -clouds2_b_->getWidth()) { clouds2_b_->setPosX(clouds2_b_->getWidth()); }
|
||||||
|
|
||||||
|
// Herba: `counter_` derivat de `elapsed_s_*60` ja oscil·la a 60Hz.
|
||||||
|
grass_sprite_->setSpriteClip(0, (6 * (counter_ / 20 % 2)), 256, 6);
|
||||||
|
|
||||||
|
if (death_shake_.active) {
|
||||||
|
const int V[] = {-1, 1, -1, 1, -1, 1, -1, 0};
|
||||||
|
buildings_sprite_->setPosX(V[death_shake_.step]);
|
||||||
|
} else if (effect_.shake) {
|
||||||
|
buildings_sprite_->setPosX(((effect_.shake_counter % 2) * 2) - 1);
|
||||||
|
} else {
|
||||||
|
buildings_sprite_->setPosX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dibuja el fondo
|
// Dibuja el fondo
|
||||||
void Game::renderBackground() {
|
void Game::renderBackground() {
|
||||||
const float GRADIENT_NUMBER = std::min(((float)balloons_popped_ / 1250.0F), 3.0F);
|
const float GRADIENT_NUMBER = std::min(((float)balloons_popped_ / 1250.0F), 3.0F);
|
||||||
@@ -2679,55 +2964,62 @@ auto Game::isDeathShaking() const -> bool {
|
|||||||
|
|
||||||
// Ejecuta un frame del juego
|
// Ejecuta un frame del juego
|
||||||
void Game::iterate() {
|
void Game::iterate() {
|
||||||
// En modo demo, no hay pausa ni game over
|
// Consum del temps real des de l'última iteració. Sempre s'ha de cridar
|
||||||
if (demo_.enabled) {
|
// perquè el rellotge no acumuli a través de transicions/sub-estats.
|
||||||
if (section_->subsection == SUBSECTION_GAME_PAUSE || section_->subsection == SUBSECTION_GAME_GAMEOVER) {
|
const float DELTA_TIME_S = DeltaTime::tick();
|
||||||
section_->name = SECTION_PROG_TITLE;
|
|
||||||
section_->subsection = SUBSECTION_TITLE_INSTRUCTIONS;
|
// En modo demo, ni pause ni game over: torna immediatament al títol
|
||||||
return;
|
if (demo_.enabled && (section_->subsection == SUBSECTION_GAME_PAUSE || section_->subsection == SUBSECTION_GAME_GAMEOVER)) {
|
||||||
}
|
section_->name = SECTION_PROG_TITLE;
|
||||||
|
section_->subsection = SUBSECTION_TITLE_INSTRUCTIONS;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sección juego en pausa
|
switch (section_->subsection) {
|
||||||
if (section_->subsection == SUBSECTION_GAME_PAUSE) {
|
case SUBSECTION_GAME_PAUSE:
|
||||||
if (!pause_initialized_) {
|
iteratePaused();
|
||||||
enterPausedGame();
|
break;
|
||||||
}
|
case SUBSECTION_GAME_GAMEOVER:
|
||||||
updatePausedGame();
|
iterateGameOver();
|
||||||
renderPausedGame();
|
break;
|
||||||
|
case SUBSECTION_GAME_PLAY_1P:
|
||||||
|
case SUBSECTION_GAME_PLAY_2P:
|
||||||
|
iteratePlaying(DELTA_TIME_S);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rama de iterate(): pause
|
||||||
|
void Game::iteratePaused() {
|
||||||
|
if (!pause_initialized_) { enterPausedGame(); }
|
||||||
|
updatePausedGame();
|
||||||
|
renderPausedGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rama de iterate(): game over
|
||||||
|
void Game::iterateGameOver() {
|
||||||
|
if (!game_over_initialized_) { enterGameOverScreen(); }
|
||||||
|
updateGameOverScreen();
|
||||||
|
renderGameOverScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rama de iterate(): joc actiu
|
||||||
|
void Game::iteratePlaying(float dt_s) {
|
||||||
|
// Si veníem de Pause/GameOver, el dt acumulat seria enorme; descarta'l.
|
||||||
|
if (pause_initialized_ || game_over_initialized_) {
|
||||||
|
DeltaTime::reset();
|
||||||
|
}
|
||||||
|
pause_initialized_ = false;
|
||||||
|
game_over_initialized_ = false;
|
||||||
|
|
||||||
|
if (Audio::getRealMusicState() == Audio::MusicState::STOPPED && !game_completed_ && !demo_.enabled && players_[0]->isAlive()) {
|
||||||
|
Audio::get()->playMusic(game_music_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sección Game Over
|
update(dt_s);
|
||||||
else if (section_->subsection == SUBSECTION_GAME_GAMEOVER) {
|
render();
|
||||||
if (!game_over_initialized_) {
|
|
||||||
enterGameOverScreen();
|
|
||||||
}
|
|
||||||
updateGameOverScreen();
|
|
||||||
renderGameOverScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sección juego jugando
|
|
||||||
else if ((section_->subsection == SUBSECTION_GAME_PLAY_1P) || (section_->subsection == SUBSECTION_GAME_PLAY_2P)) {
|
|
||||||
// Resetea los flags de inicialización de sub-estados
|
|
||||||
pause_initialized_ = false;
|
|
||||||
game_over_initialized_ = false;
|
|
||||||
|
|
||||||
// Si la música no está sonando
|
|
||||||
if ((Audio::getRealMusicState() == Audio::MusicState::STOPPED) || (Audio::getRealMusicState() == Audio::MusicState::STOPPED)) {
|
|
||||||
// Reproduce la música (nunca en modo demo: deja sonar la del título)
|
|
||||||
if (!game_completed_ && !demo_.enabled) {
|
|
||||||
if (players_[0]->isAlive()) {
|
|
||||||
Audio::get()->playMusic(game_music_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza la lógica del juego
|
|
||||||
update();
|
|
||||||
|
|
||||||
// Dibuja los objetos
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indica si el juego ha terminado
|
// Indica si el juego ha terminado
|
||||||
@@ -3109,6 +3401,19 @@ void Game::updateGameCompleted() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza el tramo final de juego (time-based)
|
||||||
|
void Game::updateGameCompleted(float dt_s) {
|
||||||
|
if (!game_completed_) { return; }
|
||||||
|
|
||||||
|
const int PREV = game_completed_counter_;
|
||||||
|
game_completed_counter_s_ += dt_s;
|
||||||
|
game_completed_counter_ = static_cast<int>(game_completed_counter_s_ * 60.0F);
|
||||||
|
|
||||||
|
if (PREV < GAME_COMPLETED_END && game_completed_counter_ >= GAME_COMPLETED_END) {
|
||||||
|
section_->subsection = SUBSECTION_GAME_GAMEOVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza las variables de ayuda
|
// Actualiza las variables de ayuda
|
||||||
void Game::updateHelper() {
|
void Game::updateHelper() {
|
||||||
// Solo ofrece ayuda cuando la amenaza es elevada
|
// Solo ofrece ayuda cuando la amenaza es elevada
|
||||||
@@ -3124,6 +3429,20 @@ void Game::updateHelper() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actualiza las variables de ayuda (time-based). De moment cap timer real
|
||||||
|
// dins helper_; clonem la lògica per consistència d'API.
|
||||||
|
void Game::updateHelper([[maybe_unused]] float dt_s) {
|
||||||
|
if (menace_current_ > 15) {
|
||||||
|
for (const auto *player : players_) {
|
||||||
|
helper_.need_coffee = player->getCoffees() == 0;
|
||||||
|
helper_.need_coffee_machine = !player->isPowerUp();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
helper_.need_coffee = false;
|
||||||
|
helper_.need_coffee_machine = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Comprueba si todos los jugadores han muerto
|
// Comprueba si todos los jugadores han muerto
|
||||||
auto Game::allPlayersAreDead() -> bool {
|
auto Game::allPlayersAreDead() -> bool {
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|||||||
+59
-31
@@ -38,6 +38,11 @@ class Game {
|
|||||||
void handleEvent(const SDL_Event *event); // Procesa un evento
|
void handleEvent(const SDL_Event *event); // Procesa un evento
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Branques de iterate() — separades per a reduir la complexitat cognitiva
|
||||||
|
void iteratePaused();
|
||||||
|
void iterateGameOver();
|
||||||
|
void iteratePlaying(float dt_s);
|
||||||
|
|
||||||
// Cantidad de elementos a escribir en los ficheros de datos
|
// Cantidad de elementos a escribir en los ficheros de datos
|
||||||
static constexpr int TOTAL_SCORE_DATA = 3;
|
static constexpr int TOTAL_SCORE_DATA = 3;
|
||||||
static constexpr int TOTAL_DEMO_DATA = 2000;
|
static constexpr int TOTAL_DEMO_DATA = 2000;
|
||||||
@@ -141,10 +146,11 @@ class Game {
|
|||||||
DemoKeys data_file[TOTAL_DEMO_DATA]; // Datos del fichero con los movimientos para la demo
|
DemoKeys data_file[TOTAL_DEMO_DATA]; // Datos del fichero con los movimientos para la demo
|
||||||
};
|
};
|
||||||
|
|
||||||
void update(); // Actualiza el juego
|
void update(); // Actualiza el juego (frame-based)
|
||||||
void render(); // Dibuja el juego
|
void update(float dt_s); // Actualiza el juego (time-based)
|
||||||
void init(); // Inicializa las variables necesarias para la sección 'Game'
|
void render(); // Dibuja el juego
|
||||||
void loadMedia(); // Carga los recursos necesarios para la sección 'Game'
|
void init(); // Inicializa las variables necesarias para la sección 'Game'
|
||||||
|
void loadMedia(); // Carga los recursos necesarios para la sección 'Game'
|
||||||
|
|
||||||
auto loadScoreFile() -> bool; // Carga el fichero de puntos
|
auto loadScoreFile() -> bool; // Carga el fichero de puntos
|
||||||
auto loadDemoFile() -> bool; // Carga el fichero de datos para la demo
|
auto loadDemoFile() -> bool; // Carga el fichero de datos para la demo
|
||||||
@@ -167,14 +173,18 @@ class Game {
|
|||||||
static auto updateScoreText(Uint32 num) -> std::string; // Transforma un valor numérico en una cadena de 6 cifras
|
static auto updateScoreText(Uint32 num) -> std::string; // Transforma un valor numérico en una cadena de 6 cifras
|
||||||
void renderScoreBoard(); // Pinta el marcador en pantalla usando un objeto texto
|
void renderScoreBoard(); // Pinta el marcador en pantalla usando un objeto texto
|
||||||
|
|
||||||
void updatePlayers(); // Actualiza las variables del jugador
|
void updatePlayers(); // Actualiza las variables del jugador (frame-based)
|
||||||
void renderPlayers(); // Dibuja a los jugadores
|
void updatePlayers(float dt_s); // Actualiza las variables del jugador (time-based)
|
||||||
|
void renderPlayers(); // Dibuja a los jugadores
|
||||||
|
|
||||||
void updateStage(); // Actualiza las variables de la fase
|
void updateStage(); // Actualiza las variables de la fase (frame-based)
|
||||||
void updateDeath(); // Actualiza el estado de muerte
|
void updateStage(float dt_s); // Actualiza las variables de la fase (time-based)
|
||||||
|
void updateDeath(); // Actualiza el estado de muerte (frame-based)
|
||||||
|
void updateDeath(float dt_s); // Actualiza el estado de muerte (time-based)
|
||||||
void renderDeathFade(int counter); // Renderiza el fade final cuando se acaba la partida
|
void renderDeathFade(int counter); // Renderiza el fade final cuando se acaba la partida
|
||||||
|
|
||||||
void updateBalloons(); // Actualiza los globos
|
void updateBalloons(); // Actualiza los globos (frame-based)
|
||||||
|
void updateBalloons(float dt_s); // Actualiza los globos (time-based)
|
||||||
void renderBalloons(); // Pinta en pantalla todos los globos activos
|
void renderBalloons(); // Pinta en pantalla todos los globos activos
|
||||||
auto createBalloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer) -> Uint8; // Crea un globo nuevo en el vector de globos
|
auto createBalloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer) -> Uint8; // Crea un globo nuevo en el vector de globos
|
||||||
void createPowerBall(); // Crea una PowerBall
|
void createPowerBall(); // Crea una PowerBall
|
||||||
@@ -193,12 +203,14 @@ class Game {
|
|||||||
void checkBulletBalloonCollision(); // Comprueba la colisión entre las balas y los globos
|
void checkBulletBalloonCollision(); // Comprueba la colisión entre las balas y los globos
|
||||||
void resolveBulletBalloonHit(Bullet *bullet, Balloon *balloon); // Resuelve un impacto bala-globo (helper de checkBulletBalloonCollision)
|
void resolveBulletBalloonHit(Bullet *bullet, Balloon *balloon); // Resuelve un impacto bala-globo (helper de checkBulletBalloonCollision)
|
||||||
|
|
||||||
void moveBullets(); // Mueve las balas activas
|
void moveBullets(); // Mueve las balas activas (frame-based)
|
||||||
|
void moveBullets(float dt_s); // Mueve las balas activas (time-based)
|
||||||
void renderBullets(); // Pinta las balas activas
|
void renderBullets(); // Pinta las balas activas
|
||||||
void createBullet(int x, int y, Bullet::Kind kind, bool powered_up, int owner); // Crea un objeto bala
|
void createBullet(int x, int y, Bullet::Kind kind, bool powered_up, int owner); // Crea un objeto bala
|
||||||
void freeBullets(); // Vacia el vector de balas
|
void freeBullets(); // Vacia el vector de balas
|
||||||
|
|
||||||
void updateItems(); // Actualiza los items
|
void updateItems(); // Actualiza los items (frame-based)
|
||||||
|
void updateItems(float dt_s); // Actualiza los items (time-based)
|
||||||
void renderItems(); // Pinta los items activos
|
void renderItems(); // Pinta los items activos
|
||||||
auto dropItem() -> Item::Id; // Devuelve un item en función del azar
|
auto dropItem() -> Item::Id; // Devuelve un item en función del azar
|
||||||
void createItem(Item::Id kind, float x, float y); // Crea un objeto item
|
void createItem(Item::Id kind, float x, float y); // Crea un objeto item
|
||||||
@@ -207,11 +219,13 @@ class Game {
|
|||||||
void createItemScoreSprite(int x, int y, const SmartSprite *sprite); // Crea un objeto SmartSprite
|
void createItemScoreSprite(int x, int y, const SmartSprite *sprite); // Crea un objeto SmartSprite
|
||||||
void freeSmartSprites(); // Vacia el vector de smartsprites
|
void freeSmartSprites(); // Vacia el vector de smartsprites
|
||||||
|
|
||||||
void renderFlashEffect(); // Dibuja el efecto de flash
|
void renderFlashEffect(); // Dibuja el efecto de flash
|
||||||
void updateShakeEffect(); // Actualiza el efecto de agitar la pantalla
|
void updateShakeEffect(); // Actualiza el efecto de agitar la pantalla (frame-based)
|
||||||
void throwCoffee(int x, int y); // Crea un SmartSprite para arrojar el item café al recibir un impacto
|
void updateShakeEffect(float dt_s); // Actualiza el efecto de agitar la pantalla (time-based)
|
||||||
void updateSmartSprites(); // Actualiza los SmartSprites
|
void throwCoffee(int x, int y); // Crea un SmartSprite para arrojar el item café al recibir un impacto
|
||||||
void renderSmartSprites(); // Pinta los SmartSprites activos
|
void updateSmartSprites(); // Actualiza los SmartSprites (frame-based)
|
||||||
|
void updateSmartSprites(float dt_s); // Actualiza los SmartSprites (time-based)
|
||||||
|
void renderSmartSprites(); // Pinta los SmartSprites activos
|
||||||
|
|
||||||
void killPlayer(Player *player); // Acciones a realizar cuando el jugador muere
|
void killPlayer(Player *player); // Acciones a realizar cuando el jugador muere
|
||||||
void evaluateAndSetMenace(); // Calcula y establece el valor de amenaza en funcion de los globos activos
|
void evaluateAndSetMenace(); // Calcula y establece el valor de amenaza en funcion de los globos activos
|
||||||
@@ -222,11 +236,14 @@ class Game {
|
|||||||
void setTimeStoppedCounter(Uint16 value); // Establece el valor de la variable
|
void setTimeStoppedCounter(Uint16 value); // Establece el valor de la variable
|
||||||
void incTimeStoppedCounter(Uint16 value); // Incrementa el valor de la variable
|
void incTimeStoppedCounter(Uint16 value); // Incrementa el valor de la variable
|
||||||
|
|
||||||
void updateEnemyDeployCounter(); // Actualiza la variable EnemyDeployCounter
|
void updateEnemyDeployCounter(); // Actualiza la variable EnemyDeployCounter (frame-based)
|
||||||
void updateTimeStoppedCounter(); // Actualiza y comprueba el valor de la variable
|
void updateEnemyDeployCounter(float dt_s); // Actualiza la variable EnemyDeployCounter (time-based)
|
||||||
void updateMenace(); // Gestiona el nivel de amenaza
|
void updateTimeStoppedCounter(); // Actualiza y comprueba el valor de la variable (frame-based)
|
||||||
void updateBackground(); // Actualiza el fondo
|
void updateTimeStoppedCounter(float dt_s); // Actualiza y comprueba el valor de la variable (time-based)
|
||||||
void renderBackground(); // Dibuja el fondo
|
void updateMenace(); // Gestiona el nivel de amenaza
|
||||||
|
void updateBackground(); // Actualiza el fondo (frame-based)
|
||||||
|
void updateBackground(float dt_s); // Actualiza el fondo (time-based)
|
||||||
|
void renderBackground(); // Dibuja el fondo
|
||||||
|
|
||||||
void checkGameInput(); // Gestiona la entrada durante el juego
|
void checkGameInput(); // Gestiona la entrada durante el juego
|
||||||
void processDemoInput(); // Helper de checkGameInput
|
void processDemoInput(); // Helper de checkGameInput
|
||||||
@@ -254,8 +271,10 @@ class Game {
|
|||||||
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 actual de los globos en pantalla
|
auto calculateScreenPower() -> int; // Calcula el poder actual de los globos en pantalla
|
||||||
void initPaths(); // Inicializa las variables que contienen puntos de ruta para mover objetos
|
void initPaths(); // Inicializa las variables que contienen puntos de ruta para mover objetos
|
||||||
void updateGameCompleted(); // Actualiza el tramo final de juego, una vez completado
|
void updateGameCompleted(); // Actualiza el tramo final de juego (frame-based)
|
||||||
void updateHelper(); // Actualiza las variables de ayuda
|
void updateGameCompleted(float dt_s); // Actualiza el tramo final de juego (time-based)
|
||||||
|
void updateHelper(); // Actualiza las variables de ayuda (frame-based)
|
||||||
|
void updateHelper(float dt_s); // Actualiza las variables de ayuda (time-based)
|
||||||
auto allPlayersAreDead() -> bool; // Comprueba si todos los jugadores han muerto
|
auto allPlayersAreDead() -> bool; // Comprueba si todos los jugadores han muerto
|
||||||
void deleteAllVectorObjects(); // Elimina todos los objetos contenidos en vectores
|
void deleteAllVectorObjects(); // Elimina todos los objetos contenidos en vectores
|
||||||
void setHiScore(); // Establece la máxima puntuación desde fichero o desde las puntuaciones online
|
void setHiScore(); // Establece la máxima puntuación desde fichero o desde las puntuaciones online
|
||||||
@@ -337,30 +356,38 @@ class Game {
|
|||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
int num_players_; // Numero de jugadores
|
int num_players_; // Numero de jugadores
|
||||||
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa (frame-based)
|
||||||
Uint8 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
|
Uint8 ticks_speed_; // Velocidad a la que se repiten los bucles del programa (frame-based)
|
||||||
|
float elapsed_s_{0.0F}; // Acumulador global de temps de joc (time-based)
|
||||||
Uint32 hi_score_; // Puntuación máxima
|
Uint32 hi_score_; // Puntuación máxima
|
||||||
bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima
|
bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima
|
||||||
std::string hi_score_name_; // Nombre del jugador que ostenta la máxima puntuación
|
std::string hi_score_name_; // Nombre del jugador que ostenta la máxima puntuación
|
||||||
Stage stage_[10]; // Variable con los datos de cada pantalla
|
Stage stage_[10]; // Variable con los datos de cada pantalla
|
||||||
Uint8 current_stage_; // Indica la fase actual
|
Uint8 current_stage_; // Indica la fase actual
|
||||||
Uint8 stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage
|
Uint8 stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage (frame-based)
|
||||||
|
float stage_bitmap_counter_s_{0.0F}; // Contador (time-based)
|
||||||
float stage_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
|
float stage_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
|
||||||
float get_ready_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
|
float get_ready_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
|
||||||
Uint16 death_counter_; // Contador para la animación de muerte del jugador
|
Uint16 death_counter_; // Contador para la animación de muerte del jugador (frame-based)
|
||||||
|
float death_counter_s_{0.0F}; // Contador (time-based)
|
||||||
Uint8 menace_current_; // Nivel de amenaza actual
|
Uint8 menace_current_; // Nivel de amenaza actual
|
||||||
Uint8 menace_threshold_; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el numero de globos
|
Uint8 menace_threshold_; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el numero de globos
|
||||||
bool time_stopped_; // Indica si el tiempo está detenido
|
bool time_stopped_; // Indica si el tiempo está detenido
|
||||||
Uint16 time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido
|
Uint16 time_stopped_counter_; // Temporizador (frame-based)
|
||||||
Uint32 counter_; // Contador para el juego
|
float time_stopped_counter_s_{0.0F}; // Temporizador (time-based)
|
||||||
|
Uint32 counter_; // Contador para el juego (frame-based, derivat de elapsed_s_*60 en time-based)
|
||||||
Uint32 score_data_file_[TOTAL_SCORE_DATA]; // Datos del fichero de puntos
|
Uint32 score_data_file_[TOTAL_SCORE_DATA]; // Datos del fichero de puntos
|
||||||
SDL_Rect sky_colors_rect_[4]; // Vector con las coordenadas de los 4 colores de cielo
|
SDL_Rect sky_colors_rect_[4]; // Vector con las coordenadas de los 4 colores de cielo
|
||||||
Uint16 balloons_popped_; // Lleva la cuenta de los globos explotados
|
Uint16 balloons_popped_; // Lleva la cuenta de los globos explotados
|
||||||
Uint8 last_enemy_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
|
Uint8 last_enemy_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
|
||||||
int enemy_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
|
int enemy_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero (frame-based)
|
||||||
|
float enemy_deploy_counter_s_{0.0F}; // Comptador (time-based)
|
||||||
float enemy_speed_; // Velocidad a la que se mueven los enemigos
|
float enemy_speed_; // Velocidad a la que se mueven los enemigos
|
||||||
float default_enemy_speed_; // Velocidad base de los enemigos, sin incrementar
|
float default_enemy_speed_; // Velocidad base de los enemigos, sin incrementar
|
||||||
Effect effect_; // Variable para gestionar los efectos visuales
|
Effect effect_; // Variable para gestionar los efectos visuales
|
||||||
|
float shake_phase_s_{0.0F}; // Acumulador per decrementar shake_counter a 60Hz (time-based)
|
||||||
|
float helper_counter_s_{0.0F}; // Acumulador per al comptador helper_.counter (time-based)
|
||||||
|
float enemy_deploy_phase_s_{0.0F}; // Acumulador per al decrement de enemy_deploy_counter_ (time-based)
|
||||||
DeathShake death_shake_; // Variable para gestionar el efecto de agitación intensa
|
DeathShake death_shake_; // Variable para gestionar el efecto de agitación intensa
|
||||||
DeathSequence death_sequence_; // Variable para gestionar la secuencia de muerte
|
DeathSequence death_sequence_; // Variable para gestionar la secuencia de muerte
|
||||||
Helper helper_; // Variable para gestionar las ayudas
|
Helper helper_; // Variable para gestionar las ayudas
|
||||||
@@ -368,7 +395,8 @@ class Game {
|
|||||||
Uint8 power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
|
Uint8 power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
|
||||||
bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego
|
bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego
|
||||||
bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
|
bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
|
||||||
int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
|
int game_completed_counter_; // Contador per al tram final (frame-based)
|
||||||
|
float game_completed_counter_s_{0.0F}; // Comptador (time-based)
|
||||||
Uint8 difficulty_; // Dificultad del juego
|
Uint8 difficulty_; // Dificultad del juego
|
||||||
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
|
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
|
||||||
Color difficulty_color_; // Color asociado a la dificultad
|
Color difficulty_color_; // Color asociado a la dificultad
|
||||||
|
|||||||
Reference in New Issue
Block a user