Redissenyat el time stopper

This commit is contained in:
2024-10-27 13:36:00 +01:00
parent ddfb3672ea
commit 71f76fda05
12 changed files with 233 additions and 398 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

View File

@@ -15,6 +15,7 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
vx_(vel_x),
being_created_(creation_timer > 0),
invulnerable_(creation_timer > 0),
stopped_(creation_timer > 0),
creation_counter_(creation_timer),
creation_counter_ini_(creation_timer),
type_(type),
@@ -83,6 +84,9 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
// Alinea el circulo de colisión con el objeto
collider_.r = w_ / 2;
shiftColliders();
// Establece la animación a usar
setAnimation();
}
// Centra el globo en la posición X
@@ -213,7 +217,6 @@ void Balloon::pop()
void Balloon::update()
{
move();
updateAnimation();
updateState();
updateBounce();
shiftSprite();
@@ -229,7 +232,7 @@ void Balloon::updateState()
if (isBeingCreated())
{
// Actualiza el valor de las variables
setStop(true);
stop();
setInvulnerable(true);
if (creation_counter_ > 0)
@@ -258,34 +261,15 @@ void Balloon::updateState()
{
// El contador ha llegado a cero
being_created_ = false;
// visible_ = true;
setStop(false);
start();
setInvulnerable(false);
if (type_ == BalloonType::POWERBALL)
sprite_->enableRotate();
}
}
else if (isStopped())
{
// Solo comprueba el estado detenido cuando no se está creando
if (type_ == BalloonType::POWERBALL)
sprite_->disableRotate();
// Reduce el contador
if (stopped_counter_ > 0)
--stopped_counter_;
else
{
// Si el contador ha llegado a cero
setStop(false);
if (type_ == BalloonType::POWERBALL)
sprite_->enableRotate();
setAnimation();
}
}
}
// Establece la animación correspondiente al estado
void Balloon::updateAnimation()
void Balloon::setAnimation()
{
std::string creating_animation;
std::string normal_animation;
@@ -307,7 +291,10 @@ void Balloon::updateAnimation()
}
// Establece el frame de animación
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation);
if (use_reversed_colors_)
sprite_->setCurrentAnimation(creating_animation);
else
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation);
}
// Comprueba si el globo está habilitado
@@ -364,10 +351,20 @@ BalloonType Balloon::getType() const
return type_;
}
// Establece el valor de la variable
void Balloon::setStop(bool state)
// Detiene el globo
void Balloon::stop()
{
stopped_ = state;
stopped_ = true;
if (type_ == BalloonType::POWERBALL)
sprite_->disableRotate();
}
// Pone el globo en movimiento
void Balloon::start()
{
stopped_ = false;
if (type_ == BalloonType::POWERBALL)
sprite_->enableRotate();
}
// Obtiene del valor de la variable
@@ -376,18 +373,6 @@ bool Balloon::isStopped() const
return stopped_;
}
// Establece el valor de la variable
void Balloon::setBlink(bool value)
{
blinking_ = value;
}
// Obtiene del valor de la variable
bool Balloon::isBlinking() const
{
return blinking_;
}
// Establece el valor de la variable
void Balloon::setInvulnerable(bool value)
{
@@ -406,18 +391,6 @@ bool Balloon::isBeingCreated() const
return being_created_;
}
// Establece el valor de la variable
void Balloon::setStoppedTimer(Uint16 time)
{
stopped_counter_ = time;
}
// Obtiene del valor de la variable
Uint16 Balloon::getStoppedTimer() const
{
return stopped_counter_;
}
// Obtiene del valor de la variable
Uint16 Balloon::getScore() const
{
@@ -509,4 +482,27 @@ bool Balloon::canBePopped() const
bool Balloon::canBeDestroyed() const
{
return isEnabled();
}
// Pone el color alternativo en el globo
void Balloon::useReverseColor()
{
if (!isBeingCreated())
{
use_reversed_colors_ = true;
setAnimation();
}
}
// Pone el color normal en el globo
void Balloon::useNormalColor()
{
use_reversed_colors_ = false;
setAnimation();
}
// Indica si está usando el color alternativo
bool Balloon::isUsingReversedColor()
{
return use_reversed_colors_;
}

View File

@@ -87,32 +87,31 @@ private:
std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
// Variables
float x_; // Posición en el eje X
float y_; // Posición en el eje Y
Uint8 w_; // Ancho
Uint8 h_; // Alto
float vx_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vy_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float gravity_; // Aceleración en el eje Y. Modifica la velocidad
float default_vy_; // Velocidad inicial que tienen al rebotar contra el suelo
float max_vy_; // Máxima velocidad que puede alcanzar el objeto en el eje Y
bool being_created_; // Indica si el globo se está creando
bool blinking_ = false; // Indica si el globo está intermitente
bool enabled_ = true; // Indica si el globo esta activo
bool invulnerable_; // Indica si el globo es invulnerable
bool stopped_ = true; // Indica si el globo está parado
Circle collider_; // Circulo de colisión del objeto
Uint16 creation_counter_; // Temporizador para controlar el estado "creandose"
Uint16 creation_counter_ini_; // Valor inicial para el temporizador para controlar el estado "creandose"
Uint16 score_; // Puntos que da el globo al ser destruido
Uint16 stopped_counter_ = 0; // Contador para controlar el estado "parado"
BalloonType type_; // Clase de globo
BalloonSize size_; // Tamaño del globo
Uint8 menace_; // Cantidad de amenaza que genera el globo
Uint32 counter_ = 0; // Contador interno
float travel_y_ = 1.0f; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad
float speed_; // Velocidad a la que se mueven los globos
Uint8 power_; // Cantidad de poder que alberga el globo
float x_; // Posición en el eje X
float y_; // Posición en el eje Y
Uint8 w_; // Ancho
Uint8 h_; // Alto
float vx_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vy_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float gravity_; // Aceleración en el eje Y. Modifica la velocidad
float default_vy_; // Velocidad inicial que tienen al rebotar contra el suelo
float max_vy_; // Máxima velocidad que puede alcanzar el objeto en el eje Y
bool being_created_; // Indica si el globo se está creando
bool enabled_ = true; // Indica si el globo esta activo
bool invulnerable_; // Indica si el globo es invulnerable
bool stopped_; // Indica si el globo está parado
bool use_reversed_colors_ = false; // Indica si se ha de usar el color secundario del globo como color principal
Circle collider_; // Circulo de colisión del objeto
Uint16 creation_counter_; // Temporizador para controlar el estado "creandose"
Uint16 creation_counter_ini_; // Valor inicial para el temporizador para controlar el estado "creandose"
Uint16 score_; // Puntos que da el globo al ser destruido
BalloonType type_; // Clase de globo
BalloonSize size_; // Tamaño del globo
Uint8 menace_; // Cantidad de amenaza que genera el globo
Uint32 counter_ = 0; // Contador interno
float travel_y_ = 1.0f; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad
float speed_; // Velocidad a la que se mueven los globos
Uint8 power_; // Cantidad de poder que alberga el globo
// Alinea el circulo de colisión con la posición del objeto globo
void shiftColliders();
@@ -136,7 +135,7 @@ private:
void updateState();
// Establece la animación correspondiente
void updateAnimation();
void setAnimation();
public:
// Constructor
@@ -190,18 +189,15 @@ public:
// Obtiene el tipo de globo
BalloonType getType() const;
// Establece el valor de la variable
void setStop(bool value);
// 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 setBlink(bool value);
// Obtiene del valor de la variable
bool isBlinking() const;
// Establece el valor de la variable
void setInvulnerable(bool value);
@@ -211,12 +207,6 @@ public:
// Obtiene del valor de la variable
bool isBeingCreated() const;
// Establece el valor de la variable
void setStoppedTimer(Uint16 time);
// Obtiene del valor de la variable
Uint16 getStoppedTimer() const;
// Obtiene del valor de la variable
Uint16 getScore() const;
@@ -234,4 +224,13 @@ public:
// 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
bool isUsingReversedColor();
};

View File

@@ -431,6 +431,7 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_5000_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_powerup.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_one_hit.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_stop.png", AssetType::BITMAP);
}
{ // Intro

View File

@@ -16,7 +16,7 @@ void EnterName::init()
// Inicia la lista de caracteres permitidos
character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
position_ = 0;
num_characters_ = (int)character_list_.size();
num_characters_ = static_cast<int>(character_list_.size());
// Pone la lista de indices para que refleje el nombre
updateCharacterIndex();
@@ -36,7 +36,7 @@ void EnterName::incPosition()
// Decrementa la posición
void EnterName::decPosition()
{
position_--;
--position_;
position_ = std::max(position_, 0);
}
@@ -76,14 +76,14 @@ void EnterName::updateName()
void EnterName::updateCharacterIndex()
{
// Rellena de espacios y marca como no usados
for (int i = 0; i < NAME_LENGHT; ++i)
for (size_t i = 0; i < NAME_LENGHT; ++i)
{
character_index_[i] = 0;
position_has_been_used_[i] = false;
}
// Coloca los índices en funcion de los caracteres que forman el nombre
for (int i = 0; i < (int)name_.size(); ++i)
// Coloca los índices en función de los caracteres que forman el nombre
for (size_t i = 0; i < name_.size(); ++i)
{
character_index_[i] = findIndex(name_.at(i));
position_has_been_used_[i] = true;
@@ -91,15 +91,11 @@ void EnterName::updateCharacterIndex()
}
// Encuentra el indice de un caracter en "character_list_"
int EnterName::findIndex(char character)
int EnterName::findIndex(char character) const
{
for (int i = 0; i < (int)character_list_.size(); ++i)
{
if (character == character_list_[i])
{
for (size_t i = 0; i < character_list_.size(); ++i)
if (character == character_list_.at(i))
return i;
}
}
return 0;
}
@@ -121,9 +117,7 @@ void EnterName::checkIfPositionHasBeenUsed()
auto used = position_has_been_used_[position_];
if (!used && position_ > 0)
{
character_index_[position_] = character_index_[position_ - 1];
}
position_has_been_used_[position_] = true;
updateName();

View File

@@ -30,7 +30,7 @@ private:
void updateCharacterIndex();
// Encuentra el indice de un caracter en "characterList"
int findIndex(char character);
int findIndex(char character) const;
// Comprueba la posición y copia el caracter si es necesario
void checkIfPositionHasBeenUsed();

View File

@@ -124,6 +124,7 @@ void Game::setResources()
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_5000_points.png"));
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_powerup.png"));
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_one_hit.png"));
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_stop.png"));
}
// Texturas - Globos
@@ -438,6 +439,20 @@ std::shared_ptr<Balloon> Game::createBalloon(float x, int y, BalloonType type, B
return balloons_.back();
}
// Crea un globo a partir de otro globo
void Game::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction)
{
const float vx = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE;
const auto lower_size = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1);
auto b = createBalloon(0, balloon->getPosY(), balloon->getType(), lower_size, vx, balloon_speed_, 0);
b->alignTo(balloon->getPosX() + (balloon->getWidth() / 2));
b->setVelY(b->getType() == BalloonType::BALLOON ? -2.50f : vx * 2.0f);
if (balloon->isStopped())
b->stop();
if (balloon->isUsingReversedColor())
b->useReverseColor();
}
// Crea una PowerBall
void Game::createPowerBall()
{
@@ -491,7 +506,6 @@ void Game::updateBalloonSpeed()
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
void Game::popBalloon(std::shared_ptr<Balloon> balloon)
{
// Aumenta el poder de la fase
increaseStageCurrentPower(1);
balloons_popped_++;
@@ -503,29 +517,15 @@ void Game::popBalloon(std::shared_ptr<Balloon> balloon)
}
else
{
const int size = static_cast<int>(balloon->getSize());
if (size == static_cast<int>(BalloonSize::SIZE1))
if (balloon->getSize() != BalloonSize::SIZE1)
{
// Si es del tipo más pequeño, simplemente elimina el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), size);
balloon->pop();
createChildBalloon(balloon, "LEFT");
createChildBalloon(balloon, "RIGHT");
}
else
{
const auto lower_size = static_cast<BalloonSize>(size - 1);
// En cualquier otro caso, crea dos globos de un tipo inferior
auto balloon_left = createBalloon(0, balloon->getPosY(), balloon->getType(), lower_size, BALLOON_VELX_NEGATIVE, balloon_speed_, 0);
balloon_left->alignTo(balloon->getPosX() + (balloon->getWidth() / 2));
balloon_left->setVelY(balloon_left->getType() == BalloonType::BALLOON ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
auto balloon_right = createBalloon(0, balloon->getPosY(), balloon->getType(), lower_size, BALLOON_VELX_POSITIVE, balloon_speed_, 0);
balloon_right->alignTo(balloon->getPosX() + (balloon->getWidth() / 2));
balloon_right->setVelY(balloon_right->getType() == BalloonType::BALLOON ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
// Elimina el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), size);
balloon->pop();
}
// Agrega la explosión y elimina el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
balloon->pop();
}
// Recalcula el nivel de amenaza
@@ -543,19 +543,15 @@ void Game::destroyBalloon(std::shared_ptr<Balloon> &balloon)
case BalloonSize::SIZE4:
score = BALLOON_SCORE[3] + (2 * BALLOON_SCORE[2]) + (4 * BALLOON_SCORE[1]) + (8 * BALLOON_SCORE[0]);
break;
case BalloonSize::SIZE3:
score = BALLOON_SCORE[2] + (2 * BALLOON_SCORE[1]) + (4 * BALLOON_SCORE[0]);
break;
case BalloonSize::SIZE2:
score = BALLOON_SCORE[1] + (2 * BALLOON_SCORE[0]);
break;
case BalloonSize::SIZE1:
score = BALLOON_SCORE[0];
break;
default:
score = 0;
break;
@@ -563,9 +559,7 @@ void Game::destroyBalloon(std::shared_ptr<Balloon> &balloon)
// Otorga los puntos correspondientes al globo
for (auto &player : players_)
{
player->addScore(score * player->getScoreMultiplier() * difficulty_score_multiplier_);
}
updateHiScore();
// Aumenta el poder de la fase
@@ -576,21 +570,14 @@ void Game::destroyBalloon(std::shared_ptr<Balloon> &balloon)
// Destruye el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
balloon->pop();
// Recalcula el nivel de amenaza
evaluateAndSetMenace();
}
// Destruye todos los globos
void Game::destroyAllBalloons()
{
for (auto &balloon : balloons_)
{
if (balloon->canBeDestroyed())
{
destroyBalloon(balloon);
}
}
balloon_deploy_counter_ = 300;
JA_PlaySound(Resource::get()->getSound("powerball.wav"));
@@ -599,29 +586,32 @@ void Game::destroyAllBalloons()
}
// Detiene todos los globos
void Game::stopAllBalloons(int time)
void Game::stopAllBalloons()
{
for (auto &balloon : balloons_)
{
if (balloon->isEnabled())
{
balloon->setStop(true);
balloon->setStoppedTimer(time);
}
}
balloon->stop();
}
// Pone en marcha todos los globos
void Game::startAllBalloons()
{
for (auto &balloon : balloons_)
{
if ((balloon->isEnabled()) && (!balloon->isBeingCreated()))
{
balloon->setStop(false);
balloon->setStoppedTimer(0);
}
}
if (!balloon->isBeingCreated())
balloon->start();
}
// Cambia el color de todos los globos
void Game::reverseColorsToAllBalloons()
{
for (auto &balloon : balloons_)
balloon->useReverseColor();
}
// Cambia el color de todos los globos
void Game::normalColorsToAllBalloons()
{
for (auto &balloon : balloons_)
balloon->useNormalColor();
}
// Vacia del vector de globos los globos que ya no sirven
@@ -637,15 +627,9 @@ void Game::freeBalloons()
bool Game::checkPlayerBalloonCollision(std::shared_ptr<Player> &player)
{
for (auto &balloon : balloons_)
{
if ((balloon->isEnabled()) && !(balloon->isStopped()) && !(balloon->isInvulnerable()))
{
if (checkCollision(player->getCollider(), balloon->getCollider()))
{
return true;
}
}
}
return false;
}
@@ -654,9 +638,7 @@ bool Game::checkPlayerBalloonCollision(std::shared_ptr<Player> &player)
void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
{
if (!player->isPlaying())
{
return;
}
for (auto &item : items_)
{
@@ -672,27 +654,24 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
createItemScoreSprite(item->getPosX() + (item->getWidth() / 2) - (game_text_textures_[0]->getWidth() / 2), player->getPosY(), game_text_textures_[0]);
break;
}
case ItemType::GAVINA:
{
player->addScore(2500);
createItemScoreSprite(item->getPosX() + (item->getWidth() / 2) - (game_text_textures_[1]->getWidth() / 2), player->getPosY(), game_text_textures_[1]);
break;
}
case ItemType::PACMAR:
{
player->addScore(5000);
createItemScoreSprite(item->getPosX() + (item->getWidth() / 2) - (game_text_textures_[2]->getWidth() / 2), player->getPosY(), game_text_textures_[2]);
break;
}
case ItemType::CLOCK:
{
enableTimeStopItem();
createItemScoreSprite(item->getPosX() + (item->getWidth() / 2) - (game_text_textures_[5]->getWidth() / 2), player->getPosY(), game_text_textures_[5]);
break;
}
case ItemType::COFFEE:
{
if (player->getCoffees() == 2)
@@ -707,7 +686,6 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
}
break;
}
case ItemType::COFFEE_MACHINE:
{
player->setPowerUp();
@@ -715,7 +693,6 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
createItemScoreSprite(item->getPosX() + (item->getWidth() / 2) - (game_text_textures_[3]->getWidth() / 2), player->getPosY(), game_text_textures_[3]);
break;
}
default:
break;
}
@@ -785,27 +762,15 @@ void Game::checkBulletBalloonCollision()
void Game::moveBullets()
{
for (auto &bullet : bullets_)
{
if (bullet->isEnabled())
{
if (bullet->move() == BulletMoveStatus::OUT)
{
getPlayer(bullet->getOwner())->decScoreMultiplier();
}
}
}
if (bullet->move() == BulletMoveStatus::OUT)
getPlayer(bullet->getOwner())->decScoreMultiplier();
}
// Pinta las balas activas
void Game::renderBullets()
{
for (auto &bullet : bullets_)
{
if (bullet->isEnabled())
{
bullet->render();
}
}
bullet->render();
}
// Crea un objeto bala
@@ -818,22 +783,15 @@ void Game::createBullet(int x, int y, BulletType kind, bool powered_up, int owne
void Game::freeBullets()
{
if (!bullets_.empty())
{
for (int i = bullets_.size() - 1; i >= 0; --i)
{
if (!bullets_[i]->isEnabled())
{
bullets_.erase(bullets_.begin() + i);
}
}
}
}
// Actualiza los items
void Game::updateItems()
{
for (auto &item : items_)
{
if (item->isEnabled())
{
item->update();
@@ -843,16 +801,13 @@ void Game::updateItems()
screen_->shake();
}
}
}
}
// Pinta los items activos
void Game::renderItems()
{
for (auto &item : items_)
{
item->render();
}
}
// Devuelve un item al azar y luego segun sus probabilidades
@@ -869,28 +824,24 @@ ItemType Game::dropItem()
return ItemType::DISK;
}
break;
case 1:
if (lucky_number < helper_.item_gavina_odds)
{
return ItemType::GAVINA;
}
break;
case 2:
if (lucky_number < helper_.item_pacmar_odds)
{
return ItemType::GAVINA;
}
break;
case 3:
if (lucky_number < helper_.item_clock_odds)
{
return ItemType::CLOCK;
}
break;
case 4:
if (lucky_number < helper_.item_coffee_odds)
{
@@ -900,30 +851,22 @@ ItemType Game::dropItem()
else
{
if (helper_.need_coffee)
{
helper_.item_coffee_odds++;
}
}
break;
case 5:
if (lucky_number < helper_.item_coffee_machine_odds)
{
helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS_;
if (!coffee_machine_enabled_ && helper_.need_coffee_machine)
{
return ItemType::COFFEE_MACHINE;
}
}
else
{
if (helper_.need_coffee_machine)
{
helper_.item_coffee_machine_odds++;
}
}
break;
default:
break;
}
@@ -941,15 +884,9 @@ void Game::createItem(ItemType type, float x, float y)
void Game::freeItems()
{
if (!items_.empty())
{
for (int i = items_.size() - 1; i >= 0; --i)
{
if (!items_[i]->isEnabled())
{
items_.erase(items_.begin() + i);
}
}
}
}
// Crea un objeto SpriteSmart para mostrar la puntuación al coger un objeto
@@ -980,15 +917,9 @@ void Game::createItemScoreSprite(int x, int y, std::shared_ptr<Texture> texture)
void Game::freeSpriteSmarts()
{
if (!smart_sprites_.empty())
{
for (int i = smart_sprites_.size() - 1; i >= 0; --i)
{
if (smart_sprites_[i]->hasFinished())
{
smart_sprites_.erase(smart_sprites_.begin() + i);
}
}
}
}
// Crea un SpriteSmart para arrojar el item café al recibir un impacto
@@ -1018,18 +949,14 @@ void Game::throwCoffee(int x, int y)
void Game::updateSpriteSmarts()
{
for (auto &ss : smart_sprites_)
{
ss->update();
}
}
// Pinta los SpriteSmarts activos
void Game::renderSpriteSmarts()
{
for (auto &ss : smart_sprites_)
{
ss->render();
}
}
// Acciones a realizar cuando el jugador muere
@@ -1052,20 +979,13 @@ void Game::killPlayer(std::shared_ptr<Player> &player)
else
{
// Si no tiene cafes, muere
if (!demo_.enabled)
{
JA_PauseMusic();
}
stopAllBalloons(10);
pauseMusic();
stopAllBalloons();
JA_PlaySound(Resource::get()->getSound("player_collision.wav"));
screen_->shake();
JA_PlaySound(Resource::get()->getSound("coffeeout.wav"));
player->setStatusPlaying(PlayerStatus::DYING);
if (!demo_.enabled)
{
// En el modo DEMO ni se para la musica ni se añade la puntuación a la tabla
allPlayersAreNotPlaying() ? JA_StopMusic() : JA_ResumeMusic();
}
allPlayersAreNotPlaying() ? stopMusic() : resumeMusic();
}
}
@@ -1076,60 +996,36 @@ void Game::evaluateAndSetMenace()
{ return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
}
// Obtiene el valor de la variable
int Game::getMenace() const
{
return menace_current_;
}
// Establece el valor de la variable
void Game::setTimeStopped(bool value)
{
time_stopped_ = value;
}
// Obtiene el valor de la variable
bool Game::isTimeStopped() const
{
return time_stopped_;
}
// Establece el valor de la variable
void Game::setTimeStoppedCounter(int value)
{
time_stopped_counter_ = value;
}
// Incrementa el valor de la variable
void Game::incTimeStoppedCounter(int value)
{
time_stopped_counter_ += value;
}
// Actualiza y comprueba el valor de la variable
void Game::updateTimeStoppedCounter()
void Game::updateTimeStopped()
{
if (isTimeStopped())
if (time_stopped_counter_ > 0)
{
if (time_stopped_counter_ > 0)
time_stopped_counter_--;
if (time_stopped_counter_ > 120)
{
time_stopped_counter_--;
stopAllBalloons(TIME_STOPPED_COUNTER_);
if (time_stopped_counter_ % 30 == 0)
JA_PlaySound(Resource::get()->getSound("clock.wav"));
}
else
{
disableTimeStopItem();
if (time_stopped_counter_ % 15 == 0)
JA_PlaySound(Resource::get()->getSound("clock.wav"));
if (time_stopped_counter_ % 30 == 0)
normalColorsToAllBalloons();
if (time_stopped_counter_ % 30 == 15)
reverseColorsToAllBalloons();
}
}
else
disableTimeStopItem();
}
// Actualiza la variable enemyDeployCounter
void Game::updateBalloonDeployCounter()
{
if (balloon_deploy_counter_ > 0)
{
--balloon_deploy_counter_;
}
}
// Actualiza el juego
@@ -1149,9 +1045,7 @@ void Game::update()
{
// 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)
@@ -1174,9 +1068,7 @@ void Game::update()
// 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
@@ -1229,7 +1121,7 @@ void Game::update()
updateSpriteSmarts();
// Actualiza los contadores de estado y efectos
updateTimeStoppedCounter();
updateTimeStopped();
updateBalloonDeployCounter();
// Actualiza el ayudante
@@ -1273,9 +1165,7 @@ void Game::updateBackground()
{
// Si el juego está completado, se reduce la velocidad de las nubes
if (game_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
constexpr auto clouds_initial_speed = 0.05f;
@@ -1337,9 +1227,7 @@ void Game::render()
void Game::updateMenace()
{
if (game_completed_)
{
return;
}
const auto stage = balloon_formations_->getStage(current_stage_);
const float percent = current_power_ / stage.power_to_complete;
@@ -1364,33 +1252,7 @@ void Game::renderMessages()
{
// GetReady
if (counter_ < STAGE_COUNTER_ && !demo_.enabled)
{
text_nokia2_big_->write((int)get_ready_bitmap_path_[counter_], param.game.play_area.center_y - 8, lang::getText(75), -2);
}
// Time Stopped
if (time_stopped_)
{
if (time_stopped_counter_ > 100 || time_stopped_counter_ % 10 > 4)
{
text_nokia2_->writeDX(TEXT_CENTER, param.game.play_area.center_x, param.game.play_area.first_quarter_y, lang::getText(36) + std::to_string(time_stopped_counter_ / 10), -1, no_color, 1, shdw_txt_color);
}
if (time_stopped_counter_ > 100)
{
if (time_stopped_counter_ % 30 == 0)
{
JA_PlaySound(Resource::get()->getSound("clock.wav"));
}
}
else
{
if (time_stopped_counter_ % 15 == 0)
{
JA_PlaySound(Resource::get()->getSound("clock.wav"));
}
}
}
// STAGE NUMBER
if (stage_bitmap_counter_ < STAGE_COUNTER_)
@@ -1399,20 +1261,24 @@ void Game::renderMessages()
std::string text;
if (stage_number == 10)
{ // Ultima fase
{
// Ultima fase
text = lang::getText(79);
}
else
{ // X fases restantes
{
// X fases restantes
text = std::to_string(11 - stage_number) + lang::getText(38);
}
if (!game_completed_)
{ // Escribe el número de fases restantes
{
// Escribe el número de fases restantes
text_nokia2_big_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_], text, -2, no_color, 2, shdw_txt_color);
}
else
{ // Escribe el texto de juego completado
{
// Escribe el texto de juego completado
text = lang::getText(50);
text_nokia2_big_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_], text, -2, no_color, 1, shdw_txt_color);
text_nokia2_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_] + text_nokia2_big_->getCharacterSize() + 2, lang::getText(76), -1, no_color, 1, shdw_txt_color);
@@ -1423,25 +1289,17 @@ void Game::renderMessages()
// Habilita el efecto del item de detener el tiempo
void Game::enableTimeStopItem()
{
stopAllBalloons(TIME_STOPPED_COUNTER_);
setTimeStopped(true);
incTimeStoppedCounter(TIME_STOPPED_COUNTER_);
if (JA_GetMusicState() == JA_MUSIC_PLAYING && !demo_.enabled)
{
JA_PauseMusic();
}
stopAllBalloons();
reverseColorsToAllBalloons();
time_stopped_counter_ = TIME_STOPPED_COUNTER_;
}
// Deshabilita el efecto del item de detener el tiempo
void Game::disableTimeStopItem()
{
time_stopped_ = false;
setTimeStoppedCounter(0);
time_stopped_counter_ = 0;
startAllBalloons();
if (JA_GetMusicState() == JA_MUSIC_PAUSED && !demo_.enabled)
{
JA_ResumeMusic();
}
normalColorsToAllBalloons();
}
// Comprueba si la música ha de estar sonando
@@ -1449,10 +1307,8 @@ void Game::checkMusicStatus()
{
// Si la música no está sonando
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"));
}
}
// Bucle para el juego
@@ -1491,9 +1347,7 @@ void Game::initPaths()
// Vector con los valores del seno para 360 grados
float sin[360];
for (int i = 0; i < 360; ++i)
{
sin[i] = SDL_sinf((float)i * 3.14f / 180.0f);
}
// Letrero de STAGE #
constexpr auto first_part = STAGE_COUNTER_ / 4; // 50
@@ -1508,9 +1362,7 @@ void Game::initPaths()
}
for (int i = first_part; i < second_part; ++i)
{
stage_bitmap_path_[i] = center_point;
}
for (int i = second_part; i < STAGE_COUNTER_; ++i)
{
@@ -1536,9 +1388,7 @@ void Game::initPaths()
}
for (int i = first_part; i < second_part; ++i)
{
get_ready_bitmap_path_[i] = (int)finish1;
}
for (int i = second_part; i < STAGE_COUNTER_; ++i)
{
@@ -1552,9 +1402,7 @@ void Game::initPaths()
void Game::updateGameCompleted()
{
if (game_completed_)
{
game_completed_counter_++;
}
if (game_completed_counter_ == GAME_COMPLETED_END_)
{
@@ -1581,9 +1429,7 @@ void Game::updateHelper()
}
}
else
{
helper_.need_coffee = helper_.need_coffee_machine = false;
}
}
// Comprueba si todos los jugadores han terminado de jugar
@@ -1591,9 +1437,7 @@ bool Game::allPlayersAreWaitingOrGameOver()
{
auto success = true;
for (const auto &player : players_)
{
success &= player->isWaiting() || player->isGameOver();
}
return success;
}
@@ -1603,9 +1447,7 @@ bool Game::allPlayersAreGameOver()
{
auto success = true;
for (const auto &player : players_)
{
success &= player->isGameOver();
}
return success;
}
@@ -1615,9 +1457,7 @@ bool Game::allPlayersAreNotPlaying()
{
auto success = true;
for (const auto &player : players_)
{
success &= !player->isPlaying();
}
return success;
}
@@ -1642,10 +1482,7 @@ void Game::checkEvents()
{
case SDL_WINDOWEVENT_FOCUS_LOST:
{
if (!demo_.enabled)
{
pause(true);
}
pause(!demo_.enabled);
break;
}
@@ -1654,13 +1491,11 @@ void Game::checkEvents()
pause(false);
break;
}
case SDL_WINDOWEVENT_SIZE_CHANGED:
{
reloadTextures();
break;
}
default:
break;
}
@@ -1671,28 +1506,27 @@ void Game::checkEvents()
{
switch (event.key.keysym.sym)
{
// Crea una powerball
case SDLK_1:
case SDLK_1: // Crea una powerball
{
createPowerBall();
break;
}
// Crea dos globos gordos
case SDLK_2:
case SDLK_2: // Crea dos globos gordos
{
createTwoBigBalloons();
}
break;
// Activa el modo para pasar el juego automaticamente
case SDLK_3:
case SDLK_3: // Activa el modo para pasar el juego automaticamente
{
auto_pop_balloons_ = !auto_pop_balloons_;
Notifier::get()->showText("auto_pop_balloons_ " + boolToString(auto_pop_balloons_));
break;
}
case SDLK_4: // Suelta un item
{
createItem(ItemType::CLOCK, players_.at(0)->getPosX(), players_.at(0)->getPosY() - 40);
break;
}
default:
break;
}
@@ -1705,27 +1539,17 @@ void Game::checkEvents()
void Game::reloadTextures()
{
for (auto &texture : item_textures_)
{
texture->reLoad();
}
for (auto &texture : balloon_textures_)
{
texture->reLoad();
}
for (auto &textures : player_textures_)
{
for (auto &texture : textures)
{
texture->reLoad();
}
}
for (auto &texture : game_text_textures_)
{
texture->reLoad();
}
bullet_texture_->reLoad();
background_->reloadTextures();
@@ -1881,7 +1705,6 @@ void Game::handleDemoMode()
}
// Procesa las entradas para un jugador específico durante el modo demo.
// Incluye movimientos (izquierda, derecha, sin movimiento) y disparos automáticos.
void Game::handleDemoPlayerInput(const std::shared_ptr<Player> &player, int index)
{
const auto &demoData = demo_.data[index][demo_.counter];
@@ -2202,4 +2025,25 @@ void Game::createTwoBigBalloons()
auto p = set.init[i];
createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
}
}
// Pausa la música
void Game::pauseMusic()
{
if (JA_GetMusicState() == JA_MUSIC_PLAYING && !demo_.enabled)
JA_PauseMusic();
}
// Reanuda la música
void Game::resumeMusic()
{
if (JA_GetMusicState() == JA_MUSIC_PAUSED && !demo_.enabled)
JA_ResumeMusic();
}
// Detiene la música
void Game::stopMusic()
{
if (!demo_.enabled)
JA_StopMusic();
}

View File

@@ -72,7 +72,7 @@ private:
static constexpr int GAME_COMPLETED_START_FADE_ = 500;
static constexpr int GAME_COMPLETED_END_ = 700;
static constexpr int GAME_OVER_COUNTER_ = 350;
static constexpr int TIME_STOPPED_COUNTER_ = 300;
static constexpr int TIME_STOPPED_COUNTER_ = 360;
// Porcentaje de aparición de los objetos
static constexpr int ITEM_POINTS_1_DISK_ODDS_ = 10;
@@ -151,9 +151,9 @@ private:
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// Variables
HiScoreEntry hi_score_ =
HiScoreEntry(options.game.hi_score_table[0].name,
options.game.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
HiScoreEntry hi_score_ = HiScoreEntry(
options.game.hi_score_table[0].name,
options.game.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
int current_stage_; // Indica la fase actual
int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado
@@ -166,7 +166,6 @@ private:
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
bool time_stopped_ = false; // Indica si el tiempo está detenido
float balloon_speed_; // Velocidad a la que se mueven los enemigos
float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
@@ -231,6 +230,9 @@ private:
// Crea un globo nuevo en el vector de globos
std::shared_ptr<Balloon> createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int stopped_counter);
// Crea un globo a partir de otro globo
void createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction);
// Crea una PowerBall
void createPowerBall();
@@ -250,11 +252,17 @@ private:
void destroyAllBalloons();
// Detiene todos los globos
void stopAllBalloons(int time);
void stopAllBalloons();
// Pone en marcha todos los globos
void startAllBalloons();
// Cambia el color de todos los globos
void reverseColorsToAllBalloons();
// Cambia el color de todos los globos
void normalColorsToAllBalloons();
// Vacia el vector de globos
void freeBalloons();
@@ -315,26 +323,11 @@ private:
// Calcula y establece el valor de amenaza en funcion de los globos activos
void evaluateAndSetMenace();
// Obtiene el valor de la variable
int getMenace() const;
// Establece el valor de la variable
void setTimeStopped(bool value);
// Obtiene el valor de la variable
bool isTimeStopped() const;
// Establece el valor de la variable
void setTimeStoppedCounter(int value);
// Incrementa el valor de la variable
void incTimeStoppedCounter(int value);
// Actualiza la variable EnemyDeployCounter
void updateBalloonDeployCounter();
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter();
void updateTimeStopped();
// Gestiona el nivel de amenaza
void updateMenace();
@@ -342,6 +335,9 @@ private:
// Actualiza el fondo
void updateBackground();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
@@ -357,9 +353,6 @@ private:
// Calcula el poder actual de los globos en pantalla
int calculateScreenPower();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Actualiza el tramo final de juego, una vez completado
void updateGameCompleted();
@@ -415,7 +408,6 @@ private:
void handleDemoMode();
// Procesa las entradas para un jugador específico durante el modo demo.
// Incluye movimientos (izquierda, derecha, sin movimiento) y disparos automáticos.
void handleDemoPlayerInput(const std::shared_ptr<Player> &player, int index);
// Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos.
@@ -454,6 +446,15 @@ private:
// Crea dos globos gordos
void createTwoBigBalloons();
// Pausa la música
void pauseMusic();
// Reanuda la música
void resumeMusic();
// Detiene la música
void stopMusic();
public:
// Constructor
Game(int playerID, int current_stage, bool demo);

View File

@@ -44,7 +44,7 @@ Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr
}
// Centra el objeto en la posición X
void Item::allignTo(int x)
void Item::alignTo(int x)
{
pos_x_ = static_cast<float>(x - (width_ / 2));

View File

@@ -64,7 +64,7 @@ public:
~Item() = default;
// Centra el objeto en la posición X
void allignTo(int x);
void alignTo(int x);
// Pinta el objeto en la pantalla
void render();

View File

@@ -54,7 +54,7 @@ public:
explicit MovingSprite(std::shared_ptr<Texture> texture);
// Destructor
~MovingSprite() = default;
virtual ~MovingSprite() = default;
// Actualiza las variables internas del objeto
virtual void update();

View File

@@ -20,7 +20,7 @@ public:
explicit Sprite(std::shared_ptr<Texture>);
// Destructor
~Sprite() = default;
virtual ~Sprite() = default;
// Muestra el sprite por pantalla
virtual void render();