#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(); mEnabled = true; switch (kind) { case BALLOON_1: // 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: // 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: // 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: // 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: // 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: // 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: // 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: // 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: // 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: 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->disableRotate(); 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::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(); } } }