#include "const.h"
#include "balloon.h"

// Constructor
Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, SDL_Renderer *renderer)
{
	mSprite = new AnimatedSprite();
	disable();

	const Uint8 NUM_FRAMES_BALLON = 10;
	const Uint8 NUM_FRAMES_BALLON_POP = 12;
	const Uint8 NUM_FRAMES_BALLON_BORN = 10;

	const Uint8 OFFSET_ORANGE_BALLOONS = 58 * 0;
	const Uint8 OFFSET_BLUE_BALLOONS = 58 * 1;
	const Uint8 OFFSET_GREEN_BALLOONS = 58 * 2;
	const Uint8 OFFSET_PURPLE_BALLOONS = 58 * 3;
	const Uint8 OFFSET_POWER_BALL = 58 * 4;
	const int OFFSET_EXPLOSIONS = 58 * 5;

	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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
		{
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 50 + OFFSET_ORANGE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
		}

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
		{
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 50 + OFFSET_BLUE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());
		}

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
		{
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 50 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());
		}

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_ORANGE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_BLUE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_ORANGE_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_BLUE_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_ORANGE_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_BLUE_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 50 + OFFSET_GREEN_BALLOONS, 21 + (37 * i), getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 50 + OFFSET_PURPLE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 50 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_GREEN_BALLOONS, 21 + (37 * i), getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_PURPLE_BALLOONS, 21 + (37 * i), getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 21 + (37 * i), getWidth(), getHeight());

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, 37 + OFFSET_GREEN_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, 37 + OFFSET_PURPLE_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, 37 + OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_GREEN_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_PURPLE_BALLOONS, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());

		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;

		// Establece los frames de cada animación
		for (int i = 0; i < NUM_FRAMES_BALLON; i++)
			mSprite->setAnimationFrames(BALLOON_MOVING_ANIMATION, i, OFFSET_POWER_BALL, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_BORN; i++)
			mSprite->setAnimationFrames(BALLOON_BORN_ANIMATION, i, OFFSET_POWER_BALL, 37 * i, getWidth(), getHeight());

		for (int i = 0; i < NUM_FRAMES_BALLON_POP; i++)
			mSprite->setAnimationFrames(BALLOON_POP_ANIMATION, i, OFFSET_EXPLOSIONS, 37 * i, getWidth(), getHeight());

		// 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};

	// Textura con los gráficos del sprite
	mSprite->setTexture(texture);

	// Renderizador
	mSprite->setRenderer(renderer);

	// 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;

	// Inicializa las variables para la animación
	// mSprite->setCurrentFrame(0);
	// mSprite->setAnimationCounter(0);

	// Establece el numero de frames de cada animacion
	// mSprite->setAnimationNumFrames(BALLOON_MOVING_ANIMATION, NUM_FRAMES_BALLON);
	// mSprite->setAnimationNumFrames(BALLOON_POP_ANIMATION, NUM_FRAMES_BALLON_POP);
	// mSprite->setAnimationNumFrames(BALLOON_BORN_ANIMATION, NUM_FRAMES_BALLON_BORN);

	// Establece la velocidad de cada animación
	mSprite->setAnimationSpeed(BALLOON_MOVING_ANIMATION, 10);
	mSprite->setAnimationSpeed(BALLOON_POP_ANIMATION, 5);
	mSprite->setAnimationSpeed(BALLOON_BORN_ANIMATION, 20);

	// Establece si la animación se reproduce en bucle
	mSprite->setAnimationLoop(BALLOON_MOVING_ANIMATION, true);
	mSprite->setAnimationLoop(BALLOON_POP_ANIMATION, false);
	mSprite->setAnimationLoop(BALLOON_BORN_ANIMATION, true);

	// Selecciona un frame para pintar
	mSprite->setSpriteClip(mSprite->getAnimationClip(0, 0));
}

// Destructor
Balloon::~Balloon()
{
	delete mSprite;
	mSprite = nullptr;
}

// 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(BALLOON_POP_ANIMATION);
	}
	else if (isBeingCreated())
	{
		mSprite->setCurrentAnimation(BALLOON_BORN_ANIMATION);
	}
	else
	{
		mSprite->setCurrentAnimation(BALLOON_MOVING_ANIMATION);
	}

	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();
	}
}