diff --git a/media/gfx/items.png b/media/gfx/items.png index f5a5704..f81f0aa 100644 Binary files a/media/gfx/items.png and b/media/gfx/items.png differ diff --git a/source/const.h b/source/const.h index 9a1c042..7c42b0a 100644 --- a/source/const.h +++ b/source/const.h @@ -286,6 +286,15 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2; #define ITEM_POWER_BALL 6 #define ITEM_COFFEE_MACHINE 7 +// Porcentaje de aparición de los objetos +#define ITEM_POINTS_1_DISK_ODDS 10 +#define ITEM_POINTS_2_GAVINA_ODDS 6 +#define ITEM_POINTS_3_PACMAR_ODDS 3 +#define ITEM_CLOCK_ODDS 5 +#define ITEM_COFFEE_ODDS 5 +#define ITEM_POWER_BALL_ODDS 0 +#define ITEM_COFFEE_MACHINE_ODDS 4 + // Cantidad de objetos simultaneos #define MAX_ITEMS 5 @@ -324,6 +333,7 @@ const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2; #define INSTRUCTIONS_COUNTER 600 #define DEATH_COUNTER 350 #define SHAKE_COUNTER 10 +#define HELP_COUNTER 1000 // Colores const color_t bgColor = {0x27, 0x27, 0x36}; diff --git a/source/game.cpp b/source/game.cpp index e2430f7..b8bfbc1 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -219,6 +219,7 @@ Game::~Game() JA_DeleteSound(mSoundBubble4); JA_DeleteSound(mSoundClock); JA_DeleteSound(mSoundPowerBall); + JA_DeleteSound(mSoundCollision); JA_DeleteMusic(mMusicPlaying); } @@ -253,7 +254,7 @@ void Game::init() mMenaceThreshold = 0; mScore = 0; mHiScoreAchieved = false; - mCurrentStage = 9; + mCurrentStage = 0; mStageBitmapCounter = STAGE_COUNTER; mDeathCounter = DEATH_COUNTER; mExplosionTime = false; @@ -269,7 +270,18 @@ void Game::init() mEffect.flash = false; mEffect.shake = false; mEffect.shakeCounter = SHAKE_COUNTER; + mHelper.needCoffee = false; + mHelper.needCoffeeMachine = false; + mHelper.needPowerBall = false; + mHelper.counter = HELP_COUNTER; + mHelper.itemPoints1Odds = ITEM_POINTS_1_DISK_ODDS; + mHelper.itemPoints2Odds = ITEM_POINTS_2_GAVINA_ODDS; + mHelper.itemPoints3Odds = ITEM_POINTS_3_PACMAR_ODDS; + mHelper.itemClockOdds = ITEM_CLOCK_ODDS; + mHelper.itemCoffeeOdds = ITEM_COFFEE_ODDS; + mHelper.itemCoffeeMachineOdds = ITEM_COFFEE_MACHINE_ODDS; mPowerBallEnabled = false; + mCoffeeMachineEnabled = false; mPostFade = 0; if (mDemo.enabled) @@ -468,6 +480,7 @@ bool Game::loadMedia() mSoundPlayerCollision = JA_LoadSound(mFileList[19].c_str()); mSoundPowerBall = JA_LoadSound(mFileList[23].c_str()); mSoundStageChange = JA_LoadSound(mFileList[20].c_str()); + mSoundCollision = JA_LoadSound(mFileList[21].c_str()); // Musicas mMusicPlaying = JA_LoadMusic(mFileList[4].c_str()); @@ -1617,10 +1630,14 @@ void Game::updateDeath() } // Animación - if ((mDeathCounter / 5) % 2 == 0) - mSmartSprite[mDeathIndex]->setSpriteClip(0, 0, 24, 24); - else - mSmartSprite[mDeathIndex]->setSpriteClip(24, 0, 24, 24); + if ((mDeathCounter / 5) % 4 == 0) + mSmartSprite[mDeathIndex]->setSpriteClip(24 * 0, 24, 24, 24); + else if ((mDeathCounter / 5) % 4 == 1) + mSmartSprite[mDeathIndex]->setSpriteClip(24 * 1, 24, 24, 24); + else if ((mDeathCounter / 5) % 4 == 2) + mSmartSprite[mDeathIndex]->setSpriteClip(24 * 2, 24, 24, 24); + else if ((mDeathCounter / 5) % 4 == 3) + mSmartSprite[mDeathIndex]->setSpriteClip(24 * 3, 24, 24, 24); // Rebote en los laterales if (mSmartSprite[mDeathIndex]->getVelX() > 0) @@ -2026,6 +2043,7 @@ void Game::checkPlayerItemCollision() case ITEM_COFFEE_MACHINE: mPlayer->setPowerUp(true); JA_PlaySound(mSoundItemPickup); + mCoffeeMachineEnabled = false; break; default: @@ -2055,7 +2073,10 @@ void Game::checkBulletBalloonCollision() if ((droppeditem != NO_KIND) && !(mDemo.enabled) && !(mDemo.recording)) { createItem(mBalloon[i]->getPosX(), mBalloon[i]->getPosY(), droppeditem); - JA_PlaySound(mSoundItemDrop); + if (droppeditem != ITEM_COFFEE_MACHINE) + JA_PlaySound(mSoundItemDrop); + else + mCoffeeMachineEnabled = true; } break; } @@ -2105,7 +2126,11 @@ void Game::createBullet(int x, int y, Uint8 kind, bool poweredUp) void Game::updateItems() { for (int i = 0; i < MAX_ITEMS; i++) - mItem[i]->update(); + if (mItem[i]->update() == 1) + { + JA_PlaySound(mSoundCollision); + mEffect.shake = true; + } } // Pinta los items activos @@ -2135,39 +2160,56 @@ void Game::resetItems() // Devuelve un item en función del azar Uint8 Game::dropItem() { - if (mPlayer->isPowerUp()) + /*if (mPlayer->isPowerUp() || (mCoffeeMachineEnabled)) return NO_KIND; else - return ITEM_COFFEE_MACHINE; + return ITEM_COFFEE_MACHINE;*/ - const Uint8 luckyNumber = rand() % 99; + const Uint8 luckyNumber = rand() % 100; const Uint8 item = rand() % 6; switch (item) { case 0: - if (luckyNumber < 10) + if (luckyNumber < mHelper.itemPoints1Odds) return ITEM_POINTS_1_DISK; break; case 1: - if (luckyNumber < 6) + if (luckyNumber < mHelper.itemPoints2Odds) return ITEM_POINTS_2_GAVINA; break; case 2: - if (luckyNumber < 3) + if (luckyNumber < mHelper.itemPoints3Odds) return ITEM_POINTS_3_PACMAR; break; case 3: - if (luckyNumber < 5) + if (luckyNumber < mHelper.itemClockOdds) return ITEM_CLOCK; break; case 4: - if (luckyNumber < 5) + if (luckyNumber < mHelper.itemCoffeeOdds) + { + mHelper.itemCoffeeOdds = ITEM_COFFEE_ODDS; return ITEM_COFFEE; + } + else + { + if (mHelper.needCoffee) + mHelper.itemCoffeeOdds++; + } break; case 5: - if (luckyNumber < 4) - return ITEM_COFFEE_MACHINE; + if (luckyNumber < mHelper.itemCoffeeMachineOdds) + { + mHelper.itemCoffeeMachineOdds = ITEM_COFFEE_MACHINE_ODDS; + if ((!mCoffeeMachineEnabled) && (mHelper.needCoffeeMachine)) + return ITEM_COFFEE_MACHINE; + } + else + { + if (mHelper.needCoffeeMachine) + mHelper.itemCoffeeMachineOdds++; + } break; default: break; @@ -2217,7 +2259,10 @@ void Game::updateShakeEffect() if (mEffect.shakeCounter > 0) mEffect.shakeCounter--; else + { mEffect.shake = false; + mEffect.shakeCounter = SHAKE_COUNTER; + } } } @@ -2464,6 +2509,9 @@ void Game::updatePlayField() updateEnemyDeployCounter(); updateShakeEffect(); + // Actualiza el ayudante + updateHelper(); + // Comprueba las colisiones entre globos y balas checkBulletBalloonCollision(); @@ -2512,7 +2560,7 @@ void Game::updateBackground() // Dibuja el fondo void Game::renderBackground() { - const float gradientNumber = std::min(((float)mBalloonsPopped / 900.0f), 3.0f); + const float gradientNumber = std::min(((float)mBalloonsPopped / 1000.0f), 3.0f); const float percent = gradientNumber - (int)gradientNumber; const int alpha = std::max((255 - (int)(255 * percent)), 0); @@ -3212,4 +3260,27 @@ void Game::updateGameCompleted() if (mGameCompletedCounter == 500) mSection.subsection = GAME_SECTION_GAMEOVER; +} + +// Actualiza las variables de ayuda +void Game::updateHelper() +{ + // Solo ofrece ayuda cuando la amenaza o la velocidad es elevada + if (mMenaceCurrent > 15) + { + if (mPlayer->getCoffees() == 0) + mHelper.needCoffee = true; + else + mHelper.needCoffee = false; + + if (!mPlayer->isPowerUp()) + mHelper.needCoffeeMachine = true; + else + mHelper.needCoffeeMachine = false; + } + else + { + mHelper.needCoffee = false; + mHelper.needCoffeeMachine = false; + } } \ No newline at end of file diff --git a/source/game.h b/source/game.h index ce4f808..a2797e5 100644 --- a/source/game.h +++ b/source/game.h @@ -65,6 +65,20 @@ private: Uint8 shakeCounter; // Contador para medir el tiempo que dura el efecto }; + struct helper_t + { + bool needCoffee; // Indica si se necesitan cafes + bool needCoffeeMachine; // Indica si se necesita PowerUp + bool needPowerBall; // Indica si se necesita una PowerBall + int counter; // Contador para no dar ayudas consecutivas + int itemPoints1Odds; // Probabilidad de aparición del objeto + int itemPoints2Odds; // Probabilidad de aparición del objeto + int itemPoints3Odds; // Probabilidad de aparición del objeto + int itemClockOdds; // Probabilidad de aparición del objeto + int itemCoffeeOdds; // Probabilidad de aparición del objeto + int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto + }; + SDL_Renderer *mRenderer; // El renderizador de la ventana std::string *mFileList; // Lista de ficheros con los recursos std::string *mTextStrings; // Vector con los textos del juego @@ -126,6 +140,7 @@ private: JA_Sound mSoundBubble4; // Sonido para cuando el jugador muere JA_Sound mSoundClock; // Sonido para cuando se detiene el tiempo con el item reloj JA_Sound mSoundPowerBall; // Sonido para cuando se explota una Power Ball + JA_Sound mSoundCollision; // Sonido para cuando la máquina de café toca el suelo JA_Music mMusicPlaying; // Musica de fondo @@ -158,7 +173,9 @@ private: Uint8 mEnemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero float mEnemySpeed; // Velocidad a la que se mueven los enemigos effect_t mEffect; // Variable para gestionar los efectos visuales + helper_t mHelper; // Variable para gestionar las ayudas bool mPowerBallEnabled; // Indica si hay una powerball ya activa + bool mCoffeeMachineEnabled; // Indica si hay una máquina de café en el terreno de juego Uint8 mPostFade; // Qué hacer al acabar el fade float mSin[360]; // Vector con los valores del seno para 360 grados bool mGameCompleted; // Indica si se ha completado la partida, llegando al final de la ultima pantalla @@ -471,6 +488,9 @@ public: // Actualiza el tramo final de juego, una vez completado void updateGameCompleted(); + + // Actualiza las variables de ayuda + void updateHelper(); }; #endif diff --git a/source/item.cpp b/source/item.cpp index 1242161..181463d 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -29,6 +29,7 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer * mVelY = -4.0f; mAccelX = 0.0f; mAccelY = 0.2f; + mStatus = 0; mCollider.r = mWidth / 2; shiftColliders(); @@ -83,7 +84,8 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer * case ITEM_COFFEE_MACHINE: mWidth = 32; mHeight = 32; - mPosX = (rand() % (PLAY_AREA_WIDTH - mWidth - 3)) + 3; + //mPosX = (rand() % (PLAY_AREA_WIDTH - mWidth - 3)) + 3; + mPosX = (((int)x + (PLAY_AREA_WIDTH / 2)) % (PLAY_AREA_WIDTH - mWidth)); mPosY = PLAY_AREA_TOP - mHeight; mVelX = 0.0f; mVelY = -2.0f; @@ -142,6 +144,8 @@ void Item::render() // Actualiza la posición y estados del globo void Item::move() { + mStatus = 0; + // Calcula la nueva posición mPosX += mVelX; mPosY += mVelY; @@ -182,6 +186,7 @@ void Item::move() mAccelX = 0; mAccelY = 0; mPosY = PLAY_AREA_BOTTOM - mHeight; + if (mClass == ITEM_COFFEE_MACHINE) mStatus = 1; } // Actualiza la posición del sprite @@ -196,7 +201,7 @@ void Item::erase() } // Actualiza el objeto a su posicion, animación y controla los contadores -void Item::update() +int Item::update() { if (mEnabled) { @@ -206,6 +211,8 @@ void Item::update() updateTimeToLive(); checkTimeToLive(); } + + return mStatus; } // Actualiza el contador diff --git a/source/item.h b/source/item.h index 0c38a48..0da7b0c 100644 --- a/source/item.h +++ b/source/item.h @@ -9,6 +9,26 @@ // Clase AnimatedSprite class Item { +private: + float mPosX; // Posición X del objeto + float mPosY; // Posición Y del objeto + Uint8 mWidth; // Ancho del objeto + Uint8 mHeight; // Alto del objeto + float mVelX; // Velocidad en el eje X + float mVelY; // Velocidad en el eje Y + float mAccelX; // Aceleración en el eje X + float mAccelY; // Aceleración en el eje Y + int mStatus; // Contiene mensajes de estado + + AnimatedSprite *mSprite; // Sprite con los graficos del objeto + + Uint8 mClass; // Especifica el tipo de objeto que es + bool mEnabled; // Especifica si el objeto está habilitado + circle_t mCollider; // Circulo de colisión del objeto + + // Alinea el circulo de colisión con la posición del objeto + void shiftColliders(); + public: // Constructor Item(); @@ -17,7 +37,7 @@ public: ~Item(); // Iniciador - void init(Uint8 value, float x, float y, LTexture* texture, SDL_Renderer *renderer); + void init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *renderer); // Centra el objeto en la posición X void allignTo(int x); @@ -32,7 +52,7 @@ public: void erase(); // Actualiza al objeto a su posicion, animación y controla los contadores - void update(); + int update(); // Actualiza el contador void updateTimeToLive(); @@ -64,40 +84,8 @@ public: // Obtiene el circulo de colisión circle_t &getCollider(); - // Temporizador con el tiempo que el objeto está presente + // Temporizador con el tiempo que el objeto está presente Uint16 mTimeToLive; - -private: - // Posición X,Y del objeto - float mPosX; - float mPosY; - - // Alto y ancho del objeto - Uint8 mWidth; - Uint8 mHeight; - - // Variables para controlar la velocidad del objeto - float mVelX; - float mVelY; - - // Aceleración - float mAccelX; - float mAccelY; - - // Sprite con los graficos del objeto - AnimatedSprite *mSprite; - - // Especifica el tipo de objeto que es - Uint8 mClass; - - // Especifica si está habilitado el objeto - bool mEnabled; - - // Circulo de colisión del objeto - circle_t mCollider; - - // Alinea el circulo de colisión con la posición del objeto - void shiftColliders(); }; #endif diff --git a/source/lang.h b/source/lang.h index 621da69..f0754d1 100644 --- a/source/lang.h +++ b/source/lang.h @@ -268,7 +268,7 @@ const std::string gTextStrings[MAX_TEXT_STRINGS][3] = // 50 - TEXTO DE COMPLETAR EL JUEGO {"FELICIDADES!!", "FELICITATS!!", - "CONGRATULATIONS!!"}, + "NICE!!"}, };