Files
coffee_crisis/source/balloon.cpp

861 lines
16 KiB
C++

#include "const.h"
#include "balloon.h"
// Constructor
Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, std::string file, SDL_Renderer *renderer)
{
mSprite = new AnimatedSprite(texture, renderer, file);
disable();
switch (kind)
{
case BALLOON_1:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_1;
mHeight = BALLOON_WIDTH_1;
mSize = BALLOON_SIZE_1;
mPower = 1;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3.0f;
mGravity = 0.09f;
mDefaultVelY = 2.6f;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_1;
// Amenaza que genera el globo
mMenace = 1;
break;
case BALLOON_2:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_2;
mHeight = BALLOON_WIDTH_2;
mSize = BALLOON_SIZE_2;
mPower = 3;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3.0f;
mGravity = 0.10f;
mDefaultVelY = 3.5f;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_2;
// Amenaza que genera el globo
mMenace = 2;
break;
case BALLOON_3:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_3;
mHeight = BALLOON_WIDTH_3;
mSize = BALLOON_SIZE_3;
mPower = 7;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3.0f;
mGravity = 0.10f;
mDefaultVelY = 4.50f;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_3;
// Amenaza que genera el globo
mMenace = 4;
break;
case BALLOON_4:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_4;
mHeight = BALLOON_WIDTH_4;
mSize = BALLOON_SIZE_4;
mPower = 15;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3.0f;
mGravity = 0.10f;
mDefaultVelY = 4.95f;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_4;
// Amenaza que genera el globo
mMenace = 8;
break;
case HEXAGON_1:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_1;
mHeight = BALLOON_WIDTH_1;
mSize = BALLOON_SIZE_1;
mPower = 1;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = abs(velx) * 2;
mMaxVelY = abs(velx) * 2;
mGravity = 0.00f;
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_1;
// Amenaza que genera el globo
mMenace = 1;
break;
case HEXAGON_2:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_2;
mHeight = BALLOON_WIDTH_2;
mSize = BALLOON_SIZE_2;
mPower = 3;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = abs(velx) * 2;
mMaxVelY = abs(velx) * 2;
mGravity = 0.00f;
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_2;
// Amenaza que genera el globo
mMenace = 2;
break;
case HEXAGON_3:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_3;
mHeight = BALLOON_WIDTH_3;
mSize = BALLOON_SIZE_3;
mPower = 7;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = abs(velx) * 2;
mMaxVelY = abs(velx) * 2;
mGravity = 0.00f;
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_3;
// Amenaza que genera el globo
mMenace = 4;
break;
case HEXAGON_4:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_4;
mHeight = BALLOON_WIDTH_4;
mSize = BALLOON_SIZE_4;
mPower = 15;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = abs(velx) * 2;
mMaxVelY = abs(velx) * 2;
mGravity = 0.00f;
mDefaultVelY = abs(velx) * 2;
// Puntos que da el globo al ser destruido
mScore = BALLOON_SCORE_4;
// Amenaza que genera el globo
mMenace = 8;
break;
case POWER_BALL:
mEnabled = true;
// Alto y ancho del objeto
mWidth = BALLOON_WIDTH_4;
mHeight = BALLOON_WIDTH_4;
mSize = 4;
mPower = 0;
// Inicializa los valores de velocidad y gravedad
mVelX = velx;
mVelY = 0;
mMaxVelY = 3.0f;
mGravity = 0.10f;
mDefaultVelY = 4.95f;
// Puntos que da el globo al ser destruido
mScore = 0;
// Amenaza que genera el globo
mMenace = 0;
// Añade rotación al sprite
mSprite->setRotate(false);
mSprite->setRotateSpeed(1);
mSprite->setRotateAmount(2.0);
break;
default:
mEnabled = false;
mMenace = 0;
break;
}
// Posición inicial
mPosX = x;
mPosY = y;
// Valores para el efecto de rebote
mBouncing.enabled = false;
mBouncing.counter = 0;
mBouncing.speed = 0;
mBouncing.zoomW = 1.0f;
mBouncing.zoomH = 1.0f;
mBouncing.despX = 0.0f;
mBouncing.despY = 0.0f;
mBouncing.w = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f};
mBouncing.h = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f};
// Alto y ancho del sprite
mSprite->setWidth(mWidth);
mSprite->setHeight(mHeight);
// Posición X,Y del sprite
mSprite->setPosX((int)mPosX);
mSprite->setPosY((int)mPosY);
// Tamaño del circulo de colisión
mCollider.r = mWidth / 2;
// Alinea el circulo de colisión con el objeto
updateColliders();
// Inicializa variables
mStopped = true;
mStoppedCounter = 0;
mBlinking = false;
mVisible = true;
mInvulnerable = false;
mBeingCreated = true;
mCreationCounter = creationtimer;
mCreationCounterIni = creationtimer;
mPopping = false;
mBouncing.enabled = false;
mBouncing.counter = 0;
mBouncing.speed = 2;
mBouncing.zoomW = 1;
mBouncing.zoomH = 1;
mBouncing.despX = 0;
mBouncing.despY = 0;
mCounter = 0;
mTravelY = 1.0f;
mSpeed = speed;
// Tipo
mKind = kind;
// Selecciona un frame para pintar
mSprite->setSpriteClip(mSprite->getAnimationClip(0, 0));
}
// Destructor
Balloon::~Balloon()
{
delete mSprite;
}
// Centra el globo en la posición X
void Balloon::allignTo(int x)
{
mPosX = float(x - (mWidth / 2));
if (mPosX < PLAY_AREA_LEFT)
mPosX = PLAY_AREA_LEFT + 1;
else if ((mPosX + mWidth) > PLAY_AREA_RIGHT)
mPosX = float(PLAY_AREA_RIGHT - mWidth - 1);
// Posición X,Y del sprite
mSprite->setPosX(getPosX());
mSprite->setPosY(getPosY());
// Alinea el circulo de colisión con el objeto
updateColliders();
}
// Pinta el globo en la pantalla
void Balloon::render()
{
if ((mVisible) && (mEnabled))
{
if (mBouncing.enabled)
{
// Aplica desplazamiento para el zoom
mSprite->setPosX(getPosX() + mBouncing.despX);
mSprite->setPosY(getPosY() + mBouncing.despY);
mSprite->render();
mSprite->setPosX(getPosX() - mBouncing.despX);
mSprite->setPosY(getPosY() - mBouncing.despY);
}
else if (isBeingCreated())
{
// Aplica alpha blending
mSprite->getTexture()->setAlpha(255 - (int)((float)mCreationCounter * (255.0f / (float)mCreationCounterIni)));
mSprite->render();
mSprite->getTexture()->setAlpha(255);
}
else
{
mSprite->render();
}
}
}
// Actualiza la posición y estados del globo
void Balloon::move()
{
// Comprueba si se puede mover
if (!isStopped())
{
// Lo mueve a izquierda o derecha
mPosX += (mVelX * mSpeed);
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT))
{
// Corrige posición
mPosX -= (mVelX * mSpeed);
// Invierte sentido
mVelX = -mVelX;
// Invierte la rotación
mSprite->switchRotate();
// Activa el efecto de rebote
bounceStart();
}
// Mueve el globo hacia arriba o hacia abajo
mPosY += (mVelY * mSpeed);
// Si se sale por arriba
if (mPosY < PLAY_AREA_TOP)
{
// Corrige
mPosY = PLAY_AREA_TOP;
// Invierte sentido
mVelY = -mVelY;
// Activa el efecto de rebote
bounceStart();
}
// Si el globo se sale por la parte inferior
if (mPosY + mHeight > PLAY_AREA_BOTTOM)
{
// Corrige
mPosY = PLAY_AREA_BOTTOM - mHeight;
// Invierte colocando una velocidad por defecto
mVelY = -mDefaultVelY;
// Activa el efecto de rebote
bounceStart();
}
/*
Para aplicar la gravedad, el diseño original la aplicaba en cada iteración del bucle
Al añadir el modificador de velocidad se reduce la distancia que recorre el objeto y por
tanto recibe mas gravedad. Para solucionarlo se va a aplicar la gravedad cuando se haya
recorrido una distancia igual a la velocidad en Y, que era el cálculo inicial
*/
// Incrementa la variable que calcula la distancia acumulada en Y
mTravelY += mSpeed;
// Si la distancia acumulada en Y es igual a la velocidad, se aplica la gravedad
if (mTravelY >= 1.0f)
{
// Quita el excedente
mTravelY -= 1.0f;
// Aplica la gravedad al objeto sin pasarse de una velocidad máxima
mVelY += mGravity;
std::min(mVelY, mMaxVelY);
}
// Actualiza la posición del sprite
mSprite->setPosX(getPosX());
mSprite->setPosY(getPosY());
}
}
// Deshabilita el globo y pone a cero todos los valores
void Balloon::disable()
{
mBeingCreated = false;
mBlinking = false;
mCollider.r = 0;
mCollider.x = 0;
mCollider.y = 0;
mCounter = 0;
mCreationCounter = 0;
mCreationCounterIni = 0;
mDefaultVelY = 0.0f;
mEnabled = false;
mGravity = 0.0f;
mHeight = 0;
mInvulnerable = false;
mKind = 0;
mMaxVelY = 0.0f;
mMenace = 0;
mPopping = false;
mPosX = 0.0f;
mPosY = 0.0f;
mPower = 0;
mScore = 0;
mSize = 0;
mSpeed = 0;
mStopped = false;
mStoppedCounter = 0;
mTimeToLive = 0;
mTravelY = 0;
mVelX = 0.0f;
mVelY = 0.0f;
mVisible = false;
mWidth = 0;
mSprite->clear();
}
// Explosiona el globo
void Balloon::pop()
{
setPopping(true);
mSprite->setAnimationCounter(0);
mSprite->disableRotate();
setTimeToLive(120);
setStop(true);
setStoppedTimer(2000);
setInvulnerable(true);
mMenace = 0;
}
// Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update()
{
if (mEnabled)
{
mSprite->MovingSprite::update();
move();
updateAnimation();
updateColliders();
updateState();
updateBounce();
mCounter++;
}
}
// Actualiza los estados del globo
void Balloon::updateState()
{
// Si está explotando
if (isPopping())
{
setInvulnerable(true);
setStop(true);
if (mSprite->animationIsCompleted())
{
mSprite->setAnimationCompleted(BALLOON_POP_ANIMATION, false);
mTimeToLive = 0;
disable();
}
else if (mTimeToLive > 0)
{
mTimeToLive--;
}
else
{
disable();
}
}
// Si se está creando
if (isBeingCreated())
{
// Actualiza el valor de las variables
setStop(true);
setInvulnerable(true);
// Todavia tiene tiempo en el contador
if (mCreationCounter > 0)
{
// Desplaza lentamente el globo hacia abajo y hacia un lado
if (mCreationCounter % 10 == 0)
{
mPosY++;
mPosX += mVelX;
// Comprueba no se salga por los laterales
if ((mPosX < PLAY_AREA_LEFT) || (mPosX > (PLAY_AREA_RIGHT - mWidth)))
{
// Corrige y cambia el sentido de la velocidad
mPosX -= mVelX;
mVelX = -mVelX;
}
// Actualiza la posición del sprite
mSprite->setPosX(getPosX());
mSprite->setPosY(getPosY());
// Actualiza la posición del circulo de colisión
updateColliders();
}
mCreationCounter--;
}
// El contador ha llegado a cero
else
{
setBeingCreated(false);
setStop(false);
setVisible(true);
setInvulnerable(false);
if (mKind == POWER_BALL)
{
mSprite->setRotate(true);
if (mVelX > 0.0f)
{
mSprite->setRotateAmount(2.0);
}
else
{
mSprite->setRotateAmount(-2.0);
}
}
}
}
// Solo comprueba el estado detenido cuando no se está creando
else if (isStopped())
{
// Si está detenido, reduce el contador
if (mStoppedCounter > 0)
{
mStoppedCounter--;
}
// Si el contador ha llegado a cero, ya no está detenido
else if (!isPopping())
{ // Quitarles el estado "detenido" si no estan explosionando
setStop(false);
}
}
}
// Establece la animación correspondiente al estado
void Balloon::updateAnimation()
{
// Establece el frame de animación
if (isPopping())
{
mSprite->setCurrentAnimation("pop");
}
else if (isBeingCreated())
{
mSprite->setCurrentAnimation("blue");
}
else
{
mSprite->setCurrentAnimation("orange");
}
mSprite->animate();
}
// Comprueba si el globo está habilitado
bool Balloon::isEnabled()
{
return mEnabled;
}
// Obtiene del valor de la variable
float Balloon::getPosX()
{
return mPosX;
}
// Obtiene del valor de la variable
float Balloon::getPosY()
{
return mPosY;
}
// Obtiene del valor de la variable
float Balloon::getVelY()
{
return mVelY;
}
// Obtiene del valor de la variable
int Balloon::getWidth()
{
return mWidth;
}
// Obtiene del valor de la variable
int Balloon::getHeight()
{
return mHeight;
}
// Establece el valor de la variable
void Balloon::setVelY(float velY)
{
mVelY = velY;
}
// Establece el valor de la variable
void Balloon::setSpeed(float speed)
{
mSpeed = speed;
}
// Obtiene del valor de la variable
int Balloon::getKind()
{
return mKind;
}
// Obtiene del valor de la variable
Uint8 Balloon::getSize()
{
return mSize;
}
// Obtiene la clase a la que pertenece el globo
Uint8 Balloon::getClass()
{
if ((mKind >= BALLOON_1) && (mKind <= BALLOON_4))
{
return BALLOON_CLASS;
}
else if ((mKind >= HEXAGON_1) && (mKind <= HEXAGON_4))
{
return HEXAGON_CLASS;
}
else
{
return 0;
}
}
// Establece el valor de la variable
void Balloon::setStop(bool state)
{
mStopped = state;
}
// Obtiene del valor de la variable
bool Balloon::isStopped()
{
return mStopped;
}
// Establece el valor de la variable
void Balloon::setBlink(bool state)
{
mBlinking = state;
}
// Obtiene del valor de la variable
bool Balloon::isBlinking()
{
return mBlinking;
}
// Establece el valor de la variable
void Balloon::setVisible(bool state)
{
mVisible = state;
}
// Obtiene del valor de la variable
bool Balloon::isVisible()
{
return mVisible;
}
// Establece el valor de la variable
void Balloon::setInvulnerable(bool state)
{
mInvulnerable = state;
}
// Obtiene del valor de la variable
bool Balloon::isInvulnerable()
{
return mInvulnerable;
}
// Establece el valor de la variable
void Balloon::setBeingCreated(bool state)
{
mBeingCreated = state;
}
// Obtiene del valor de la variable
bool Balloon::isBeingCreated()
{
return mBeingCreated;
}
// Establece el valor de la variable
void Balloon::setPopping(bool state)
{
mPopping = state;
}
// Obtiene del valor de la variable
bool Balloon::isPopping()
{
return mPopping;
}
// Establece el valor de la variable
void Balloon::setTimeToLive(Uint16 time)
{
mTimeToLive = time;
}
// Obtiene del valor de la variable
Uint16 Balloon::getTimeToLive()
{
return mTimeToLive;
}
// Establece el valor de la variable
void Balloon::setStoppedTimer(Uint16 time)
{
mStoppedCounter = time;
}
// Obtiene del valor de la variable
Uint16 Balloon::getStoppedTimer()
{
return mStoppedCounter;
}
// Obtiene del valor de la variable
Uint16 Balloon::getScore()
{
return mScore;
}
// Obtiene el circulo de colisión
circle_t &Balloon::getCollider()
{
return mCollider;
}
// Alinea el circulo de colisión con la posición del objeto globo
void Balloon::updateColliders()
{
mCollider.x = Uint16(mPosX + mCollider.r);
mCollider.y = mPosY + mCollider.r;
}
// Obtiene le valor de la variable
Uint8 Balloon::getMenace()
{
if (isEnabled())
{
return mMenace;
}
else
{
return 0;
}
}
// Obtiene le valor de la variable
Uint8 Balloon::getPower()
{
return mPower;
}
void Balloon::bounceStart()
{
mBouncing.enabled = true;
mBouncing.zoomW = 1;
mBouncing.zoomH = 1;
mSprite->setZoomW(mBouncing.zoomW);
mSprite->setZoomH(mBouncing.zoomH);
mBouncing.despX = 0;
mBouncing.despY = 0;
}
void Balloon::bounceStop()
{
mBouncing.enabled = false;
mBouncing.counter = 0;
mBouncing.zoomW = 1.0f;
mBouncing.zoomH = 1.0f;
mSprite->setZoomW(mBouncing.zoomW);
mSprite->setZoomH(mBouncing.zoomH);
mBouncing.despX = 0.0f;
mBouncing.despY = 0.0f;
}
void Balloon::updateBounce()
{
if (mBouncing.enabled)
{
mBouncing.zoomW = mBouncing.w.at(mBouncing.counter / mBouncing.speed);
mBouncing.zoomH = mBouncing.h.at(mBouncing.counter / mBouncing.speed);
mSprite->setZoomW(mBouncing.zoomW);
mSprite->setZoomH(mBouncing.zoomH);
mBouncing.despX = (mSprite->getSpriteClip().w - (mSprite->getSpriteClip().w * mBouncing.zoomW));
mBouncing.despY = (mSprite->getSpriteClip().h - (mSprite->getSpriteClip().h * mBouncing.zoomH));
mBouncing.counter++;
if ((mBouncing.counter / mBouncing.speed) > (MAX_BOUNCE - 1))
{
bounceStop();
}
}
}