diff --git a/source/balloon.cpp b/source/balloon.cpp index c54d350..28e8444 100644 --- a/source/balloon.cpp +++ b/source/balloon.cpp @@ -200,17 +200,11 @@ void Balloon::move() } } -// Deshabilita el globo y pone a cero todos los valores -void Balloon::disable() -{ - enabled_ = false; -} +// Deshabilita el globo +void Balloon::disable() { enabled_ = false; } // Explosiona el globo -void Balloon::pop() -{ - disable(); -} +void Balloon::pop() { disable(); } // Actualiza al globo a su posicion, animación y controla los contadores void Balloon::update() @@ -296,60 +290,6 @@ void Balloon::setAnimation() sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation); } -// Comprueba si el globo está habilitado -bool Balloon::isEnabled() const -{ - return enabled_; -} - -// Obtiene del valor de la variable -float Balloon::getPosX() const -{ - return x_; -} - -// Obtiene del valor de la variable -float Balloon::getPosY() const -{ - return y_; -} - -// Obtiene del valor de la variable -int Balloon::getWidth() const -{ - return w_; -} - -// Obtiene del valor de la variable -int Balloon::getHeight() const -{ - return h_; -} - -// Establece el valor de la variable -void Balloon::setVelY(float vel_y) -{ - vy_ = vel_y; -} - -// Establece el valor de la variable -void Balloon::setSpeed(float speed) -{ - speed_ = speed; -} - -// Obtiene el tamaño del globo -BalloonSize Balloon::getSize() const -{ - return size_; -} - -// Obtiene el tipo de globo -BalloonType Balloon::getType() const -{ - return type_; -} - // Detiene el globo void Balloon::stop() { @@ -366,42 +306,6 @@ void Balloon::start() sprite_->enableRotate(); } -// Obtiene del valor de la variable -bool Balloon::isStopped() const -{ - return stopped_; -} - -// Establece el valor de la variable -void Balloon::setInvulnerable(bool value) -{ - invulnerable_ = value; -} - -// Obtiene del valor de la variable -bool Balloon::isInvulnerable() const -{ - return invulnerable_; -} - -// Obtiene del valor de la variable -bool Balloon::isBeingCreated() const -{ - return being_created_; -} - -// Obtiene del valor de la variable -Uint16 Balloon::getScore() const -{ - return score_; -} - -// Obtiene el circulo de colisión -Circle &Balloon::getCollider() -{ - return collider_; -} - // Alinea el circulo de colisión con la posición del objeto globo void Balloon::shiftColliders() { @@ -423,18 +327,6 @@ void Balloon::zoomSprite() sprite_->setZoomH(bouncing_.zoomH); } -// Obtiene le valor de la variable -Uint8 Balloon::getMenace() const -{ - return isEnabled() ? menace_ : 0; -} - -// Obtiene le valor de la variable -Uint8 Balloon::getPower() const -{ - return power_; -} - // Activa el efecto void Balloon::enableBounce() { @@ -471,18 +363,6 @@ void Balloon::updateBounce() } } -// Indica si el globo se puede explotar -bool Balloon::canBePopped() const -{ - return isEnabled() && !isBeingCreated(); -} - -// Indica si el globo se puede destruir -bool Balloon::canBeDestroyed() const -{ - return isEnabled(); -} - // Pone el color alternativo en el globo void Balloon::useReverseColor() { @@ -500,8 +380,25 @@ void Balloon::useNormalColor() setAnimation(); } -// Indica si está usando el color alternativo -bool Balloon::isUsingReversedColor() -{ - return use_reversed_colors_; -} \ No newline at end of file +// Getters +float Balloon::getPosX() const { return x_; } +float Balloon::getPosY() const { return y_; } +int Balloon::getWidth() const { return w_; } +int Balloon::getHeight() const { return h_; } +BalloonSize Balloon::getSize() const { return size_; } +BalloonType Balloon::getType() const { return type_; } +Uint16 Balloon::getScore() const { return score_; } +Circle &Balloon::getCollider() { return collider_; } +Uint8 Balloon::getMenace() const { return isEnabled() ? menace_ : 0; } +Uint8 Balloon::getPower() const { return power_; } +bool Balloon::isStopped() const { return stopped_; } +bool Balloon::isInvulnerable() const { return invulnerable_; } +bool Balloon::isBeingCreated() const { return being_created_; } +bool Balloon::isEnabled() const { return enabled_; } +bool Balloon::isUsingReversedColor() { return use_reversed_colors_; } +bool Balloon::canBePopped() const { return !isBeingCreated(); } + +// Setters +void Balloon::setVelY(float vel_y) { vy_ = vel_y; } +void Balloon::setSpeed(float speed) { speed_ = speed; } +void Balloon::setInvulnerable(bool value) { invulnerable_ = value; } \ No newline at end of file diff --git a/source/balloon.h b/source/balloon.h index c39c042..04d9806 100644 --- a/source/balloon.h +++ b/source/balloon.h @@ -161,75 +161,38 @@ public: // Actualiza al globo a su posicion, animación y controla los contadores void update(); - // Comprueba si el globo está habilitado - bool isEnabled() const; - - // Obtiene del valor de la variable - float getPosX() const; - - // Obtiene del valor de la variable - float getPosY() const; - - // Obtiene del valor de la variable - int getWidth() const; - - // Obtiene del valor de la variable - int getHeight() const; - - // Establece el valor de la variable - void setVelY(float vel_y); - - // Establece el valor de la variable - void setSpeed(float speed); - - // Obtiene el tamaño del globo - BalloonSize getSize() const; - - // Obtiene el tipo de globo - BalloonType getType() const; - // Detiene el globo void stop(); // Pone el globo en movimiento void start(); - // Obtiene del valor de la variable - bool isStopped() const; - - // Establece el valor de la variable - void setInvulnerable(bool value); - - // Obtiene del valor de la variable - bool isInvulnerable() const; - - // Obtiene del valor de la variable - bool isBeingCreated() const; - - // Obtiene del valor de la variable - Uint16 getScore() const; - - // Obtiene el circulo de colisión - Circle &getCollider(); - - // Obtiene le valor de la variable - Uint8 getMenace() const; - - // Obtiene le valor de la variable - Uint8 getPower() const; - - // Indica si el globo se puede explotar - bool canBePopped() const; - - // Indica si el globo se puede destruir - bool canBeDestroyed() const; - // Pone el color alternativo en el globo void useReverseColor(); // Pone el color normal en el globo void useNormalColor(); - // Indica si está usando el color alternativo + // Getters + float getPosX() const; + float getPosY() const; + int getWidth() const; + int getHeight() const; + BalloonSize getSize() const; + BalloonType getType() const; + Uint16 getScore() const; + Circle &getCollider(); + Uint8 getMenace() const; + Uint8 getPower() const; + bool isStopped() const; + bool isInvulnerable() const; + bool isBeingCreated() const; + bool isEnabled() const; bool isUsingReversedColor(); + bool canBePopped() const; + + // Setters + void setVelY(float vel_y); + void setSpeed(float speed); + void setInvulnerable(bool value); }; \ No newline at end of file diff --git a/source/director.cpp b/source/director.cpp index b0a5266..d321be3 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -95,13 +95,9 @@ Director::Director(int argc, const char *argv[]) { auto manager = std::make_unique(options.game.hi_score_table); if (overrides.clear_hi_score_table) - { manager->clear(); - } else - { manager->loadFromFile(Asset::get()->get("score.bin")); - } } // Inicializa SDL @@ -629,7 +625,11 @@ void Director::runTitle() void Director::runGame() { const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2; +#ifdef DEBUG + constexpr auto current_stage = 9; +#else constexpr auto current_stage = 0; +#endif auto game = std::make_unique(player_id, current_stage, GAME_MODE_DEMO_OFF); game->run(); } diff --git a/source/game.cpp b/source/game.cpp index 1c33fa3..7320a3f 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -1,15 +1,4 @@ #include "game.h" -#include // for SDL_BLENDMODE_BLEND -#include // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN -#include // for SDLK_1, SDLK_2, SDLK_3, SDLK_4 -#include // for SDL_PIXELFORMAT_RGBA8888 -#include // for SDL_GetTicks -#include // for SDL_WINDOWEVENT_FOCUS_GAINED, SDL_... -#include // for rand, size_t -#include // for find_if, clamp, min, remove_if -#include // for function -#include // for distance, size -#include // for accumulate #include "asset.h" // for Asset #include "background.h" // for Background #include "balloon.h" // for Balloon, BALLOON_SCORE, BALLOON_VE... @@ -34,7 +23,19 @@ #include "smart_sprite.h" // for SmartSprite #include "text.h" // for Text #include "texture.h" // for Texture -struct JA_Sound_t; // lines 36-36 +#include // for SDL_BLENDMODE_BLEND +#include // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN +#include // for SDLK_1, SDLK_2, SDLK_3, SDLK_4 +#include // for SDL_PIXELFORMAT_RGBA8888 +#include // for SDL_GetTicks +#include // for SDL_WINDOWEVENT_FOCUS_GAINED, SDL_... +#include // for find_if, clamp, min, remove_if +#include // for function +#include // for distance, size +#include // for accumulate +#include // for rand, size_t + +struct JA_Sound_t; // lines 36-36 // Constructor Game::Game(int player_id, int current_stage, bool demo) @@ -84,7 +85,7 @@ Game::Game(int player_id, int current_stage, bool demo) initPaths(); setTotalPower(); - // Crea los primeros globos + // Crea los primeros globos y el mensaje de inicio if (!demo_.enabled) { createTwoBigBalloons(); @@ -210,7 +211,6 @@ void Game::deployBalloonFormation() // Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última if (balloon_deploy_counter_ == 0) { - // En este punto se decide entre crear una powerball o una formación enemiga if ((rand() % 100 < 15) && (canPowerBallBeCreated())) { @@ -250,10 +250,7 @@ void Game::deployBalloonFormation() } // Aumenta el poder de la fase -void Game::increaseStageCurrentPower(int power) -{ - current_power_ += power; -} +void Game::increaseStageCurrentPower(int power) { current_power_ += power; } // Actualiza el valor de hiScore en caso necesario void Game::updateHiScore() @@ -328,34 +325,40 @@ void Game::updateStage() // Cambio de fase ++current_stage_; current_power_ = 0; - - // Ha llegado al final el juego - if (current_stage_ == 10) - { - game_completed_ = true; // Marca el juego como completado - current_stage_ = 9; // Deja el valor dentro de los limites - destroyAllBalloons(); // Destruye a todos los enemigos - current_power_ = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos lo globos - menace_current_ = 255; // Sube el nivel de amenaza para que no cree mas globos - - // Añade un millon de puntos a los jugadores que queden vivos - for (auto &player : players_) - if (player->isPlaying()) - player->addScore(1000000); - - updateHiScore(); - JA_StopMusic(); - } JA_PlaySound(Resource::get()->getSound("stage_change.wav")); balloon_speed_ = default_balloon_speed_; setBalloonSpeed(balloon_speed_); screen_->flash(flash_color, 100); screen_->shake(); - // Escribe el texto por pantalla - const auto stage_number = balloon_formations_->getStage(current_stage_).number; - if (!game_completed_) + // Ha llegado al final el juego + if (status_ == GameStatus::PLAYING && current_stage_ == 10) { + status_ = GameStatus::COMPLETED; + stopMusic(); + current_stage_ = 9; // Deja el valor dentro de los limites + destroyAllBalloons(); // Destruye a todos los globos + destroyAllItems(); // Destruye todos los items + current_power_ = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos los globos + + for (auto &player : players_) + if (player->isPlaying()) + { + player->addScore(1000000); + player->setStatusPlaying(player->IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME_GAME_COMPLETED : PlayerStatus::GAME_COMPLETED); + } + else + { + player->setStatusPlaying(PlayerStatus::GAME_OVER); + } + + updateHiScore(); + } + + // Escribe el texto por pantalla + if (status_ == GameStatus::PLAYING) + { + const auto stage_number = balloon_formations_->getStage(current_stage_).number; std::vector paths = {paths_.at(2), paths_.at(3)}; if (stage_number == 10) createMessage(paths, Resource::get()->getTexture("last_stage")); @@ -377,8 +380,8 @@ void Game::updateStage() // Actualiza el estado de fin de la partida void Game::updateGameOver() { - // Si todos estan en estado de Game Over - if (allPlayersAreGameOver()) + // Si todos estan en estado de Game Over y no hay mensajes por pantalla + if (allPlayersAreGameOver() && path_sprites_.empty()) { if (game_over_counter_ > 0) { @@ -391,11 +394,7 @@ void Game::updateGameOver() { // Hace sonar aleatoriamente uno de los 4 sonidos de burbujas const auto index = rand() % 4; - JA_Sound_t *sound[4] = { - Resource::get()->getSound("bubble1.wav"), - Resource::get()->getSound("bubble2.wav"), - Resource::get()->getSound("bubble3.wav"), - Resource::get()->getSound("bubble4.wav")}; + JA_Sound_t *sound[4] = {Resource::get()->getSound("bubble1.wav"), Resource::get()->getSound("bubble2.wav"), Resource::get()->getSound("bubble3.wav"), Resource::get()->getSound("bubble4.wav")}; JA_PlaySound(sound[index], 0); } @@ -416,18 +415,14 @@ void Game::updateGameOver() void Game::updateBalloons() { for (auto balloon : balloons_) - { balloon->update(); - } } // Pinta en pantalla todos los globos activos void Game::renderBalloons() { for (auto &balloon : balloons_) - { balloon->render(); - } } // Crea un globo nuevo en el vector de globos @@ -477,29 +472,25 @@ void Game::createPowerBall() void Game::setBalloonSpeed(float speed) { for (auto &balloon : balloons_) - { - if (balloon->isEnabled()) - { - balloon->setSpeed(speed); - } - } + balloon->setSpeed(speed); } // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase -void Game::updateBalloonSpeed() +void Game::checkAndUpdateBalloonSpeed() { + if (difficulty_ != GameDifficulty::NORMAL) + return; + const float percent = static_cast(current_power_) / balloon_formations_->getStage(current_stage_).power_to_complete; const float thresholds[] = {0.2f, 0.4f, 0.6f, 0.8f}; for (size_t i = 0; i < std::size(thresholds); ++i) - { if (balloon_speed_ == BALLOON_SPEED[i] && percent > thresholds[i]) { balloon_speed_ = BALLOON_SPEED[i + 1]; setBalloonSpeed(balloon_speed_); break; // Salir del bucle una vez actualizada la velocidad y aplicada } - } } // Explosiona un globo. Lo destruye y crea otros dos si es el caso @@ -575,8 +566,7 @@ void Game::destroyBalloon(std::shared_ptr &balloon) void Game::destroyAllBalloons() { for (auto &balloon : balloons_) - if (balloon->canBeDestroyed()) - destroyBalloon(balloon); + destroyBalloon(balloon); balloon_deploy_counter_ = 300; JA_PlaySound(Resource::get()->getSound("powerball.wav")); @@ -584,6 +574,13 @@ void Game::destroyAllBalloons() screen_->shake(); } +// Destruye todos los items +void Game::destroyAllItems() +{ + for (auto &item : items_) + item->disable(); +} + // Detiene todos los globos void Game::stopAllBalloons() { @@ -617,8 +614,7 @@ void Game::normalColorsToAllBalloons() // Vacia del vector de globos los globos que ya no sirven void Game::freeBalloons() { - auto it = std::remove_if(balloons_.begin(), balloons_.end(), - [](const auto &balloon) + auto it = std::remove_if(balloons_.begin(), balloons_.end(), [](const auto &balloon) { return !balloon->isEnabled(); }); balloons_.erase(it, balloons_.end()); } @@ -627,7 +623,7 @@ void Game::freeBalloons() bool Game::checkPlayerBalloonCollision(std::shared_ptr &player) { for (auto &balloon : balloons_) - if ((balloon->isEnabled()) && !(balloon->isStopped()) && !(balloon->isInvulnerable())) + if (!balloon->isStopped() && !balloon->isInvulnerable()) if (checkCollision(player->getCollider(), balloon->getCollider())) return true; @@ -651,28 +647,36 @@ void Game::checkPlayerItemCollision(std::shared_ptr &player) case ItemType::DISK: { player->addScore(1000); - const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[0]->getWidth()) / 2; + const auto x = + item->getPosX() + + (item->getWidth() - game_text_textures_[0]->getWidth()) / 2; createItemText(x, game_text_textures_[0]); break; } case ItemType::GAVINA: { player->addScore(2500); - const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[1]->getWidth()) / 2; + const auto x = + item->getPosX() + + (item->getWidth() - game_text_textures_[1]->getWidth()) / 2; createItemText(x, game_text_textures_[1]); break; } case ItemType::PACMAR: { player->addScore(5000); - const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[2]->getWidth()) / 2; + const auto x = + item->getPosX() + + (item->getWidth() - game_text_textures_[2]->getWidth()) / 2; createItemText(x, game_text_textures_[2]); break; } case ItemType::CLOCK: { enableTimeStopItem(); - const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[5]->getWidth()) / 2; + const auto x = + item->getPosX() + + (item->getWidth() - game_text_textures_[5]->getWidth()) / 2; createItemText(x, game_text_textures_[5]); break; } @@ -681,13 +685,17 @@ void Game::checkPlayerItemCollision(std::shared_ptr &player) if (player->getCoffees() == 2) { player->addScore(5000); - const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[2]->getWidth()) / 2; + const auto x = + item->getPosX() + + (item->getWidth() - game_text_textures_[2]->getWidth()) / 2; createItemText(x, game_text_textures_[2]); } else { player->giveExtraHit(); - const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[4]->getWidth()) / 2; + const auto x = + item->getPosX() + + (item->getWidth() - game_text_textures_[4]->getWidth()) / 2; createItemText(x, game_text_textures_[4]); } break; @@ -696,7 +704,9 @@ void Game::checkPlayerItemCollision(std::shared_ptr &player) { player->setPowerUp(); coffee_machine_enabled_ = false; - const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[3]->getWidth()) / 2; + const auto x = + item->getPosX() + + (item->getWidth() - game_text_textures_[3]->getWidth()) / 2; createItemText(x, game_text_textures_[3]); break; } @@ -723,7 +733,7 @@ void Game::checkBulletBalloonCollision() { if (checkCollision(balloon->getCollider(), bullet->getCollider())) { - // Otorga los puntos correspondientes al globo al jugador que disparó la bala + // Otorga los puntos al jugador que disparó la bala auto player = getPlayer(bullet->getOwner()); if (!player) { @@ -783,7 +793,8 @@ void Game::renderBullets() // Crea un objeto bala void Game::createBullet(int x, int y, BulletType kind, bool powered_up, int owner) { - bullets_.emplace_back(std::make_unique(x, y, kind, powered_up, owner, bullet_texture_)); + bullets_.emplace_back( + std::make_unique(x, y, kind, powered_up, owner, bullet_texture_)); } // Vacia el vector de balas @@ -1033,8 +1044,9 @@ void Game::killPlayer(std::shared_ptr &player) // Calcula y establece el valor de amenaza en funcion de los globos activos void Game::evaluateAndSetMenace() { - menace_current_ = std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) - { return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); }); + menace_current_ = std::accumulate( + balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) + { return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); }); } // Actualiza y comprueba el valor de la variable @@ -1076,131 +1088,19 @@ void Game::update() if (SDL_GetTicks() - ticks_ > TICKS_SPEED) { - // Actualiza el contador de ticks ticks_ = SDL_GetTicks(); - - // Actualiza el contador de juego counter_++; - if (demo_.enabled) - { - // Incrementa el contador de la demo - if (demo_.counter < TOTAL_DEMO_DATA) - demo_.counter++; - - // Activa el fundido antes de acabar con los datos de la demo - if (demo_.counter == TOTAL_DEMO_DATA - 200) - { - fade_->setType(FadeType::RANDOM_SQUARE); - fade_->activate(); - } - - // Si ha terminado el fundido, cambia de sección - if (fade_->hasEnded()) - { - section::name = section::Name::HI_SCORE_TABLE; - return; - } - } + updateDemo(); #ifdef RECORDING - // Solo mira y guarda el input en cada update - checkInput(); - - // Incrementa el contador de la demo - if (demo_.counter < TOTAL_DEMO_DATA) - demo_.counter++; - - // Si se ha llenado el vector con datos, sale del programa - else - { - section::name = section::Name::QUIT; - return; - } + updateRecording(); #endif -#ifdef DEBUG - if (auto_pop_balloons_ && !game_completed_) - { - balloons_popped_++; - increaseStageCurrentPower(1); - } -#endif - if (!paused_) - { - // Actualiza el objeto fade - fade_->update(); + updateNormalGame(); + updateCompletedGame(); - // Actualiza las variables del jugador - updatePlayers(); - - // Actualiza el marcador - checkPlayersStatusPlaying(); - updateScoreboard(); - - // Actualiza el fondo - updateBackground(); - - // Mueve los globos - updateBalloons(); - - // Actualiza el objeto encargado de las explosiones - explosions_->update(); - - // Mueve las balas - moveBullets(); - - // Actualiza los items - updateItems(); - - // Comprueba si hay cambio de fase y actualiza las variables - updateStage(); - - // Actualiza el estado de muerte - updateGameOver(); - - // Actualiza los SpriteSmarts - updateSmartSprites(); - - // Actualiza los PathSmarts - updatePathSprites(); - - // Actualiza los contadores de estado y efectos - updateTimeStopped(); - updateBalloonDeployCounter(); - - // Actualiza el ayudante - updateHelper(); - - // Comprueba las colisiones entre globos y balas - checkBulletBalloonCollision(); - - // Comprueba el nivel de amenaza para ver si se han de crear nuevos enemigos - updateMenace(); - - // Actualiza la velocidad de los enemigos - if (difficulty_ == GameDifficulty::NORMAL) - { - updateBalloonSpeed(); - } - - // Actualiza el tramo final de juego, una vez completado - updateGameCompleted(); - - // Vacia los vectores - freeBullets(); - freeBalloons(); - freeItems(); - freeSmartSprites(); - freePathSprites(); - } - - // Comprueba si la música ha de estar sonando checkMusicStatus(); - - // Actualiza el objeto screen screen_->update(); - - // Dibuja los graficos de la zona de juego en la textura fillCanvas(); } } @@ -1209,7 +1109,7 @@ void Game::update() void Game::updateBackground() { // Si el juego está completado, se reduce la velocidad de las nubes - if (game_completed_) + if (status_ == GameStatus::COMPLETED) balloons_popped_ = (balloons_popped_ > 400) ? (balloons_popped_ - 25) : 200; // Calcula la velocidad en función de los globos explotados y el total de globos a explotar para acabar el juego @@ -1271,9 +1171,6 @@ void Game::render() // Gestiona el nivel de amenaza void Game::updateMenace() { - if (game_completed_) - return; - const auto stage = balloon_formations_->getStage(current_stage_); const float percent = current_power_ / stage.power_to_complete; const int difference = stage.max_menace - stage.min_menace; @@ -1312,9 +1209,10 @@ void Game::disableTimeStopItem() void Game::checkMusicStatus() { // Si la música no está sonando - if (JA_GetMusicState() == JA_MUSIC_INVALID || JA_GetMusicState() == JA_MUSIC_STOPPED) + if (JA_GetMusicState() == JA_MUSIC_INVALID || + JA_GetMusicState() == JA_MUSIC_STOPPED) // Si se ha completado el juego o los jugadores han terminado, detiene la música - game_completed_ || allPlayersAreGameOver() ? JA_StopMusic() : JA_PlayMusic(Resource::get()->getMusic("playing.ogg")); + status_ == GameStatus::COMPLETED || allPlayersAreGameOver() ? JA_StopMusic() : JA_PlayMusic(Resource::get()->getMusic("playing.ogg")); } // Bucle para el juego @@ -1335,10 +1233,7 @@ void Game::run() } // Indica si se puede crear una powerball -bool Game::canPowerBallBeCreated() -{ - return (!power_ball_enabled_) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); -} +bool Game::canPowerBallBeCreated() { return (!power_ball_enabled_) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); } // Calcula el poder actual de los globos en pantalla int Game::calculateScreenPower() @@ -1362,7 +1257,8 @@ void Game::initPaths() paths_.emplace_back(Path(createPath(x1, x2, PathType::HORIZONTAL, y, 80, easeInQuint), 0)); } - // Recorrido para el texto de "Last Stage!" o de "X stages left" o "Game Over" (2,3) + // Recorrido para el texto de "Last Stage!" o de "X stages left" o "Game Over" + // (2,3) { const auto &texture = Resource::get()->getTexture("last_stage"); const auto h = texture->getHeight(); @@ -1401,19 +1297,6 @@ void Game::initPaths() } } -// Actualiza el tramo final de juego, una vez completado -void Game::updateGameCompleted() -{ - if (game_completed_) - game_completed_counter_++; - - if (game_completed_counter_ == GAME_COMPLETED_END_) - { - section::name = section::Name::TITLE; - section::options = section::Options::TITLE_1; - } -} - // Actualiza las variables de ayuda void Game::updateHelper() { @@ -1547,6 +1430,10 @@ void Game::checkEvents() screen_->flash(flash_color, 100); break; } + case SDLK_8: + { + players_.at(0)->setStatusPlaying(PlayerStatus::GAME_COMPLETED); + } default: break; } @@ -1613,9 +1500,7 @@ void Game::addScoreToScoreBoard(const std::string &name, int score) // Saca del estado de GAME OVER al jugador si el otro está activo void Game::checkAndUpdatePlayerStatus(int activePlayerIndex, int inactivePlayerIndex) { - if (players_[activePlayerIndex]->isGameOver() && - !players_[inactivePlayerIndex]->isGameOver() && - !players_[inactivePlayerIndex]->isWaiting()) + if (players_[activePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isWaiting()) { players_[activePlayerIndex]->setStatusPlaying(PlayerStatus::WAITING); } @@ -1660,11 +1545,8 @@ std::shared_ptr Game::getPlayer(int id) // Obtiene un controlador a partir del "id" del jugador int Game::getController(int player_id) { - auto it = std::find_if(options.controller.begin(), options.controller.end(), - [player_id](const auto &controller) - { - return controller.player_id == player_id; - }); + auto it = std::find_if(options.controller.begin(), options.controller.end(), [player_id](const auto &controller) + { return controller.player_id == player_id; }); if (it != options.controller.end()) { @@ -1680,9 +1562,13 @@ void Game::checkInput() checkPauseInput(); // Verifica si se debe pausar el juego. if (demo_.enabled) - handleDemoMode(); // Controla el comportamiento de los jugadores en modo demo. + { // Controla el comportamiento de los jugadores en modo demo. + handleDemoMode(); + } else - handlePlayersInput(); // Gestiona el input normal de los jugadores. + { // Gestiona el input normal de los jugadores. + handlePlayersInput(); + } screen_->checkInput(); // Verifica el input en la pantalla del juego. globalInputs::check(); // Verifica los inputs globales. @@ -1710,17 +1596,20 @@ void Game::checkPauseInput() // Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos. void Game::handleDemoMode() { - int i = 0; + int index = 0; for (const auto &player : players_) { if (player->isPlaying()) - handleDemoPlayerInput(player, i); // Maneja el input específico del jugador en modo demo. + { // Maneja el input específico del jugador en modo demo. + handleDemoPlayerInput(player, index); + } + if (input_->checkAnyButtonPressed()) { section::name = section::Name::TITLE; // Salir del modo demo y regresar al menú principal. return; } - i++; + ++index; } } @@ -1730,18 +1619,30 @@ void Game::handleDemoPlayerInput(const std::shared_ptr &player, int inde const auto &demoData = demo_.data[index][demo_.counter]; if (demoData.left == 1) + { player->setInput(InputType::LEFT); + } else if (demoData.right == 1) + { player->setInput(InputType::RIGHT); + } else if (demoData.no_input == 1) + { player->setInput(InputType::NONE); + } if (demoData.fire == 1) + { handleFireInput(player, BulletType::UP); + } else if (demoData.fire_left == 1) + { handleFireInput(player, BulletType::LEFT); + } else if (demoData.fire_right == 1) + { handleFireInput(player, BulletType::RIGHT); + } } // Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos. @@ -1753,7 +1654,8 @@ void Game::handleFireInput(const std::shared_ptr &player, BulletType bul : InputType::FIRE_RIGHT); createBullet(player->getPosX() + (player->getWidth() / 2) - 6, player->getPosY() + (player->getHeight() / 2), bulletType, player->isPowerUp(), player->getId()); JA_PlaySound(Resource::get()->getSound("bullet.wav")); - player->setFireCooldown(10); // Establece un tiempo de espera para el próximo disparo. + // Establece un tiempo de espera para el próximo disparo. + player->setFireCooldown(10); } } @@ -1763,11 +1665,17 @@ void Game::handlePlayersInput() for (const auto &player : players_) { if (player->isPlaying()) - handleNormalPlayerInput(player); // Maneja el input de los jugadores en modo normal. + { // Maneja el input de los jugadores en modo normal. + handleNormalPlayerInput(player); + } else if (player->isContinue() || player->isWaiting()) - handlePlayerContinue(player); // Gestiona la continuación del jugador. - else if (player->isEnteringName()) - handleNameInput(player); // Gestiona la introducción del nombre del jugador. + { // Gestiona la continuación del jugador. + handlePlayerContinue(player); + } + else if (player->isEnteringName() || player->isEnteringNameGameCompleted()) + { // Gestiona la introducción del nombre del jugador. + handleNameInput(player); + } } } @@ -1802,24 +1710,32 @@ void Game::handleNormalPlayerInput(const std::shared_ptr &player) handleFireInputs(player, autofire, controllerIndex); // Verifica y maneja todas las posibles entradas de disparo. } -// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado. -void Game::handleFireInputs(const std::shared_ptr &player, bool autofire, int controllerIndex) +// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos +// si está habilitado. +void Game::handleFireInputs(const std::shared_ptr &player, + bool autofire, int controllerIndex) { - if (input_->checkInput(InputType::FIRE_CENTER, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) + if (input_->checkInput(InputType::FIRE_CENTER, autofire, + options.controller[controllerIndex].device_type, + options.controller[controllerIndex].index)) { handleFireInput(player, BulletType::UP); #ifdef RECORDING demo_.keys.fire = 1; #endif } - else if (input_->checkInput(InputType::FIRE_LEFT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) + else if (input_->checkInput(InputType::FIRE_LEFT, autofire, + options.controller[controllerIndex].device_type, + options.controller[controllerIndex].index)) { handleFireInput(player, BulletType::LEFT); #ifdef RECORDING demo_.keys.fire_left = 1; #endif } - else if (input_->checkInput(InputType::FIRE_RIGHT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) + else if (input_->checkInput(InputType::FIRE_RIGHT, autofire, + options.controller[controllerIndex].device_type, + options.controller[controllerIndex].index)) { handleFireInput(player, BulletType::RIGHT); #ifdef RECORDING @@ -1828,19 +1744,29 @@ void Game::handleFireInputs(const std::shared_ptr &player, bool autofire } } -// Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio. +// Maneja la continuación del jugador cuando no está jugando, permitiendo que +// continúe si se pulsa el botón de inicio. void Game::handlePlayerContinue(const std::shared_ptr &player) { const auto controllerIndex = player->getController(); - if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) + if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, + options.controller[controllerIndex].device_type, + options.controller[controllerIndex].index)) { player->setStatusPlaying(PlayerStatus::PLAYING); } - // Disminuye el contador de continuación si se presiona cualquier botón de disparo. - if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || - input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || - input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) + // Disminuye el contador de continuación si se presiona cualquier botón de + // disparo. + if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, + options.controller[controllerIndex].device_type, + options.controller[controllerIndex].index) || + input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, + options.controller[controllerIndex].device_type, + options.controller[controllerIndex].index) || + input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, + options.controller[controllerIndex].device_type, + options.controller[controllerIndex].index)) { player->decContinueCounter(); } @@ -1858,7 +1784,8 @@ void Game::handleNameInput(const std::shared_ptr &player) { player->setInput(InputType::START); addScoreToScoreBoard(player->getRecordName(), player->getScore()); - player->setStatusPlaying(PlayerStatus::CONTINUE); + const auto status = player->getStatusPlaying(); + player->setStatusPlaying(status == PlayerStatus::ENTERING_NAME ? PlayerStatus::CONTINUE : PlayerStatus::GAME_COMPLETED); } else { @@ -1877,15 +1804,18 @@ void Game::handleNameInput(const std::shared_ptr &player) { player->setInput(InputType::LEFT); } + /* else if (input_->checkInput(InputType::RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) { player->setInput(InputType::RIGHT); } + */ else if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) { player->setInput(InputType::START); addScoreToScoreBoard(player->getRecordName(), player->getScore()); - player->setStatusPlaying(PlayerStatus::CONTINUE); + const auto status = player->getStatusPlaying(); + player->setStatusPlaying(status == PlayerStatus::ENTERING_NAME ? PlayerStatus::CONTINUE : PlayerStatus::GAME_COMPLETED); } } @@ -1908,7 +1838,8 @@ void Game::initDemo(int player_id) current_stage_ = stages[demo]; } - // Actualiza el numero de globos explotados según la fase del modo demostración + // Actualiza el numero de globos explotados según la fase del modo + // demostración for (int i = 0; i < current_stage_; ++i) { balloons_popped_ += balloon_formations_->getStage(i).power_to_complete; @@ -1954,7 +1885,8 @@ void Game::setTotalPower() total_power_to_complete_game_ = 0; for (int i = 0; i < 10; ++i) { - total_power_to_complete_game_ += balloon_formations_->getStage(i).power_to_complete; + total_power_to_complete_game_ += + balloon_formations_->getStage(i).power_to_complete; } } @@ -2037,7 +1969,8 @@ void Game::createTwoBigBalloons() for (int i = 0; i < numEnemies; ++i) { auto p = set.init[i]; - createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter); + createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, + p.creation_counter); } } @@ -2060,4 +1993,114 @@ void Game::stopMusic() { if (!demo_.enabled) JA_StopMusic(); +} + +// Actualiza las variables durante el modo demo +void Game::updateDemo() +{ + if (demo_.enabled) + { + // Incrementa el contador de la demo + if (demo_.counter < TOTAL_DEMO_DATA) + demo_.counter++; + + // Activa el fundido antes de acabar con los datos de la demo + if (demo_.counter == TOTAL_DEMO_DATA - 200) + { + fade_->setType(FadeType::RANDOM_SQUARE); + fade_->activate(); + } + + // Si ha terminado el fundido, cambia de sección + if (fade_->hasEnded()) + { + section::name = section::Name::HI_SCORE_TABLE; + return; + } + } +} + +#ifdef RECORDING +// Actualiza las variables durante el modo de grabación +void Game::updateRecording() +{ + // Solo mira y guarda el input en cada update + checkInput(); + + // Incrementa el contador de la demo + if (demo_.counter < TOTAL_DEMO_DATA) + demo_.counter++; + + // Si se ha llenado el vector con datos, sale del programa + else + { + section::name = section::Name::QUIT; + return; + } +} +#endif + +// Actualiza las variables durante el transcurso normal del juego +void Game::updateNormalGame() +{ + if (status_ == GameStatus::PLAYING && !paused_) + { +#ifdef DEBUG + if (auto_pop_balloons_) + { + balloons_popped_++; + increaseStageCurrentPower(1); + } +#endif + fade_->update(); + updatePlayers(); + checkPlayersStatusPlaying(); + updateScoreboard(); + updateBackground(); + updateBalloons(); + explosions_->update(); + moveBullets(); + updateItems(); + updateStage(); + updateGameOver(); + updateSmartSprites(); + updatePathSprites(); + updateTimeStopped(); + updateBalloonDeployCounter(); + updateHelper(); + checkBulletBalloonCollision(); + updateMenace(); + checkAndUpdateBalloonSpeed(); + freeBullets(); + freeBalloons(); + freeItems(); + freeSmartSprites(); + freePathSprites(); + } +} + +// Actualiza las variables durante el transcurso normal del juego +void Game::updateCompletedGame() +{ + if (status_ == GameStatus::COMPLETED && !paused_) + { + fade_->update(); + updatePlayers(); + checkPlayersStatusPlaying(); + updateScoreboard(); + updateBackground(); + updateBalloons(); + explosions_->update(); + moveBullets(); + updateItems(); + updateGameOver(); + updateSmartSprites(); + updatePathSprites(); + checkBulletBalloonCollision(); + freeBullets(); + freeBalloons(); + freeItems(); + freeSmartSprites(); + freePathSprites(); + } } \ No newline at end of file diff --git a/source/game.h b/source/game.h index 108d006..dcac823 100644 --- a/source/game.h +++ b/source/game.h @@ -64,7 +64,12 @@ constexpr int TOTAL_SCORE_DATA = 3; class Game { private: - // Constantes + // Enum + enum class GameStatus + { + PLAYING, + COMPLETED, + }; // Contadores static constexpr int HELP_COUNTER_ = 1000; @@ -157,7 +162,6 @@ private: Helper helper_; // Variable para gestionar las ayudas Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego - bool game_completed_ = false; // Indica si se ha completado la partida, llegando al final de la ultima pantalla bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima bool paused_ = false; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade) bool power_ball_enabled_ = false; // Indica si hay una powerball ya activa @@ -176,6 +180,7 @@ private: int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases + GameStatus status_ = GameStatus::PLAYING; // Estado #ifdef DEBUG bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados #endif @@ -232,7 +237,7 @@ private: void setBalloonSpeed(float speed); // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase - void updateBalloonSpeed(); + void checkAndUpdateBalloonSpeed(); // Explosiona un globo. Lo destruye y crea otros dos si es el caso void popBalloon(std::shared_ptr balloon); @@ -243,6 +248,9 @@ private: // Destruye todos los globos void destroyAllBalloons(); + // Destruye todos los items + void destroyAllItems(); + // Detiene todos los globos void stopAllBalloons(); @@ -357,9 +365,6 @@ private: // Calcula el poder actual de los globos en pantalla int calculateScreenPower(); - // Actualiza el tramo final de juego, una vez completado - void updateGameCompleted(); - // Actualiza las variables de ayuda void updateHelper(); @@ -459,6 +464,18 @@ private: // Detiene la música void stopMusic(); + // Actualiza las variables durante el modo demo + void updateDemo(); +#ifdef RECORDING + // Actualiza las variables durante el modo de grabación + void updateRecording(); +#endif + // Actualiza las variables durante el transcurso normal del juego + void updateNormalGame(); + + // Actualiza las variables durante el transcurso del final del juego + void updateCompletedGame(); + public: // Constructor Game(int playerID, int current_stage, bool demo); diff --git a/source/player.cpp b/source/player.cpp index 6235882..ce3e829 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -61,8 +61,7 @@ void Player::init() // Establece la posición del sprite player_sprite_->clear(); - player_sprite_->setPosX(pos_x_); - player_sprite_->setPosY(pos_y_); + shiftSprite(); // Selecciona un frame para pintar player_sprite_->setCurrentAnimation("stand"); @@ -78,13 +77,16 @@ void Player::setInput(InputType input) setInputPlaying(input); break; } - case PlayerStatus::ENTERING_NAME: { setInputEnteringName(input); break; } - + case PlayerStatus::ENTERING_NAME_GAME_COMPLETED: + { + setInputEnteringName(input); + break; + } default: break; } @@ -101,32 +103,27 @@ void Player::setInputPlaying(InputType input) setWalkingStatus(PlayerStatus::WALKING_LEFT); break; } - case InputType::RIGHT: { vel_x_ = BASE_SPEED_; setWalkingStatus(PlayerStatus::WALKING_RIGHT); break; } - case InputType::FIRE_CENTER: { setFiringStatus(PlayerStatus::FIRING_UP); break; } - case InputType::FIRE_LEFT: { setFiringStatus(PlayerStatus::FIRING_LEFT); break; } - case InputType::FIRE_RIGHT: { setFiringStatus(PlayerStatus::FIRING_RIGHT); break; } - default: { vel_x_ = 0; @@ -144,23 +141,18 @@ void Player::setInputEnteringName(InputType input) case InputType::LEFT: enter_name_->decPosition(); break; - case InputType::RIGHT: enter_name_->incPosition(); break; - case InputType::UP: enter_name_->incIndex(); break; - case InputType::DOWN: enter_name_->decIndex(); break; - case InputType::START: setRecordName(enter_name_->getName()); break; - default: break; } @@ -170,7 +162,9 @@ void Player::setInputEnteringName(InputType input) // Mueve el jugador a la posición y animación que le corresponde void Player::move() { - if (isPlaying()) + switch (status_playing_) + { + case PlayerStatus::PLAYING: { // Mueve el jugador a derecha o izquierda pos_x_ += vel_x_; @@ -178,16 +172,12 @@ void Player::move() // Si el jugador abandona el area de juego por los laterales, restaura su posición const float min_x = param.game.play_area.rect.x - 5; const float max_x = play_area_.w + 5 - WIDTH_; - if ((pos_x_ < min_x) || (pos_x_ > max_x)) - pos_x_ = std::clamp(pos_x_, min_x, max_x); + pos_x_ = std::clamp(pos_x_, min_x, max_x); - // Actualiza la posición del sprite - player_sprite_->setPosX(pos_x_); - player_sprite_->setPosY(pos_y_); - - power_sprite_->setPosX(getPosX() - power_up_desp_x_); + shiftSprite(); + break; } - else if (isDying()) + case PlayerStatus::DYING: { // Si el cadaver abandona el area de juego por los laterales lo hace rebotar if ((player_sprite_->getPosX() < param.game.play_area.rect.x) || (player_sprite_->getPosX() + WIDTH_ > play_area_.w)) @@ -196,6 +186,33 @@ void Player::move() // Si el cadaver abandona el area de juego por abajo if (player_sprite_->getPosY() > param.game.play_area.rect.h) setStatusPlaying(PlayerStatus::DIED); + break; + } + case PlayerStatus::GAME_COMPLETED: + { + switch (id_) + { + case 1: + setInputPlaying(InputType::LEFT); + break; + case 2: + setInputPlaying(InputType::RIGHT); + break; + default: + break; + } + pos_x_ += vel_x_; + const float min_x = -WIDTH_; + const float max_x = play_area_.w; + pos_x_ = std::clamp(pos_x_, min_x, max_x); + shiftSprite(); + + if (pos_x_ == min_x || pos_x_ == max_x) + setStatusPlaying(PlayerStatus::GAME_OVER); + break; + } + default: + break; } } @@ -211,16 +228,10 @@ void Player::render() } // Establece el estado del jugador cuando camina -void Player::setWalkingStatus(PlayerStatus status) -{ - status_walking_ = status; -} +void Player::setWalkingStatus(PlayerStatus status) { status_walking_ = status; } // Establece el estado del jugador cuando dispara -void Player::setFiringStatus(PlayerStatus status) -{ - status_firing_ = status; -} +void Player::setFiringStatus(PlayerStatus status) { status_firing_ = status; } // Establece la animación correspondiente al estado void Player::setAnimation() @@ -233,7 +244,7 @@ void Player::setAnimation() const SDL_RendererFlip flip_fire = status_firing_ == PlayerStatus::FIRING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; // Establece la animación a partir de las cadenas - if (isPlaying()) + if (isPlaying() || isEnteringNameGameCompleted() || isGameCompleted()) { if (status_firing_ == PlayerStatus::FIRING_NONE) { // No esta disparando @@ -259,41 +270,22 @@ void Player::setAnimation() } // Obtiene el valor de la variable -int Player::getPosX() const -{ - return static_cast(pos_x_); -} +int Player::getPosX() const { return static_cast(pos_x_); } // Obtiene el valor de la variable -int Player::getPosY() const -{ - return pos_y_; -} +int Player::getPosY() const { return pos_y_; } // Obtiene el valor de la variable -int Player::getWidth() const -{ - return WIDTH_; -} +int Player::getWidth() const { return WIDTH_; } // Obtiene el valor de la variable -int Player::getHeight() const -{ - return HEIGHT_; -} +int Player::getHeight() const { return HEIGHT_; } // Indica si el jugador puede disparar -bool Player::canFire() const -{ - // Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador - return cooldown_ > 0 ? false : true; -} +bool Player::canFire() const { return cooldown_ > 0 ? false : true; } // Establece el valor de la variable -void Player::setFireCooldown(int time) -{ - cooldown_ = time; -} +void Player::setFireCooldown(int time) { cooldown_ = time; } // Actualiza el valor de la variable void Player::updateCooldown() @@ -327,16 +319,10 @@ void Player::update() } // Obtiene la puntuación del jugador -int Player::getScore() const -{ - return score_; -} +int Player::getScore() const { return score_; } // Asigna un valor a la puntuación del jugador -void Player::setScore(int score) -{ - score_ = score; -} +void Player::setScore(int score) { score_ = score; } // Incrementa la puntuación del jugador void Player::addScore(int score) @@ -348,66 +334,54 @@ void Player::addScore(int score) } // Indica si el jugador está jugando -bool Player::isPlaying() const -{ - return status_playing_ == PlayerStatus::PLAYING; -} +bool Player::isPlaying() const { return status_playing_ == PlayerStatus::PLAYING; } // Indica si el jugador está continuando -bool Player::isContinue() const -{ - return status_playing_ == PlayerStatus::CONTINUE; -} +bool Player::isContinue() const { return status_playing_ == PlayerStatus::CONTINUE; } // Indica si el jugador está esperando -bool Player::isWaiting() const -{ - return status_playing_ == PlayerStatus::WAITING; -} +bool Player::isWaiting() const { return status_playing_ == PlayerStatus::WAITING; } // Indica si el jugador está introduciendo su nombre -bool Player::isEnteringName() const -{ - return status_playing_ == PlayerStatus::ENTERING_NAME; -} +bool Player::isEnteringName() const { return status_playing_ == PlayerStatus::ENTERING_NAME; } // Indica si el jugador está muriendose -bool Player::isDying() const -{ - return status_playing_ == PlayerStatus::DYING; -} +bool Player::isDying() const { return status_playing_ == PlayerStatus::DYING; } // Indica si el jugador ha terminado de morir -bool Player::hasDied() const -{ - return status_playing_ == PlayerStatus::DIED; -} +bool Player::hasDied() const { return status_playing_ == PlayerStatus::DIED; } // Indica si el jugador ya ha terminado de jugar -bool Player::isGameOver() const -{ - return status_playing_ == PlayerStatus::GAME_OVER; -} +bool Player::isGameOver() const { return status_playing_ == PlayerStatus::GAME_OVER; } + +// Indica si el jugador está introduciendo su nombre una vez ha completado el juego +bool Player::isEnteringNameGameCompleted() const { return status_playing_ == PlayerStatus::ENTERING_NAME_GAME_COMPLETED; } + +// Indica si el jugador ha completado el juego +bool Player::isGameCompleted() const { return status_playing_ == PlayerStatus::GAME_COMPLETED; } // Actualiza el panel del marcador void Player::updateScoreboard() { switch (status_playing_) { - case PlayerStatus::CONTINUE: { Scoreboard::get()->setContinue(getScoreBoardPanel(), getContinueCounter()); break; } - case PlayerStatus::ENTERING_NAME: { Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName()); Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos()); break; } - + case PlayerStatus::ENTERING_NAME_GAME_COMPLETED: + { + Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName()); + Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos()); + break; + } default: break; } @@ -436,7 +410,6 @@ void Player::setStatusPlaying(PlayerStatus value) setScoreboardMode(ScoreboardMode::SCORE); break; } - case PlayerStatus::CONTINUE: { // Inicializa el contador de continuar @@ -446,19 +419,16 @@ void Player::setStatusPlaying(PlayerStatus value) setScoreboardMode(ScoreboardMode::CONTINUE); break; } - case PlayerStatus::WAITING: { setScoreboardMode(ScoreboardMode::WAITING); break; } - case PlayerStatus::ENTERING_NAME: { setScoreboardMode(ScoreboardMode::ENTER_NAME); break; } - case PlayerStatus::DYING: { // Activa la animación de morir @@ -467,42 +437,42 @@ void Player::setStatusPlaying(PlayerStatus value) rand() % 2 == 0 ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f); break; } - case PlayerStatus::DIED: { const auto nextPlayerStatus = IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME : PlayerStatus::CONTINUE; demo_ ? setStatusPlaying(PlayerStatus::WAITING) : setStatusPlaying(nextPlayerStatus); break; } - case PlayerStatus::GAME_OVER: { setScoreboardMode(ScoreboardMode::GAME_OVER); break; } - + case PlayerStatus::ENTERING_NAME_GAME_COMPLETED: + { + setWalkingStatus(PlayerStatus::WALKING_STOP); + setFiringStatus(PlayerStatus::FIRING_NONE); + setScoreboardMode(ScoreboardMode::ENTER_NAME); + break; + } + case PlayerStatus::GAME_COMPLETED: + { + setScoreboardMode(ScoreboardMode::GAME_OVER); + break; + } default: break; } } // Obtiene el estado del jugador en el juego -PlayerStatus Player::getStatusPlaying() const -{ - return status_playing_; -} +PlayerStatus Player::getStatusPlaying() const { return status_playing_; } // Obtiene el valor de la variable -float Player::getScoreMultiplier() const -{ - return score_multiplier_; -} +float Player::getScoreMultiplier() const { return score_multiplier_; } // Establece el valor de la variable -void Player::setScoreMultiplier(float value) -{ - score_multiplier_ = value; -} +void Player::setScoreMultiplier(float value) { score_multiplier_ = value; } // Aumenta el valor de la variable hasta un máximo void Player::incScoreMultiplier() @@ -519,10 +489,7 @@ void Player::decScoreMultiplier() } // Obtiene el valor de la variable -bool Player::isInvulnerable() const -{ - return invulnerable_; -} +bool Player::isInvulnerable() const { return invulnerable_; } // Establece el valor del estado void Player::setInvulnerable(bool value) @@ -532,16 +499,10 @@ void Player::setInvulnerable(bool value) } // Obtiene el valor de la variable -int Player::getInvulnerableCounter() const -{ - return invulnerable_counter_; -} +int Player::getInvulnerableCounter() const { return invulnerable_counter_; } // Establece el valor de la variable -void Player::setInvulnerableCounter(int value) -{ - invulnerable_counter_ = value; -} +void Player::setInvulnerableCounter(int value) { invulnerable_counter_ = value; } // Monitoriza el estado void Player::updateInvulnerable() @@ -562,10 +523,7 @@ void Player::updateInvulnerable() } // Obtiene el valor de la variable -bool Player::isPowerUp() const -{ - return power_up_; -} +bool Player::isPowerUp() const { return power_up_; } // Establece el valor de la variable void Player::setPowerUp() @@ -575,16 +533,10 @@ void Player::setPowerUp() } // Obtiene el valor de la variable -int Player::getPowerUpCounter() const -{ - return power_up_counter_; -} +int Player::getPowerUpCounter() const { return power_up_counter_; } // Establece el valor de la variable -void Player::setPowerUpCounter(int value) -{ - power_up_counter_ = value; -} +void Player::setPowerUpCounter(int value) { power_up_counter_ = value; } // Actualiza el valor de la variable void Player::updatePowerUp() @@ -597,10 +549,7 @@ void Player::updatePowerUp() } // Obtiene el valor de la variable -bool Player::hasExtraHit() const -{ - return extra_hit_; -} +bool Player::hasExtraHit() const { return extra_hit_; } // Concede un toque extra al jugador void Player::giveExtraHit() @@ -627,16 +576,10 @@ void Player::removeExtraHit() } // Devuelve el número de cafes actuales -int Player::getCoffees() const -{ - return coffees_; -} +int Player::getCoffees() const { return coffees_; } // Obtiene el circulo de colisión -Circle &Player::getCollider() -{ - return collider_; -} +Circle &Player::getCollider() { return collider_; } // Actualiza el circulo de colisión a la posición del jugador void Player::shiftColliders() @@ -653,10 +596,7 @@ void Player::setPlayerTextures(const std::vector> &text } // Obtiene el valor de la variable -int Player::getContinueCounter() const -{ - return continue_counter_; -} +int Player::getContinueCounter() const { return continue_counter_; } // Actualiza el contador de continue void Player::updateContinueCounter() @@ -674,7 +614,7 @@ void Player::updateContinueCounter() // Actualiza el contador de entrar nombre void Player::updateEnterNameCounter() { - if (status_playing_ == PlayerStatus::ENTERING_NAME) + if (status_playing_ == PlayerStatus::ENTERING_NAME || status_playing_ == PlayerStatus::ENTERING_NAME_GAME_COMPLETED) { constexpr int TICKS_SPEED = 1000; if (SDL_GetTicks() - enter_name_ticks_ > TICKS_SPEED) @@ -685,16 +625,10 @@ void Player::updateEnterNameCounter() } // Le asigna un panel en el marcador al jugador -void Player::setScoreBoardPanel(int panel) -{ - scoreboard_panel_ = panel; -} +void Player::setScoreBoardPanel(int panel) { scoreboard_panel_ = panel; } // Obtiene el valor de la variable -int Player::getScoreBoardPanel() const -{ - return scoreboard_panel_; -} +int Player::getScoreBoardPanel() const { return scoreboard_panel_; } // Decrementa el contador de continuar void Player::decContinueCounter() @@ -720,66 +654,45 @@ void Player::decEnterNameCounter() } // Establece el nombre del jugador -void Player::setName(const std::string &name) -{ - name_ = name; -} +void Player::setName(const std::string &name) { name_ = name; } // Establece el nombre del jugador para la tabla de mejores puntuaciones -void Player::setRecordName(const std::string &record_name) -{ - record_name_ = record_name.substr(0, 8); -} +void Player::setRecordName(const std::string &record_name) { record_name_ = record_name.substr(0, 8); } // Obtiene el nombre del jugador -std::string Player::getName() const -{ - return name_; -} +std::string Player::getName() const { return name_; } // Obtiene el nombre del jugador para la tabla de mejores puntuaciones -std::string Player::getRecordName() const -{ - return record_name_; -} +std::string Player::getRecordName() const { return record_name_; } // Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones int Player::getRecordNamePos() const { if (enter_name_) - { return enter_name_->getPosition(); - } return 0; } // Establece el mando que usará para ser controlado -void Player::setController(int index) -{ - controller_index_ = index; -} +void Player::setController(int index) { controller_index_ = index; } // Obtiene el mando que usa para ser controlado -int Player::getController() const -{ - return controller_index_; -} +int Player::getController() const { return controller_index_; } // Obtiene el "id" del jugador -int Player::getId() const -{ - return id_; -} +int Player::getId() const { return id_; } // Indica si el jugador se puede dibujar -bool Player::isRenderable() const -{ - return isPlaying() || isDying(); -} +bool Player::isRenderable() const { return isPlaying() || isDying() || isEnteringNameGameCompleted() || isGameCompleted(); } // Comprueba si la puntuación entra en la tabla de mejores puntuaciones -bool Player::IsEligibleForHighScore() +bool Player::IsEligibleForHighScore() { return score_ > options.game.hi_score_table.back().score; } + +// Recoloca los sprites +void Player::shiftSprite() { - return score_ > options.game.hi_score_table.back().score; + player_sprite_->setPosX(pos_x_); + player_sprite_->setPosY(pos_y_); + power_sprite_->setPosX(getPosX() - power_up_desp_x_); } \ No newline at end of file diff --git a/source/player.h b/source/player.h index 229d83b..5317c28 100644 --- a/source/player.h +++ b/source/player.h @@ -1,16 +1,17 @@ #pragma once +#include "animated_sprite.h" // Para AnimatedSprite +#include "enter_name.h" // Para EnterName +#include "utils.h" // Para Circle #include // Para SDL_Rect #include // Para Uint32 #include // Para unique_ptr, shared_ptr #include // Para string #include // Para vector -#include "animated_sprite.h" // Para AnimatedSprite -#include "enter_name.h" // Para EnterName -#include "utils.h" // Para Circle -class Texture; // lines 12-12 -enum class InputType : int; // lines 13-13 -enum class ScoreboardMode; // lines 14-14 + +class Texture; // lines 12-12 +enum class InputType : int; // lines 13-13 +enum class ScoreboardMode; // lines 14-14 // Estados del jugador enum class PlayerStatus @@ -31,6 +32,8 @@ enum class PlayerStatus DYING, DIED, GAME_OVER, + ENTERING_NAME_GAME_COMPLETED, + GAME_COMPLETED, }; // Variables del jugador @@ -75,7 +78,8 @@ private: int power_up_desp_x_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador Circle collider_ = Circle(0, 0, 9); // Circulo de colisión del jugador int continue_counter_ = 10; // Contador para poder continuar - Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo + Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de + // continue en función del tiempo int scoreboard_panel_ = 0; // Panel del marcador asociado al jugador std::string name_; // Nombre del jugador std::string record_name_; // Nombre del jugador para la tabla de mejores puntuaciones @@ -87,6 +91,9 @@ private: // Actualiza el circulo de colisión a la posición del jugador void shiftColliders(); + // Recoloca el sprite + void shiftSprite(); + // Monitoriza el estado void updateInvulnerable(); @@ -105,9 +112,6 @@ private: // Actualiza el panel del marcador void updateScoreboard(); - // Comprueba si la puntuación entra en la tabla de mejores puntuaciones - bool IsEligibleForHighScore(); - // Cambia el modo del marcador void setScoreboardMode(ScoreboardMode mode); @@ -202,6 +206,12 @@ public: // Indica si el jugador ya ha terminado de jugar bool isGameOver() const; + // Indica si el jugador está introduciendo su nombre una vez ha completado el juego + bool isEnteringNameGameCompleted() const; + + // Indica si el jugador ha completado el juego + bool isGameCompleted() const; + // Establece el estado del jugador en el juego void setStatusPlaying(PlayerStatus value); @@ -286,7 +296,7 @@ public: // Obtiene el nombre del jugador para la tabla de mejores puntuaciones std::string getRecordName() const; - // Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones + // Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones int getRecordNamePos() const; // Establece el mando que usará para ser controlado @@ -297,4 +307,7 @@ public: // Obtiene el "id" del jugador int getId() const; + + // Comprueba si la puntuación entra en la tabla de mejores puntuaciones + bool IsEligibleForHighScore(); };