Revisada la classe Balloon

This commit is contained in:
2024-10-26 18:08:04 +02:00
parent f750997b34
commit 6235d0b684
3 changed files with 218 additions and 344 deletions

View File

@@ -1,5 +1,6 @@
#include "balloon.h"
#include <cmath> // para abs
#include <algorithm> // para clamp
#include "animated_sprite.h" // para SpriteAnimated
#include "moving_sprite.h" // para MovingSprite
#include "param.h" // para param
@@ -9,9 +10,9 @@
// Constructor
Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
pos_x_(x),
pos_y_(y),
vel_x_(vel_x),
x_(x),
y_(y),
vx_(vel_x),
being_created_(creation_timer > 0),
invulnerable_(creation_timer > 0),
creation_counter_(creation_timer),
@@ -24,13 +25,13 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
{
case BalloonType::BALLOON:
{
vel_y_ = 0;
max_vel_y_ = 3.0f;
vy_ = 0;
max_vy_ = 3.0f;
const int size = static_cast<int>(size_);
gravity_ = param.balloon.at(size).grav;
default_vel_y_ = param.balloon.at(size).vel;
height_ = width_ = BALLOON_SIZE[size];
default_vy_ = param.balloon.at(size).vel;
h_ = w_ = BALLOON_SIZE[size];
power_ = BALLOON_POWER[size];
menace_ = BALLOON_MENACE[size];
score_ = BALLOON_SCORE[size];
@@ -40,11 +41,11 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
case BalloonType::FLOATER:
{
default_vel_y_ = max_vel_y_ = vel_y_ = fabs(vel_x_ * 2.0f);
default_vy_ = max_vy_ = vy_ = fabs(vx_ * 2.0f);
gravity_ = 0.00f;
const int size = static_cast<int>(size_);
height_ = width_ = BALLOON_SIZE[size];
h_ = w_ = BALLOON_SIZE[size];
power_ = BALLOON_POWER[size];
menace_ = BALLOON_MENACE[size];
score_ = BALLOON_SCORE[size];
@@ -55,20 +56,17 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
case BalloonType::POWERBALL:
{
const int size = 3;
// Alto y ancho del objeto
height_ = width_ = BALLOON_SIZE[size];
h_ = w_ = BALLOON_SIZE[size];
power_ = score_ = menace_ = 0;
// Inicializa los valores de velocidad y gravedad
vel_y_ = 0;
max_vel_y_ = 3.0f;
vy_ = 0;
max_vy_ = 3.0f;
gravity_ = param.balloon.at(size).grav;
default_vel_y_ = param.balloon.at(size).vel;
default_vy_ = param.balloon.at(size).vel;
// Añade rotación al sprite_
sprite_->disableRotate();
sprite_->setRotateSpeed(0);
sprite_->setRotateAmount(vel_x_ > 0.0f ? 2.0 : -2.0);
sprite_->setRotateAmount(vx_ > 0.0f ? 2.0 : -2.0);
break;
}
@@ -77,82 +75,54 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
break;
}
// Valores para el efecto de rebote
bouncing_.enabled = false;
bouncing_.counter = 0;
bouncing_.speed = 2;
bouncing_.zoomW = 1.0f;
bouncing_.zoomH = 1.0f;
bouncing_.despX = 0.0f;
bouncing_.despY = 0.0f;
bouncing_.w = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f};
bouncing_.h = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f};
// Configura el sprite
sprite_->setPos({static_cast<int>(pos_x_), static_cast<int>(pos_y_), width_, height_});
sprite_->setWidth(w_);
sprite_->setHeight(h_);
shiftSprite();
// Alinea el circulo de colisión con el objeto
collider_.r = width_ / 2;
collider_.r = w_ / 2;
shiftColliders();
}
// Centra el globo en la posición X
void Balloon::allignTo(int x)
void Balloon::alignTo(int x)
{
pos_x_ = float(x - (width_ / 2));
if (pos_x_ < param.game.play_area.rect.x)
{
pos_x_ = param.game.play_area.rect.x + 1;
}
else if ((pos_x_ + width_) > param.game.play_area.rect.w)
{
pos_x_ = float(param.game.play_area.rect.w - width_ - 1);
}
// Posición X,Y del sprite_
sprite_->setPosX(getPosX());
sprite_->setPosY(getPosY());
// Alinea el circulo de colisión con el objeto
shiftColliders();
x_ = static_cast<float>(x - (w_ / 2));
const int min_x = param.game.play_area.rect.x;
const int max_x = param.game.play_area.rect.w - w_;
x_ = std::clamp(x_, static_cast<float>(min_x), static_cast<float>(max_x));
}
// Pinta el globo en la pantalla
void Balloon::render()
{
if (visible_ && enabled_)
if (isBeingCreated())
{
// Aplica alpha blending
sprite_->getTexture()->setAlpha(255 - (int)((float)creation_counter_ * (255.0f / (float)creation_counter_ini_)));
sprite_->render();
sprite_->getTexture()->setAlpha(255);
}
else
{
if (bouncing_.enabled)
{
if (type_ != BalloonType::POWERBALL)
{
// Aplica desplazamiento para el zoom
sprite_->setPosX(getPosX() + bouncing_.despX);
sprite_->setPosY(getPosY() + bouncing_.despY);
sprite_->render();
sprite_->setPosX(getPosX() - bouncing_.despX);
sprite_->setPosY(getPosY() - bouncing_.despY);
}
}
else if (isBeingCreated())
{
// Aplica alpha blending
sprite_->getTexture()->setAlpha(255 - (int)((float)creation_counter_ * (255.0f / (float)creation_counter_ini_)));
// Aplica efecto de bouncing
sprite_->setPos(x_ + bouncing_.despX, y_ + bouncing_.despY);
sprite_->render();
sprite_->getTexture()->setAlpha(255);
sprite_->setPos(x_ - bouncing_.despX, y_ - bouncing_.despY);
}
else
{
sprite_->render();
}
}
if (type_ == BalloonType::POWERBALL && !isBeingCreated())
{
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
sp->setSpriteClip(BALLOON_SIZE[3], 0, BALLOON_SIZE[3], BALLOON_SIZE[3]);
sp->render();
}
// Añade la máscara del borde a la PowerBall
if (type_ == BalloonType::POWERBALL && !isBeingCreated())
{
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
sp->setSpriteClip(BALLOON_SIZE[3], 0, BALLOON_SIZE[3], BALLOON_SIZE[3]);
sp->render();
}
}
@@ -162,61 +132,45 @@ void Balloon::move()
// Comprueba si se puede mover
if (!isStopped())
{
// Lo mueve a izquierda o derecha
pos_x_ += (vel_x_ * speed_);
// Mueve el globo en horizontal
x_ += vx_ * speed_;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((pos_x_ < param.game.play_area.rect.x) || (pos_x_ + width_ > param.game.play_area.rect.w))
// Colisión en las partes laterales de la zona de juego
const int clip = 2;
const float min_x = param.game.play_area.rect.x - clip;
const float max_x = param.game.play_area.rect.w - w_ + clip;
if (x_ < min_x || x_ > max_x)
{
// Corrige posición
pos_x_ -= (vel_x_ * speed_);
// Invierte sentido
vel_x_ = -vel_x_;
// Invierte la rotación
sprite_->switchRotate();
// Activa el efecto de rebote
if (type_ != BalloonType::POWERBALL)
{
bounceStart();
}
x_ = std::clamp(x_, min_x, max_x);
vx_ = -vx_;
// Activa el efecto de rebote o invierte la rotación
if (type_ == BalloonType::POWERBALL)
sprite_->switchRotate();
else
enableBounce();
}
// Mueve el globo hacia arriba o hacia abajo
pos_y_ += (vel_y_ * speed_);
// Mueve el globo en vertical
y_ += vy_ * speed_;
// Si se sale por arriba
if (pos_y_ < param.game.play_area.rect.y)
// Colisión en la parte superior de la zona de juego
const int min_y = param.game.play_area.rect.y;
if (y_ < min_y)
{
// Corrige
pos_y_ = param.game.play_area.rect.y;
// Invierte sentido
vel_y_ = -vel_y_;
// Activa el efecto de rebote
y_ = min_y;
vy_ = -vy_;
if (type_ != BalloonType::POWERBALL)
{
bounceStart();
}
enableBounce();
}
// Si el globo se sale por la parte inferior
if (pos_y_ + height_ > param.game.play_area.rect.h)
// Colisión en la parte inferior de la zona de juego
const int max_y = param.game.play_area.rect.h - h_;
if (y_ > max_y)
{
// Corrige
pos_y_ = param.game.play_area.rect.h - height_;
// Invierte colocando una velocidad por defecto
vel_y_ = -default_vel_y_;
// Activa el efecto de rebote
y_ = max_y;
vy_ = -default_vy_;
if (type_ != BalloonType::POWERBALL)
{
bounceStart();
}
enableBounce();
}
/*
@@ -238,46 +192,15 @@ void Balloon::move()
travel_y_ -= 1.0f;
// Aplica la gravedad al objeto sin pasarse de una velocidad máxima
vel_y_ += gravity_;
vy_ += gravity_;
}
// Actualiza la posición del sprite_
sprite_->setPosX(getPosX());
sprite_->setPosY(getPosY());
}
}
// Deshabilita el globo y pone a cero todos los valores
void Balloon::disable()
{
being_created_ = false;
blinking_ = false;
collider_.r = 0;
collider_.x = 0;
collider_.y = 0;
counter_ = 0;
creation_counter_ = 0;
creation_counter_ini_ = 0;
default_vel_y_ = 0.0f;
enabled_ = false;
gravity_ = 0.0f;
height_ = 0;
invulnerable_ = false;
max_vel_y_ = 0.0f;
menace_ = 0;
pos_x_ = 0.0f;
pos_y_ = 0.0f;
power_ = 0;
score_ = 0;
speed_ = 0;
stopped_ = false;
stopped_counter_ = 0;
travel_y_ = 0;
vel_x_ = 0.0f;
vel_y_ = 0.0f;
visible_ = false;
width_ = 0;
sprite_->clear();
}
// Explosiona el globo
@@ -289,16 +212,14 @@ void Balloon::pop()
// Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update()
{
if (enabled_)
{
sprite_->update();
move();
updateAnimation();
shiftColliders();
updateState();
updateBounce();
++counter_;
}
move();
updateAnimation();
updateState();
updateBounce();
shiftSprite();
shiftColliders();
sprite_->update();
++counter_;
}
// Actualiza los estados del globo
@@ -311,70 +232,54 @@ void Balloon::updateState()
setStop(true);
setInvulnerable(true);
// Todavia tiene tiempo en el contador
if (creation_counter_ > 0)
{
// Desplaza lentamente el globo hacia abajo y hacia un lado
if (creation_counter_ % 10 == 0)
{
pos_y_++;
pos_x_ += vel_x_;
y_++;
x_ += vx_;
// Comprueba no se salga por los laterales
if ((pos_x_ < param.game.play_area.rect.x) || (pos_x_ > (param.game.play_area.rect.w - width_)))
const int min_x = param.game.play_area.rect.x;
const int max_x = param.game.play_area.rect.w - w_;
if (x_ < min_x || x_ > max_x)
{
// Corrige y cambia el sentido de la velocidad
pos_x_ -= vel_x_;
vel_x_ = -vel_x_;
x_ -= vx_;
vx_ = -vx_;
}
// Actualiza la posición del sprite_
sprite_->setPosX(getPosX());
sprite_->setPosY(getPosY());
// Actualiza la posición del circulo de colisión
shiftColliders();
}
creation_counter_--;
--creation_counter_;
}
// El contador ha llegado a cero
else
{
setBeingCreated(false);
// El contador ha llegado a cero
being_created_ = false;
// visible_ = true;
setStop(false);
setVisible(true);
setInvulnerable(false);
if (type_ == BalloonType::POWERBALL)
{
sprite_->enableRotate();
}
}
}
// Solo comprueba el estado detenido cuando no se está creando
else if (isStopped())
{
// Si es una powerball deja de rodar
// 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_--;
}
// Si el contador ha llegado a cero
--stopped_counter_;
else
{ // Quitarles el estado "detenido"
{
// Si el contador ha llegado a cero
setStop(false);
// Si es una powerball vuelve a rodar
if (type_ == BalloonType::POWERBALL)
{
sprite_->enableRotate();
}
}
}
}
@@ -382,23 +287,27 @@ void Balloon::updateState()
// Establece la animación correspondiente al estado
void Balloon::updateAnimation()
{
std::string creating_animation = "blue";
std::string normal_animation = "orange";
std::string creating_animation;
std::string normal_animation;
if (type_ == BalloonType::POWERBALL)
switch (type_)
{
case BalloonType::POWERBALL:
creating_animation = "powerball";
normal_animation = "powerball";
}
else if (type_ == BalloonType::FLOATER)
{
break;
case BalloonType::FLOATER:
creating_animation = "red";
normal_animation = "green";
break;
default:
creating_animation = "blue";
normal_animation = "orange";
break;
}
// Establece el frame de animación
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation);
sprite_->update();
}
// Comprueba si el globo está habilitado
@@ -410,37 +319,31 @@ bool Balloon::isEnabled() const
// Obtiene del valor de la variable
float Balloon::getPosX() const
{
return pos_x_;
return x_;
}
// Obtiene del valor de la variable
float Balloon::getPosY() const
{
return pos_y_;
}
// Obtiene del valor de la variable
float Balloon::getVelY() const
{
return vel_y_;
return y_;
}
// Obtiene del valor de la variable
int Balloon::getWidth() const
{
return width_;
return w_;
}
// Obtiene del valor de la variable
int Balloon::getHeight() const
{
return height_;
return h_;
}
// Establece el valor de la variable
void Balloon::setVelY(float vel_y)
{
vel_y_ = vel_y;
vy_ = vel_y;
}
// Establece el valor de la variable
@@ -485,18 +388,6 @@ bool Balloon::isBlinking() const
return blinking_;
}
// Establece el valor de la variable
void Balloon::setVisible(bool value)
{
visible_ = value;
}
// Obtiene del valor de la variable
bool Balloon::isVisible() const
{
return visible_;
}
// Establece el valor de la variable
void Balloon::setInvulnerable(bool value)
{
@@ -509,12 +400,6 @@ bool Balloon::isInvulnerable() const
return invulnerable_;
}
// Establece el valor de la variable
void Balloon::setBeingCreated(bool value)
{
being_created_ = value;
}
// Obtiene del valor de la variable
bool Balloon::isBeingCreated() const
{
@@ -548,8 +433,22 @@ Circle &Balloon::getCollider()
// Alinea el circulo de colisión con la posición del objeto globo
void Balloon::shiftColliders()
{
collider_.x = Uint16(pos_x_ + collider_.r);
collider_.y = pos_y_ + collider_.r;
collider_.x = static_cast<int>(x_) + collider_.r;
collider_.y = static_cast<int>(y_) + collider_.r;
}
// Alinea el sprite con la posición del objeto globo
void Balloon::shiftSprite()
{
sprite_->setPosX(x_);
sprite_->setPosY(y_);
}
// Establece el nivel de zoom del sprite
void Balloon::zoomSprite()
{
sprite_->setZoomW(bouncing_.zoomW);
sprite_->setZoomH(bouncing_.zoomH);
}
// Obtiene le valor de la variable
@@ -564,44 +463,39 @@ Uint8 Balloon::getPower() const
return power_;
}
void Balloon::bounceStart()
// Activa el efecto
void Balloon::enableBounce()
{
bouncing_.enabled = true;
bouncing_.zoomW = 1;
bouncing_.zoomH = 1;
sprite_->setZoomW(bouncing_.zoomW);
sprite_->setZoomH(bouncing_.zoomH);
bouncing_.despX = 0;
bouncing_.despY = 0;
bouncing_.reset();
zoomSprite();
}
void Balloon::bounceStop()
// Detiene el efecto
void Balloon::disableBounce()
{
bouncing_.enabled = false;
bouncing_.counter = 0;
bouncing_.zoomW = 1.0f;
bouncing_.zoomH = 1.0f;
sprite_->setZoomW(bouncing_.zoomW);
sprite_->setZoomH(bouncing_.zoomH);
bouncing_.despX = 0.0f;
bouncing_.despY = 0.0f;
bouncing_.reset();
zoomSprite();
}
// Aplica el efecto
void Balloon::updateBounce()
{
if (bouncing_.enabled)
{
bouncing_.zoomW = bouncing_.w[bouncing_.counter / bouncing_.speed];
bouncing_.zoomH = bouncing_.h[bouncing_.counter / bouncing_.speed];
sprite_->setZoomW(bouncing_.zoomW);
sprite_->setZoomH(bouncing_.zoomH);
bouncing_.despX = (sprite_->getSpriteClip().w - (sprite_->getSpriteClip().w * bouncing_.zoomW));
bouncing_.despY = (sprite_->getSpriteClip().h - (sprite_->getSpriteClip().h * bouncing_.zoomH));
++bouncing_.counter;
if ((bouncing_.counter / bouncing_.speed) > (MAX_BOUNCE - 1))
{
bounceStop();
}
const int index = bouncing_.counter / bouncing_.speed;
bouncing_.zoomW = bouncing_.w[index];
bouncing_.zoomH = bouncing_.h[index];
zoomSprite();
const auto spriteClip = sprite_->getSpriteClip();
bouncing_.despX = spriteClip.w * (1.0f - bouncing_.zoomW);
bouncing_.despY = spriteClip.h * (1.0f - bouncing_.zoomH);
if (++bouncing_.counter / bouncing_.speed >= MAX_BOUNCE)
disableBounce();
}
}