Treballant en el final del joc

This commit is contained in:
2024-10-31 11:58:01 +01:00
parent 7e2691e33e
commit 30dfa4c545
7 changed files with 502 additions and 656 deletions

View File

@@ -200,17 +200,11 @@ void Balloon::move()
} }
} }
// Deshabilita el globo y pone a cero todos los valores // Deshabilita el globo
void Balloon::disable() void Balloon::disable() { enabled_ = false; }
{
enabled_ = false;
}
// Explosiona el globo // Explosiona el globo
void Balloon::pop() void Balloon::pop() { disable(); }
{
disable();
}
// Actualiza al globo a su posicion, animación y controla los contadores // Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update() void Balloon::update()
@@ -296,60 +290,6 @@ void Balloon::setAnimation()
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation); 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 // Detiene el globo
void Balloon::stop() void Balloon::stop()
{ {
@@ -366,42 +306,6 @@ void Balloon::start()
sprite_->enableRotate(); 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 // Alinea el circulo de colisión con la posición del objeto globo
void Balloon::shiftColliders() void Balloon::shiftColliders()
{ {
@@ -423,18 +327,6 @@ void Balloon::zoomSprite()
sprite_->setZoomH(bouncing_.zoomH); 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 // Activa el efecto
void Balloon::enableBounce() 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 // Pone el color alternativo en el globo
void Balloon::useReverseColor() void Balloon::useReverseColor()
{ {
@@ -500,8 +380,25 @@ void Balloon::useNormalColor()
setAnimation(); setAnimation();
} }
// Indica si está usando el color alternativo // Getters
bool Balloon::isUsingReversedColor() float Balloon::getPosX() const { return x_; }
{ float Balloon::getPosY() const { return y_; }
return use_reversed_colors_; 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; }

View File

@@ -161,75 +161,38 @@ public:
// Actualiza al globo a su posicion, animación y controla los contadores // Actualiza al globo a su posicion, animación y controla los contadores
void update(); 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 // Detiene el globo
void stop(); void stop();
// Pone el globo en movimiento // Pone el globo en movimiento
void start(); 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 // Pone el color alternativo en el globo
void useReverseColor(); void useReverseColor();
// Pone el color normal en el globo // Pone el color normal en el globo
void useNormalColor(); 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 isUsingReversedColor();
bool canBePopped() const;
// Setters
void setVelY(float vel_y);
void setSpeed(float speed);
void setInvulnerable(bool value);
}; };

View File

@@ -95,14 +95,10 @@ Director::Director(int argc, const char *argv[])
{ {
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table); auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
if (overrides.clear_hi_score_table) if (overrides.clear_hi_score_table)
{
manager->clear(); manager->clear();
}
else else
{
manager->loadFromFile(Asset::get()->get("score.bin")); manager->loadFromFile(Asset::get()->get("score.bin"));
} }
}
// Inicializa SDL // Inicializa SDL
initSDL(); initSDL();
@@ -629,7 +625,11 @@ void Director::runTitle()
void Director::runGame() void Director::runGame()
{ {
const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2; 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; constexpr auto current_stage = 0;
#endif
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF); auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF);
game->run(); game->run();
} }

View File

@@ -1,15 +1,4 @@
#include "game.h" #include "game.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_keycode.h> // for SDLK_1, SDLK_2, SDLK_3, SDLK_4
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_FOCUS_GAINED, SDL_...
#include <stdlib.h> // for rand, size_t
#include <algorithm> // for find_if, clamp, min, remove_if
#include <functional> // for function
#include <iterator> // for distance, size
#include <numeric> // for accumulate
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "background.h" // for Background #include "background.h" // for Background
#include "balloon.h" // for Balloon, BALLOON_SCORE, BALLOON_VE... #include "balloon.h" // for Balloon, BALLOON_SCORE, BALLOON_VE...
@@ -34,6 +23,18 @@
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // for SmartSprite
#include "text.h" // for Text #include "text.h" // for Text
#include "texture.h" // for Texture #include "texture.h" // for Texture
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_keycode.h> // for SDLK_1, SDLK_2, SDLK_3, SDLK_4
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_FOCUS_GAINED, SDL_...
#include <algorithm> // for find_if, clamp, min, remove_if
#include <functional> // for function
#include <iterator> // for distance, size
#include <numeric> // for accumulate
#include <stdlib.h> // for rand, size_t
struct JA_Sound_t; // lines 36-36 struct JA_Sound_t; // lines 36-36
// Constructor // Constructor
@@ -84,7 +85,7 @@ Game::Game(int player_id, int current_stage, bool demo)
initPaths(); initPaths();
setTotalPower(); setTotalPower();
// Crea los primeros globos // Crea los primeros globos y el mensaje de inicio
if (!demo_.enabled) if (!demo_.enabled)
{ {
createTwoBigBalloons(); createTwoBigBalloons();
@@ -210,7 +211,6 @@ void Game::deployBalloonFormation()
// Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última // Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última
if (balloon_deploy_counter_ == 0) if (balloon_deploy_counter_ == 0)
{ {
// En este punto se decide entre crear una powerball o una formación enemiga // En este punto se decide entre crear una powerball o una formación enemiga
if ((rand() % 100 < 15) && (canPowerBallBeCreated())) if ((rand() % 100 < 15) && (canPowerBallBeCreated()))
{ {
@@ -250,10 +250,7 @@ void Game::deployBalloonFormation()
} }
// Aumenta el poder de la fase // Aumenta el poder de la fase
void Game::increaseStageCurrentPower(int power) void Game::increaseStageCurrentPower(int power) { current_power_ += power; }
{
current_power_ += power;
}
// Actualiza el valor de hiScore en caso necesario // Actualiza el valor de hiScore en caso necesario
void Game::updateHiScore() void Game::updateHiScore()
@@ -328,34 +325,40 @@ void Game::updateStage()
// Cambio de fase // Cambio de fase
++current_stage_; ++current_stage_;
current_power_ = 0; 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")); JA_PlaySound(Resource::get()->getSound("stage_change.wav"));
balloon_speed_ = default_balloon_speed_; balloon_speed_ = default_balloon_speed_;
setBalloonSpeed(balloon_speed_); setBalloonSpeed(balloon_speed_);
screen_->flash(flash_color, 100); screen_->flash(flash_color, 100);
screen_->shake(); screen_->shake();
// Escribe el texto por pantalla // Ha llegado al final el juego
const auto stage_number = balloon_formations_->getStage(current_stage_).number; if (status_ == GameStatus::PLAYING && current_stage_ == 10)
if (!game_completed_)
{ {
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<Path> paths = {paths_.at(2), paths_.at(3)}; std::vector<Path> paths = {paths_.at(2), paths_.at(3)};
if (stage_number == 10) if (stage_number == 10)
createMessage(paths, Resource::get()->getTexture("last_stage")); createMessage(paths, Resource::get()->getTexture("last_stage"));
@@ -377,8 +380,8 @@ void Game::updateStage()
// Actualiza el estado de fin de la partida // Actualiza el estado de fin de la partida
void Game::updateGameOver() void Game::updateGameOver()
{ {
// Si todos estan en estado de Game Over // Si todos estan en estado de Game Over y no hay mensajes por pantalla
if (allPlayersAreGameOver()) if (allPlayersAreGameOver() && path_sprites_.empty())
{ {
if (game_over_counter_ > 0) if (game_over_counter_ > 0)
{ {
@@ -391,11 +394,7 @@ void Game::updateGameOver()
{ {
// Hace sonar aleatoriamente uno de los 4 sonidos de burbujas // Hace sonar aleatoriamente uno de los 4 sonidos de burbujas
const auto index = rand() % 4; const auto index = rand() % 4;
JA_Sound_t *sound[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")};
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); JA_PlaySound(sound[index], 0);
} }
@@ -416,19 +415,15 @@ void Game::updateGameOver()
void Game::updateBalloons() void Game::updateBalloons()
{ {
for (auto balloon : balloons_) for (auto balloon : balloons_)
{
balloon->update(); balloon->update();
} }
}
// 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_)
{
balloon->render(); balloon->render();
} }
}
// Crea un globo nuevo en el vector de globos // Crea un globo nuevo en el vector de globos
std::shared_ptr<Balloon> Game::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer) std::shared_ptr<Balloon> Game::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer)
@@ -477,22 +472,19 @@ void Game::createPowerBall()
void Game::setBalloonSpeed(float speed) void Game::setBalloonSpeed(float speed)
{ {
for (auto &balloon : balloons_) 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 // 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<float>(current_power_) / balloon_formations_->getStage(current_stage_).power_to_complete; const float percent = static_cast<float>(current_power_) / balloon_formations_->getStage(current_stage_).power_to_complete;
const float thresholds[] = {0.2f, 0.4f, 0.6f, 0.8f}; const float thresholds[] = {0.2f, 0.4f, 0.6f, 0.8f};
for (size_t i = 0; i < std::size(thresholds); ++i) for (size_t i = 0; i < std::size(thresholds); ++i)
{
if (balloon_speed_ == BALLOON_SPEED[i] && percent > thresholds[i]) if (balloon_speed_ == BALLOON_SPEED[i] && percent > thresholds[i])
{ {
balloon_speed_ = BALLOON_SPEED[i + 1]; balloon_speed_ = BALLOON_SPEED[i + 1];
@@ -500,7 +492,6 @@ void Game::updateBalloonSpeed()
break; // Salir del bucle una vez actualizada la velocidad y aplicada break; // Salir del bucle una vez actualizada la velocidad y aplicada
} }
} }
}
// Explosiona un globo. Lo destruye y crea otros dos si es el caso // Explosiona un globo. Lo destruye y crea otros dos si es el caso
void Game::popBalloon(std::shared_ptr<Balloon> balloon) void Game::popBalloon(std::shared_ptr<Balloon> balloon)
@@ -575,7 +566,6 @@ void Game::destroyBalloon(std::shared_ptr<Balloon> &balloon)
void Game::destroyAllBalloons() void Game::destroyAllBalloons()
{ {
for (auto &balloon : balloons_) for (auto &balloon : balloons_)
if (balloon->canBeDestroyed())
destroyBalloon(balloon); destroyBalloon(balloon);
balloon_deploy_counter_ = 300; balloon_deploy_counter_ = 300;
@@ -584,6 +574,13 @@ void Game::destroyAllBalloons()
screen_->shake(); screen_->shake();
} }
// Destruye todos los items
void Game::destroyAllItems()
{
for (auto &item : items_)
item->disable();
}
// Detiene todos los globos // Detiene todos los globos
void Game::stopAllBalloons() void Game::stopAllBalloons()
{ {
@@ -617,8 +614,7 @@ void Game::normalColorsToAllBalloons()
// Vacia del vector de globos los globos que ya no sirven // Vacia del vector de globos los globos que ya no sirven
void Game::freeBalloons() void Game::freeBalloons()
{ {
auto it = std::remove_if(balloons_.begin(), balloons_.end(), auto it = std::remove_if(balloons_.begin(), balloons_.end(), [](const auto &balloon)
[](const auto &balloon)
{ return !balloon->isEnabled(); }); { return !balloon->isEnabled(); });
balloons_.erase(it, balloons_.end()); balloons_.erase(it, balloons_.end());
} }
@@ -627,7 +623,7 @@ void Game::freeBalloons()
bool Game::checkPlayerBalloonCollision(std::shared_ptr<Player> &player) bool Game::checkPlayerBalloonCollision(std::shared_ptr<Player> &player)
{ {
for (auto &balloon : balloons_) for (auto &balloon : balloons_)
if ((balloon->isEnabled()) && !(balloon->isStopped()) && !(balloon->isInvulnerable())) if (!balloon->isStopped() && !balloon->isInvulnerable())
if (checkCollision(player->getCollider(), balloon->getCollider())) if (checkCollision(player->getCollider(), balloon->getCollider()))
return true; return true;
@@ -651,28 +647,36 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
case ItemType::DISK: case ItemType::DISK:
{ {
player->addScore(1000); 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]); createItemText(x, game_text_textures_[0]);
break; break;
} }
case ItemType::GAVINA: case ItemType::GAVINA:
{ {
player->addScore(2500); 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]); createItemText(x, game_text_textures_[1]);
break; break;
} }
case ItemType::PACMAR: case ItemType::PACMAR:
{ {
player->addScore(5000); 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]); createItemText(x, game_text_textures_[2]);
break; break;
} }
case ItemType::CLOCK: case ItemType::CLOCK:
{ {
enableTimeStopItem(); 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]); createItemText(x, game_text_textures_[5]);
break; break;
} }
@@ -681,13 +685,17 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
if (player->getCoffees() == 2) if (player->getCoffees() == 2)
{ {
player->addScore(5000); 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]); createItemText(x, game_text_textures_[2]);
} }
else else
{ {
player->giveExtraHit(); 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]); createItemText(x, game_text_textures_[4]);
} }
break; break;
@@ -696,7 +704,9 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
{ {
player->setPowerUp(); player->setPowerUp();
coffee_machine_enabled_ = false; 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]); createItemText(x, game_text_textures_[3]);
break; break;
} }
@@ -723,7 +733,7 @@ void Game::checkBulletBalloonCollision()
{ {
if (checkCollision(balloon->getCollider(), bullet->getCollider())) 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()); auto player = getPlayer(bullet->getOwner());
if (!player) if (!player)
{ {
@@ -783,7 +793,8 @@ void Game::renderBullets()
// Crea un objeto bala // Crea un objeto bala
void Game::createBullet(int x, int y, BulletType kind, bool powered_up, int owner) void Game::createBullet(int x, int y, BulletType kind, bool powered_up, int owner)
{ {
bullets_.emplace_back(std::make_unique<Bullet>(x, y, kind, powered_up, owner, bullet_texture_)); bullets_.emplace_back(
std::make_unique<Bullet>(x, y, kind, powered_up, owner, bullet_texture_));
} }
// Vacia el vector de balas // Vacia el vector de balas
@@ -1033,7 +1044,8 @@ void Game::killPlayer(std::shared_ptr<Player> &player)
// Calcula y establece el valor de amenaza en funcion de los globos activos // Calcula y establece el valor de amenaza en funcion de los globos activos
void Game::evaluateAndSetMenace() void Game::evaluateAndSetMenace()
{ {
menace_current_ = std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) menace_current_ = std::accumulate(
balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
{ return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); }); { return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
} }
@@ -1076,131 +1088,19 @@ void Game::update()
if (SDL_GetTicks() - ticks_ > TICKS_SPEED) if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{ {
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks(); ticks_ = SDL_GetTicks();
// Actualiza el contador de juego
counter_++; counter_++;
if (demo_.enabled) updateDemo();
{
// 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 #ifdef RECORDING
// Solo mira y guarda el input en cada update updateRecording();
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 #endif
#ifdef DEBUG updateNormalGame();
if (auto_pop_balloons_ && !game_completed_) updateCompletedGame();
{
balloons_popped_++;
increaseStageCurrentPower(1);
}
#endif
if (!paused_)
{
// Actualiza el objeto fade
fade_->update();
// 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(); checkMusicStatus();
// Actualiza el objeto screen
screen_->update(); screen_->update();
// Dibuja los graficos de la zona de juego en la textura
fillCanvas(); fillCanvas();
} }
} }
@@ -1209,7 +1109,7 @@ void Game::update()
void Game::updateBackground() void Game::updateBackground()
{ {
// Si el juego está completado, se reduce la velocidad de las nubes // 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; 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 // 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 // Gestiona el nivel de amenaza
void Game::updateMenace() void Game::updateMenace()
{ {
if (game_completed_)
return;
const auto stage = balloon_formations_->getStage(current_stage_); const auto stage = balloon_formations_->getStage(current_stage_);
const float percent = current_power_ / stage.power_to_complete; const float percent = current_power_ / stage.power_to_complete;
const int difference = stage.max_menace - stage.min_menace; const int difference = stage.max_menace - stage.min_menace;
@@ -1312,9 +1209,10 @@ void Game::disableTimeStopItem()
void Game::checkMusicStatus() void Game::checkMusicStatus()
{ {
// Si la música no está sonando // 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 // 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 // Bucle para el juego
@@ -1335,10 +1233,7 @@ void Game::run()
} }
// Indica si se puede crear una powerball // Indica si se puede crear una powerball
bool Game::canPowerBallBeCreated() bool Game::canPowerBallBeCreated() { return (!power_ball_enabled_) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); }
{
return (!power_ball_enabled_) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0);
}
// Calcula el poder actual de los globos en pantalla // Calcula el poder actual de los globos en pantalla
int Game::calculateScreenPower() int Game::calculateScreenPower()
@@ -1362,7 +1257,8 @@ void Game::initPaths()
paths_.emplace_back(Path(createPath(x1, x2, PathType::HORIZONTAL, y, 80, easeInQuint), 0)); 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 &texture = Resource::get()->getTexture("last_stage");
const auto h = texture->getHeight(); 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 // Actualiza las variables de ayuda
void Game::updateHelper() void Game::updateHelper()
{ {
@@ -1547,6 +1430,10 @@ void Game::checkEvents()
screen_->flash(flash_color, 100); screen_->flash(flash_color, 100);
break; break;
} }
case SDLK_8:
{
players_.at(0)->setStatusPlaying(PlayerStatus::GAME_COMPLETED);
}
default: default:
break; 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 // Saca del estado de GAME OVER al jugador si el otro está activo
void Game::checkAndUpdatePlayerStatus(int activePlayerIndex, int inactivePlayerIndex) void Game::checkAndUpdatePlayerStatus(int activePlayerIndex, int inactivePlayerIndex)
{ {
if (players_[activePlayerIndex]->isGameOver() && if (players_[activePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isWaiting())
!players_[inactivePlayerIndex]->isGameOver() &&
!players_[inactivePlayerIndex]->isWaiting())
{ {
players_[activePlayerIndex]->setStatusPlaying(PlayerStatus::WAITING); players_[activePlayerIndex]->setStatusPlaying(PlayerStatus::WAITING);
} }
@@ -1660,11 +1545,8 @@ std::shared_ptr<Player> Game::getPlayer(int id)
// Obtiene un controlador a partir del "id" del jugador // Obtiene un controlador a partir del "id" del jugador
int Game::getController(int player_id) int Game::getController(int player_id)
{ {
auto it = std::find_if(options.controller.begin(), options.controller.end(), auto it = std::find_if(options.controller.begin(), options.controller.end(), [player_id](const auto &controller)
[player_id](const auto &controller) { return controller.player_id == player_id; });
{
return controller.player_id == player_id;
});
if (it != options.controller.end()) if (it != options.controller.end())
{ {
@@ -1680,9 +1562,13 @@ void Game::checkInput()
checkPauseInput(); // Verifica si se debe pausar el juego. checkPauseInput(); // Verifica si se debe pausar el juego.
if (demo_.enabled) if (demo_.enabled)
handleDemoMode(); // Controla el comportamiento de los jugadores en modo demo. { // Controla el comportamiento de los jugadores en modo demo.
handleDemoMode();
}
else 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. screen_->checkInput(); // Verifica el input en la pantalla del juego.
globalInputs::check(); // Verifica los inputs globales. 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. // Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos.
void Game::handleDemoMode() void Game::handleDemoMode()
{ {
int i = 0; int index = 0;
for (const auto &player : players_) for (const auto &player : players_)
{ {
if (player->isPlaying()) 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()) if (input_->checkAnyButtonPressed())
{ {
section::name = section::Name::TITLE; // Salir del modo demo y regresar al menú principal. section::name = section::Name::TITLE; // Salir del modo demo y regresar al menú principal.
return; return;
} }
i++; ++index;
} }
} }
@@ -1730,19 +1619,31 @@ void Game::handleDemoPlayerInput(const std::shared_ptr<Player> &player, int inde
const auto &demoData = demo_.data[index][demo_.counter]; const auto &demoData = demo_.data[index][demo_.counter];
if (demoData.left == 1) if (demoData.left == 1)
{
player->setInput(InputType::LEFT); player->setInput(InputType::LEFT);
}
else if (demoData.right == 1) else if (demoData.right == 1)
{
player->setInput(InputType::RIGHT); player->setInput(InputType::RIGHT);
}
else if (demoData.no_input == 1) else if (demoData.no_input == 1)
{
player->setInput(InputType::NONE); player->setInput(InputType::NONE);
}
if (demoData.fire == 1) if (demoData.fire == 1)
{
handleFireInput(player, BulletType::UP); handleFireInput(player, BulletType::UP);
}
else if (demoData.fire_left == 1) else if (demoData.fire_left == 1)
{
handleFireInput(player, BulletType::LEFT); handleFireInput(player, BulletType::LEFT);
}
else if (demoData.fire_right == 1) else if (demoData.fire_right == 1)
{
handleFireInput(player, BulletType::RIGHT); 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. // Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos.
void Game::handleFireInput(const std::shared_ptr<Player> &player, BulletType bulletType) void Game::handleFireInput(const std::shared_ptr<Player> &player, BulletType bulletType)
@@ -1753,7 +1654,8 @@ void Game::handleFireInput(const std::shared_ptr<Player> &player, BulletType bul
: InputType::FIRE_RIGHT); : InputType::FIRE_RIGHT);
createBullet(player->getPosX() + (player->getWidth() / 2) - 6, player->getPosY() + (player->getHeight() / 2), bulletType, player->isPowerUp(), player->getId()); createBullet(player->getPosX() + (player->getWidth() / 2) - 6, player->getPosY() + (player->getHeight() / 2), bulletType, player->isPowerUp(), player->getId());
JA_PlaySound(Resource::get()->getSound("bullet.wav")); 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_) for (const auto &player : players_)
{ {
if (player->isPlaying()) 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()) else if (player->isContinue() || player->isWaiting())
handlePlayerContinue(player); // Gestiona la continuación del jugador. { // Gestiona la continuación del jugador.
else if (player->isEnteringName()) handlePlayerContinue(player);
handleNameInput(player); // Gestiona la introducción del nombre del jugador. }
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> &player)
handleFireInputs(player, autofire, controllerIndex); // Verifica y maneja todas las posibles entradas de disparo. 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. // Procesa las entradas de disparo del jugador, permitiendo disparos automáticos
void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex) // si está habilitado.
void Game::handleFireInputs(const std::shared_ptr<Player> &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); handleFireInput(player, BulletType::UP);
#ifdef RECORDING #ifdef RECORDING
demo_.keys.fire = 1; demo_.keys.fire = 1;
#endif #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); handleFireInput(player, BulletType::LEFT);
#ifdef RECORDING #ifdef RECORDING
demo_.keys.fire_left = 1; demo_.keys.fire_left = 1;
#endif #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); handleFireInput(player, BulletType::RIGHT);
#ifdef RECORDING #ifdef RECORDING
@@ -1828,19 +1744,29 @@ void Game::handleFireInputs(const std::shared_ptr<Player> &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> &player) void Game::handlePlayerContinue(const std::shared_ptr<Player> &player)
{ {
const auto controllerIndex = player->getController(); 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); player->setStatusPlaying(PlayerStatus::PLAYING);
} }
// Disminuye el contador de continuación si se presiona cualquier botón de disparo. // Disminuye el contador de continuación si se presiona cualquier botón de
if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || // disparo.
input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT,
input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) 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(); player->decContinueCounter();
} }
@@ -1858,7 +1784,8 @@ void Game::handleNameInput(const std::shared_ptr<Player> &player)
{ {
player->setInput(InputType::START); player->setInput(InputType::START);
addScoreToScoreBoard(player->getRecordName(), player->getScore()); 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 else
{ {
@@ -1877,15 +1804,18 @@ void Game::handleNameInput(const std::shared_ptr<Player> &player)
{ {
player->setInput(InputType::LEFT); player->setInput(InputType::LEFT);
} }
/*
else if (input_->checkInput(InputType::RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index))
{ {
player->setInput(InputType::RIGHT); player->setInput(InputType::RIGHT);
} }
*/
else if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index))
{ {
player->setInput(InputType::START); player->setInput(InputType::START);
addScoreToScoreBoard(player->getRecordName(), player->getScore()); 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]; 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) for (int i = 0; i < current_stage_; ++i)
{ {
balloons_popped_ += balloon_formations_->getStage(i).power_to_complete; balloons_popped_ += balloon_formations_->getStage(i).power_to_complete;
@@ -1954,7 +1885,8 @@ void Game::setTotalPower()
total_power_to_complete_game_ = 0; total_power_to_complete_game_ = 0;
for (int i = 0; i < 10; ++i) 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) for (int i = 0; i < numEnemies; ++i)
{ {
auto p = set.init[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);
} }
} }
@@ -2061,3 +1994,113 @@ void Game::stopMusic()
if (!demo_.enabled) if (!demo_.enabled)
JA_StopMusic(); 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();
}
}

View File

@@ -64,7 +64,12 @@ constexpr int TOTAL_SCORE_DATA = 3;
class Game class Game
{ {
private: private:
// Constantes // Enum
enum class GameStatus
{
PLAYING,
COMPLETED,
};
// Contadores // Contadores
static constexpr int HELP_COUNTER_ = 1000; static constexpr int HELP_COUNTER_ = 1000;
@@ -157,7 +162,6 @@ private:
Helper helper_; // Variable para gestionar las ayudas Helper helper_; // Variable para gestionar las ayudas
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa 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 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 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 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 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 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 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 int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
GameStatus status_ = GameStatus::PLAYING; // Estado
#ifdef DEBUG #ifdef DEBUG
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
#endif #endif
@@ -232,7 +237,7 @@ private:
void setBalloonSpeed(float speed); void setBalloonSpeed(float speed);
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase // 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 // Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(std::shared_ptr<Balloon> balloon); void popBalloon(std::shared_ptr<Balloon> balloon);
@@ -243,6 +248,9 @@ private:
// Destruye todos los globos // Destruye todos los globos
void destroyAllBalloons(); void destroyAllBalloons();
// Destruye todos los items
void destroyAllItems();
// Detiene todos los globos // Detiene todos los globos
void stopAllBalloons(); void stopAllBalloons();
@@ -357,9 +365,6 @@ private:
// Calcula el poder actual de los globos en pantalla // Calcula el poder actual de los globos en pantalla
int calculateScreenPower(); int calculateScreenPower();
// Actualiza el tramo final de juego, una vez completado
void updateGameCompleted();
// Actualiza las variables de ayuda // Actualiza las variables de ayuda
void updateHelper(); void updateHelper();
@@ -459,6 +464,18 @@ private:
// Detiene la música // Detiene la música
void stopMusic(); 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: public:
// Constructor // Constructor
Game(int playerID, int current_stage, bool demo); Game(int playerID, int current_stage, bool demo);

View File

@@ -61,8 +61,7 @@ void Player::init()
// Establece la posición del sprite // Establece la posición del sprite
player_sprite_->clear(); player_sprite_->clear();
player_sprite_->setPosX(pos_x_); shiftSprite();
player_sprite_->setPosY(pos_y_);
// Selecciona un frame para pintar // Selecciona un frame para pintar
player_sprite_->setCurrentAnimation("stand"); player_sprite_->setCurrentAnimation("stand");
@@ -78,13 +77,16 @@ void Player::setInput(InputType input)
setInputPlaying(input); setInputPlaying(input);
break; break;
} }
case PlayerStatus::ENTERING_NAME: case PlayerStatus::ENTERING_NAME:
{ {
setInputEnteringName(input); setInputEnteringName(input);
break; break;
} }
case PlayerStatus::ENTERING_NAME_GAME_COMPLETED:
{
setInputEnteringName(input);
break;
}
default: default:
break; break;
} }
@@ -101,32 +103,27 @@ void Player::setInputPlaying(InputType input)
setWalkingStatus(PlayerStatus::WALKING_LEFT); setWalkingStatus(PlayerStatus::WALKING_LEFT);
break; break;
} }
case InputType::RIGHT: case InputType::RIGHT:
{ {
vel_x_ = BASE_SPEED_; vel_x_ = BASE_SPEED_;
setWalkingStatus(PlayerStatus::WALKING_RIGHT); setWalkingStatus(PlayerStatus::WALKING_RIGHT);
break; break;
} }
case InputType::FIRE_CENTER: case InputType::FIRE_CENTER:
{ {
setFiringStatus(PlayerStatus::FIRING_UP); setFiringStatus(PlayerStatus::FIRING_UP);
break; break;
} }
case InputType::FIRE_LEFT: case InputType::FIRE_LEFT:
{ {
setFiringStatus(PlayerStatus::FIRING_LEFT); setFiringStatus(PlayerStatus::FIRING_LEFT);
break; break;
} }
case InputType::FIRE_RIGHT: case InputType::FIRE_RIGHT:
{ {
setFiringStatus(PlayerStatus::FIRING_RIGHT); setFiringStatus(PlayerStatus::FIRING_RIGHT);
break; break;
} }
default: default:
{ {
vel_x_ = 0; vel_x_ = 0;
@@ -144,23 +141,18 @@ void Player::setInputEnteringName(InputType input)
case InputType::LEFT: case InputType::LEFT:
enter_name_->decPosition(); enter_name_->decPosition();
break; break;
case InputType::RIGHT: case InputType::RIGHT:
enter_name_->incPosition(); enter_name_->incPosition();
break; break;
case InputType::UP: case InputType::UP:
enter_name_->incIndex(); enter_name_->incIndex();
break; break;
case InputType::DOWN: case InputType::DOWN:
enter_name_->decIndex(); enter_name_->decIndex();
break; break;
case InputType::START: case InputType::START:
setRecordName(enter_name_->getName()); setRecordName(enter_name_->getName());
break; break;
default: default:
break; break;
} }
@@ -170,7 +162,9 @@ void Player::setInputEnteringName(InputType input)
// Mueve el jugador a la posición y animación que le corresponde // Mueve el jugador a la posición y animación que le corresponde
void Player::move() void Player::move()
{ {
if (isPlaying()) switch (status_playing_)
{
case PlayerStatus::PLAYING:
{ {
// Mueve el jugador a derecha o izquierda // Mueve el jugador a derecha o izquierda
pos_x_ += vel_x_; 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 // 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 min_x = param.game.play_area.rect.x - 5;
const float max_x = play_area_.w + 5 - WIDTH_; 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 shiftSprite();
player_sprite_->setPosX(pos_x_); break;
player_sprite_->setPosY(pos_y_);
power_sprite_->setPosX(getPosX() - power_up_desp_x_);
} }
else if (isDying()) case PlayerStatus::DYING:
{ {
// Si el cadaver abandona el area de juego por los laterales lo hace rebotar // 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)) 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 // Si el cadaver abandona el area de juego por abajo
if (player_sprite_->getPosY() > param.game.play_area.rect.h) if (player_sprite_->getPosY() > param.game.play_area.rect.h)
setStatusPlaying(PlayerStatus::DIED); 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 // Establece el estado del jugador cuando camina
void Player::setWalkingStatus(PlayerStatus status) void Player::setWalkingStatus(PlayerStatus status) { status_walking_ = status; }
{
status_walking_ = status;
}
// Establece el estado del jugador cuando dispara // Establece el estado del jugador cuando dispara
void Player::setFiringStatus(PlayerStatus status) void Player::setFiringStatus(PlayerStatus status) { status_firing_ = status; }
{
status_firing_ = status;
}
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
void Player::setAnimation() 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; 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 // Establece la animación a partir de las cadenas
if (isPlaying()) if (isPlaying() || isEnteringNameGameCompleted() || isGameCompleted())
{ {
if (status_firing_ == PlayerStatus::FIRING_NONE) if (status_firing_ == PlayerStatus::FIRING_NONE)
{ // No esta disparando { // No esta disparando
@@ -259,41 +270,22 @@ void Player::setAnimation()
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getPosX() const int Player::getPosX() const { return static_cast<int>(pos_x_); }
{
return static_cast<int>(pos_x_);
}
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getPosY() const int Player::getPosY() const { return pos_y_; }
{
return pos_y_;
}
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getWidth() const int Player::getWidth() const { return WIDTH_; }
{
return WIDTH_;
}
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getHeight() const int Player::getHeight() const { return HEIGHT_; }
{
return HEIGHT_;
}
// Indica si el jugador puede disparar // Indica si el jugador puede disparar
bool Player::canFire() const bool Player::canFire() const { return cooldown_ > 0 ? false : true; }
{
// Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador
return cooldown_ > 0 ? false : true;
}
// Establece el valor de la variable // Establece el valor de la variable
void Player::setFireCooldown(int time) void Player::setFireCooldown(int time) { cooldown_ = time; }
{
cooldown_ = time;
}
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updateCooldown() void Player::updateCooldown()
@@ -327,16 +319,10 @@ void Player::update()
} }
// Obtiene la puntuación del jugador // Obtiene la puntuación del jugador
int Player::getScore() const int Player::getScore() const { return score_; }
{
return score_;
}
// Asigna un valor a la puntuación del jugador // Asigna un valor a la puntuación del jugador
void Player::setScore(int score) void Player::setScore(int score) { score_ = score; }
{
score_ = score;
}
// Incrementa la puntuación del jugador // Incrementa la puntuación del jugador
void Player::addScore(int score) void Player::addScore(int score)
@@ -348,66 +334,54 @@ void Player::addScore(int score)
} }
// Indica si el jugador está jugando // Indica si el jugador está jugando
bool Player::isPlaying() const bool Player::isPlaying() const { return status_playing_ == PlayerStatus::PLAYING; }
{
return status_playing_ == PlayerStatus::PLAYING;
}
// Indica si el jugador está continuando // Indica si el jugador está continuando
bool Player::isContinue() const bool Player::isContinue() const { return status_playing_ == PlayerStatus::CONTINUE; }
{
return status_playing_ == PlayerStatus::CONTINUE;
}
// Indica si el jugador está esperando // Indica si el jugador está esperando
bool Player::isWaiting() const bool Player::isWaiting() const { return status_playing_ == PlayerStatus::WAITING; }
{
return status_playing_ == PlayerStatus::WAITING;
}
// Indica si el jugador está introduciendo su nombre // Indica si el jugador está introduciendo su nombre
bool Player::isEnteringName() const bool Player::isEnteringName() const { return status_playing_ == PlayerStatus::ENTERING_NAME; }
{
return status_playing_ == PlayerStatus::ENTERING_NAME;
}
// Indica si el jugador está muriendose // Indica si el jugador está muriendose
bool Player::isDying() const bool Player::isDying() const { return status_playing_ == PlayerStatus::DYING; }
{
return status_playing_ == PlayerStatus::DYING;
}
// Indica si el jugador ha terminado de morir // Indica si el jugador ha terminado de morir
bool Player::hasDied() const bool Player::hasDied() const { return status_playing_ == PlayerStatus::DIED; }
{
return status_playing_ == PlayerStatus::DIED;
}
// Indica si el jugador ya ha terminado de jugar // Indica si el jugador ya ha terminado de jugar
bool Player::isGameOver() const bool Player::isGameOver() const { return status_playing_ == PlayerStatus::GAME_OVER; }
{
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 // Actualiza el panel del marcador
void Player::updateScoreboard() void Player::updateScoreboard()
{ {
switch (status_playing_) switch (status_playing_)
{ {
case PlayerStatus::CONTINUE: case PlayerStatus::CONTINUE:
{ {
Scoreboard::get()->setContinue(getScoreBoardPanel(), getContinueCounter()); Scoreboard::get()->setContinue(getScoreBoardPanel(), getContinueCounter());
break; break;
} }
case PlayerStatus::ENTERING_NAME: case PlayerStatus::ENTERING_NAME:
{ {
Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName()); Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName());
Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos()); Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos());
break; break;
} }
case PlayerStatus::ENTERING_NAME_GAME_COMPLETED:
{
Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName());
Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos());
break;
}
default: default:
break; break;
} }
@@ -436,7 +410,6 @@ void Player::setStatusPlaying(PlayerStatus value)
setScoreboardMode(ScoreboardMode::SCORE); setScoreboardMode(ScoreboardMode::SCORE);
break; break;
} }
case PlayerStatus::CONTINUE: case PlayerStatus::CONTINUE:
{ {
// Inicializa el contador de continuar // Inicializa el contador de continuar
@@ -446,19 +419,16 @@ void Player::setStatusPlaying(PlayerStatus value)
setScoreboardMode(ScoreboardMode::CONTINUE); setScoreboardMode(ScoreboardMode::CONTINUE);
break; break;
} }
case PlayerStatus::WAITING: case PlayerStatus::WAITING:
{ {
setScoreboardMode(ScoreboardMode::WAITING); setScoreboardMode(ScoreboardMode::WAITING);
break; break;
} }
case PlayerStatus::ENTERING_NAME: case PlayerStatus::ENTERING_NAME:
{ {
setScoreboardMode(ScoreboardMode::ENTER_NAME); setScoreboardMode(ScoreboardMode::ENTER_NAME);
break; break;
} }
case PlayerStatus::DYING: case PlayerStatus::DYING:
{ {
// Activa la animación de morir // 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); rand() % 2 == 0 ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f);
break; break;
} }
case PlayerStatus::DIED: case PlayerStatus::DIED:
{ {
const auto nextPlayerStatus = IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME : PlayerStatus::CONTINUE; const auto nextPlayerStatus = IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME : PlayerStatus::CONTINUE;
demo_ ? setStatusPlaying(PlayerStatus::WAITING) : setStatusPlaying(nextPlayerStatus); demo_ ? setStatusPlaying(PlayerStatus::WAITING) : setStatusPlaying(nextPlayerStatus);
break; break;
} }
case PlayerStatus::GAME_OVER: case PlayerStatus::GAME_OVER:
{ {
setScoreboardMode(ScoreboardMode::GAME_OVER); setScoreboardMode(ScoreboardMode::GAME_OVER);
break; 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: default:
break; break;
} }
} }
// Obtiene el estado del jugador en el juego // Obtiene el estado del jugador en el juego
PlayerStatus Player::getStatusPlaying() const PlayerStatus Player::getStatusPlaying() const { return status_playing_; }
{
return status_playing_;
}
// Obtiene el valor de la variable // Obtiene el valor de la variable
float Player::getScoreMultiplier() const float Player::getScoreMultiplier() const { return score_multiplier_; }
{
return score_multiplier_;
}
// Establece el valor de la variable // Establece el valor de la variable
void Player::setScoreMultiplier(float value) void Player::setScoreMultiplier(float value) { score_multiplier_ = value; }
{
score_multiplier_ = value;
}
// Aumenta el valor de la variable hasta un máximo // Aumenta el valor de la variable hasta un máximo
void Player::incScoreMultiplier() void Player::incScoreMultiplier()
@@ -519,10 +489,7 @@ void Player::decScoreMultiplier()
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Player::isInvulnerable() const bool Player::isInvulnerable() const { return invulnerable_; }
{
return invulnerable_;
}
// Establece el valor del estado // Establece el valor del estado
void Player::setInvulnerable(bool value) void Player::setInvulnerable(bool value)
@@ -532,16 +499,10 @@ void Player::setInvulnerable(bool value)
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getInvulnerableCounter() const int Player::getInvulnerableCounter() const { return invulnerable_counter_; }
{
return invulnerable_counter_;
}
// Establece el valor de la variable // Establece el valor de la variable
void Player::setInvulnerableCounter(int value) void Player::setInvulnerableCounter(int value) { invulnerable_counter_ = value; }
{
invulnerable_counter_ = value;
}
// Monitoriza el estado // Monitoriza el estado
void Player::updateInvulnerable() void Player::updateInvulnerable()
@@ -562,10 +523,7 @@ void Player::updateInvulnerable()
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Player::isPowerUp() const bool Player::isPowerUp() const { return power_up_; }
{
return power_up_;
}
// Establece el valor de la variable // Establece el valor de la variable
void Player::setPowerUp() void Player::setPowerUp()
@@ -575,16 +533,10 @@ void Player::setPowerUp()
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getPowerUpCounter() const int Player::getPowerUpCounter() const { return power_up_counter_; }
{
return power_up_counter_;
}
// Establece el valor de la variable // Establece el valor de la variable
void Player::setPowerUpCounter(int value) void Player::setPowerUpCounter(int value) { power_up_counter_ = value; }
{
power_up_counter_ = value;
}
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updatePowerUp() void Player::updatePowerUp()
@@ -597,10 +549,7 @@ void Player::updatePowerUp()
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Player::hasExtraHit() const bool Player::hasExtraHit() const { return extra_hit_; }
{
return extra_hit_;
}
// Concede un toque extra al jugador // Concede un toque extra al jugador
void Player::giveExtraHit() void Player::giveExtraHit()
@@ -627,16 +576,10 @@ void Player::removeExtraHit()
} }
// Devuelve el número de cafes actuales // Devuelve el número de cafes actuales
int Player::getCoffees() const int Player::getCoffees() const { return coffees_; }
{
return coffees_;
}
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &Player::getCollider() Circle &Player::getCollider() { return collider_; }
{
return collider_;
}
// Actualiza el circulo de colisión a la posición del jugador // Actualiza el circulo de colisión a la posición del jugador
void Player::shiftColliders() void Player::shiftColliders()
@@ -653,10 +596,7 @@ void Player::setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &text
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getContinueCounter() const int Player::getContinueCounter() const { return continue_counter_; }
{
return continue_counter_;
}
// Actualiza el contador de continue // Actualiza el contador de continue
void Player::updateContinueCounter() void Player::updateContinueCounter()
@@ -674,7 +614,7 @@ void Player::updateContinueCounter()
// Actualiza el contador de entrar nombre // Actualiza el contador de entrar nombre
void Player::updateEnterNameCounter() 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; constexpr int TICKS_SPEED = 1000;
if (SDL_GetTicks() - enter_name_ticks_ > TICKS_SPEED) if (SDL_GetTicks() - enter_name_ticks_ > TICKS_SPEED)
@@ -685,16 +625,10 @@ void Player::updateEnterNameCounter()
} }
// Le asigna un panel en el marcador al jugador // Le asigna un panel en el marcador al jugador
void Player::setScoreBoardPanel(int panel) void Player::setScoreBoardPanel(int panel) { scoreboard_panel_ = panel; }
{
scoreboard_panel_ = panel;
}
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getScoreBoardPanel() const int Player::getScoreBoardPanel() const { return scoreboard_panel_; }
{
return scoreboard_panel_;
}
// Decrementa el contador de continuar // Decrementa el contador de continuar
void Player::decContinueCounter() void Player::decContinueCounter()
@@ -720,66 +654,45 @@ void Player::decEnterNameCounter()
} }
// Establece el nombre del jugador // Establece el nombre del jugador
void Player::setName(const std::string &name) void Player::setName(const std::string &name) { name_ = name; }
{
name_ = name;
}
// Establece el nombre del jugador para la tabla de mejores puntuaciones // Establece el nombre del jugador para la tabla de mejores puntuaciones
void Player::setRecordName(const std::string &record_name) void Player::setRecordName(const std::string &record_name) { record_name_ = record_name.substr(0, 8); }
{
record_name_ = record_name.substr(0, 8);
}
// Obtiene el nombre del jugador // Obtiene el nombre del jugador
std::string Player::getName() const std::string Player::getName() const { return name_; }
{
return name_;
}
// Obtiene el nombre del jugador para la tabla de mejores puntuaciones // Obtiene el nombre del jugador para la tabla de mejores puntuaciones
std::string Player::getRecordName() const std::string Player::getRecordName() const { return record_name_; }
{
return record_name_;
}
// Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones // Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones
int Player::getRecordNamePos() const int Player::getRecordNamePos() const
{ {
if (enter_name_) if (enter_name_)
{
return enter_name_->getPosition(); return enter_name_->getPosition();
}
return 0; return 0;
} }
// Establece el mando que usará para ser controlado // Establece el mando que usará para ser controlado
void Player::setController(int index) void Player::setController(int index) { controller_index_ = index; }
{
controller_index_ = index;
}
// Obtiene el mando que usa para ser controlado // Obtiene el mando que usa para ser controlado
int Player::getController() const int Player::getController() const { return controller_index_; }
{
return controller_index_;
}
// Obtiene el "id" del jugador // Obtiene el "id" del jugador
int Player::getId() const int Player::getId() const { return id_; }
{
return id_;
}
// Indica si el jugador se puede dibujar // Indica si el jugador se puede dibujar
bool Player::isRenderable() const bool Player::isRenderable() const { return isPlaying() || isDying() || isEnteringNameGameCompleted() || isGameCompleted(); }
{
return isPlaying() || isDying();
}
// Comprueba si la puntuación entra en la tabla de mejores puntuaciones // 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_);
} }

View File

@@ -1,13 +1,14 @@
#pragma once #pragma once
#include "animated_sprite.h" // Para AnimatedSprite
#include "enter_name.h" // Para EnterName
#include "utils.h" // Para Circle
#include <SDL2/SDL_rect.h> // Para SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_stdinc.h> // Para Uint32 #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr, shared_ptr #include <memory> // Para unique_ptr, shared_ptr
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "animated_sprite.h" // Para AnimatedSprite
#include "enter_name.h" // Para EnterName
#include "utils.h" // Para Circle
class Texture; // lines 12-12 class Texture; // lines 12-12
enum class InputType : int; // lines 13-13 enum class InputType : int; // lines 13-13
enum class ScoreboardMode; // lines 14-14 enum class ScoreboardMode; // lines 14-14
@@ -31,6 +32,8 @@ enum class PlayerStatus
DYING, DYING,
DIED, DIED,
GAME_OVER, GAME_OVER,
ENTERING_NAME_GAME_COMPLETED,
GAME_COMPLETED,
}; };
// Variables del jugador // Variables del jugador
@@ -75,7 +78,8 @@ private:
int power_up_desp_x_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador 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 Circle collider_ = Circle(0, 0, 9); // Circulo de colisión del jugador
int continue_counter_ = 10; // Contador para poder continuar 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 int scoreboard_panel_ = 0; // Panel del marcador asociado al jugador
std::string name_; // Nombre del jugador std::string name_; // Nombre del jugador
std::string record_name_; // Nombre del jugador para la tabla de mejores puntuaciones 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 // Actualiza el circulo de colisión a la posición del jugador
void shiftColliders(); void shiftColliders();
// Recoloca el sprite
void shiftSprite();
// Monitoriza el estado // Monitoriza el estado
void updateInvulnerable(); void updateInvulnerable();
@@ -105,9 +112,6 @@ private:
// Actualiza el panel del marcador // Actualiza el panel del marcador
void updateScoreboard(); void updateScoreboard();
// Comprueba si la puntuación entra en la tabla de mejores puntuaciones
bool IsEligibleForHighScore();
// Cambia el modo del marcador // Cambia el modo del marcador
void setScoreboardMode(ScoreboardMode mode); void setScoreboardMode(ScoreboardMode mode);
@@ -202,6 +206,12 @@ public:
// Indica si el jugador ya ha terminado de jugar // Indica si el jugador ya ha terminado de jugar
bool isGameOver() const; 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 // Establece el estado del jugador en el juego
void setStatusPlaying(PlayerStatus value); void setStatusPlaying(PlayerStatus value);
@@ -286,7 +296,7 @@ public:
// Obtiene el nombre del jugador para la tabla de mejores puntuaciones // Obtiene el nombre del jugador para la tabla de mejores puntuaciones
std::string getRecordName() const; 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; int getRecordNamePos() const;
// Establece el mando que usará para ser controlado // Establece el mando que usará para ser controlado
@@ -297,4 +307,7 @@ public:
// Obtiene el "id" del jugador // Obtiene el "id" del jugador
int getId() const; int getId() const;
// Comprueba si la puntuación entra en la tabla de mejores puntuaciones
bool IsEligibleForHighScore();
}; };