diff --git a/.gitignore b/.gitignore index e499348..6da53d7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ thumbs.db *score.bin coffee_crisis* debug.txt -cppcheck-result* \ No newline at end of file +cppcheck-result* +desktop.ini diff --git a/data/gfx/tabe/tabe.png b/data/gfx/tabe/tabe.png index f858300..d168a88 100644 Binary files a/data/gfx/tabe/tabe.png and b/data/gfx/tabe/tabe.png differ diff --git a/data/sound/tabe.wav b/data/sound/tabe.wav new file mode 100644 index 0000000..242a32c Binary files /dev/null and b/data/sound/tabe.wav differ diff --git a/data/sound/voice_get_ready.wav b/data/sound/voice_get_ready.wav new file mode 100644 index 0000000..0453f0a Binary files /dev/null and b/data/sound/voice_get_ready.wav differ diff --git a/source/director.cpp b/source/director.cpp index 0028988..e092c67 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -54,7 +54,7 @@ Director::Director(int argc, const char *argv[]) section::name = section::Name::GAME; section::options = section::Options::GAME_PLAY_1P; #elif DEBUG - section::name = section::Name::LOGO; + section::name = section::Name::GAME; #else // NORMAL GAME section::name = section::Name::LOGO; section::attract_mode = section::AttractMode::TITLE_TO_DEMO; @@ -409,6 +409,8 @@ void Director::setFileList() Asset::get()->add(prefix + "/data/sound/voice_coffee.wav", AssetType::SOUND); Asset::get()->add(prefix + "/data/sound/voice_power_up.wav", AssetType::SOUND); Asset::get()->add(prefix + "/data/sound/voice_no.wav", AssetType::SOUND); + Asset::get()->add(prefix + "/data/sound/voice_get_ready.wav", AssetType::SOUND); + Asset::get()->add(prefix + "/data/sound/tabe.wav", AssetType::SOUND); // Shaders Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA); diff --git a/source/game.cpp b/source/game.cpp index d63101b..dc76e09 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -274,7 +274,7 @@ void Game::updateStage() std::vector paths = {paths_.at(2), paths_.at(3)}; if (Stage::number == 9) { - createMessage(paths, Resource::get()->getTexture("last_stage")); + createMessage(paths, Resource::get()->getTexture("game_text_last_stage")); } else { @@ -301,8 +301,8 @@ void Game::updateFadeInState() { balloon_manager_->createTwoBigBalloons(); evaluateAndSetMenace(); - createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("get_ready")); - JA_PlaySound(Resource::get()->getSound("stage_change.wav")); + createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("game_text_get_ready")); + JA_PlaySound(Resource::get()->getSound("voice_get_ready.wav")); } } } @@ -317,7 +317,7 @@ void Game::updateGameOverState() { if (game_over_counter_ == GAME_OVER_COUNTER_) { - createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_over")); + createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_game_over")); JA_FadeOutMusic(1000); balloon_manager_->setSounds(true); } @@ -365,8 +365,8 @@ void Game::updateCompletedState() // Muestra el mensaje de felicitación y da los puntos a los jugadores if (game_completed_counter_ == 200) { - createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("congratulations")); - createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("1000000_points")); + createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("game_text_congratulations")); + createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("game_text_1000000_points")); for (auto &player : players_) if (player->isPlaying()) @@ -943,13 +943,14 @@ void Game::fillCanvas() background_->render(); renderItems(); renderSmartSprites(); - balloon_manager_->render(); tabe_->render(); + balloon_manager_->render(); renderBullets(); renderPathSprites(); renderPlayers(); - // dbg_print(0, 40, std::to_string(menace_current_).c_str(), 255, 0, 0); - // dbg_print(0, 50, std::to_string(menace_threshold_).c_str(), 255, 0, 0); + + auto sprite = std::make_unique(Resource::get()->getTexture("game_text_game_over")); + sprite->render(); // Deja el renderizador apuntando donde estaba SDL_SetRenderTarget(renderer_, temp); @@ -1023,7 +1024,7 @@ void Game::initPaths() { // Recorrido para el texto de "Get Ready!" (0,1) { - const auto &texture = Resource::get()->getTexture("get_ready"); + const auto &texture = Resource::get()->getTexture("game_text_get_ready"); const auto w = texture->getWidth(); const int x0 = -w; const int x1 = param.game.play_area.center_x - w / 2; @@ -1035,7 +1036,7 @@ void Game::initPaths() // Recorrido para el texto de "Last Stage!" o de "X stages left" o "Game Over" (2,3) { - const auto &texture = Resource::get()->getTexture("last_stage"); + const auto &texture = Resource::get()->getTexture("game_text_last_stage"); const auto h = texture->getHeight(); const int y0 = param.game.play_area.rect.h - h; const int y1 = param.game.play_area.center_y - h / 2; @@ -1047,7 +1048,7 @@ void Game::initPaths() // Recorrido para el texto de "Congratulations!!" (3,4) { - const auto &texture = Resource::get()->getTexture("congratulations"); + const auto &texture = Resource::get()->getTexture("game_text_congratulations"); const auto w = texture->getWidth(); const auto h = texture->getHeight(); const int x0 = -w; @@ -1060,7 +1061,7 @@ void Game::initPaths() // Recorrido para el texto de "1.000.000 points!" (5,6) { - const auto &texture = Resource::get()->getTexture("1000000_points"); + const auto &texture = Resource::get()->getTexture("game_text_1000000_points"); const auto w = texture->getWidth(); const auto h = texture->getHeight(); const int x0 = param.game.play_area.rect.w; @@ -1198,8 +1199,7 @@ void Game::checkEvents() } case SDLK_6: // Crea un mensaje { - createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("congratulations")); - createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("1000000_points")); + createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_congratulations")); break; } case SDLK_7: // Flash diff --git a/source/jail_audio.cpp b/source/jail_audio.cpp index be7031b..76592df 100644 --- a/source/jail_audio.cpp +++ b/source/jail_audio.cpp @@ -4,7 +4,7 @@ #include #include -#define JA_MAX_SIMULTANEOUS_CHANNELS 5 +#define JA_MAX_SIMULTANEOUS_CHANNELS 20 struct JA_Sound_t { Uint32 length {0}; diff --git a/source/resource.cpp b/source/resource.cpp index b60a051..f63aa61 100644 --- a/source/resource.cpp +++ b/source/resource.cpp @@ -290,7 +290,7 @@ void Resource::createTextures() NameAndText("game_text_powerup", lang::getText(117)), NameAndText("game_text_one_hit", lang::getText(118)), NameAndText("game_text_stop", lang::getText(119)), - NameAndText("1000000_points", lang::getText(76))}; + NameAndText("game_text_1000000_points", lang::getText(76))}; auto text = getText("04b_25"); for (const auto &s : strings) @@ -301,10 +301,10 @@ void Resource::createTextures() // Tamaño doble std::vector strings2X = { - NameAndText("get_ready", lang::getText(75)), - NameAndText("last_stage", lang::getText(79)), - NameAndText("congratulations", lang::getText(50)), - NameAndText("game_over", "Game Over")}; + NameAndText("game_text_get_ready", lang::getText(75)), + NameAndText("game_text_last_stage", lang::getText(79)), + NameAndText("game_text_congratulations", lang::getText(50)), + NameAndText("game_text_game_over", "Game Over")}; auto text2 = getText("04b_25_2x"); for (const auto &s : strings2X) diff --git a/source/tabe.cpp b/source/tabe.cpp index a870125..6f59316 100644 --- a/source/tabe.cpp +++ b/source/tabe.cpp @@ -1,13 +1,12 @@ #include "tabe.h" #include "resource.h" #include "param.h" +#include "jail_audio.h" #include // Constructor Tabe::Tabe() - : sprite_(std::make_unique(Resource::get()->getTexture("tabe.png"), Resource::get()->getAnimation("tabe.ani"))) -{ -} + : sprite_(std::make_unique(Resource::get()->getTexture("tabe.png"), Resource::get()->getAnimation("tabe.ani"))) {} // Actualiza la lógica void Tabe::update() @@ -31,25 +30,116 @@ void Tabe::render() // Mueve el objeto void Tabe::move() { + const int x = static_cast(x_); + speed_ += accel_; x_ += speed_; - const float min_x = param.game.game_area.rect.x; - const float max_x = param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_; - if (x_ < min_x || x_ > max_x) + fly_distance_ -= std::abs(x - static_cast(x_)); + + // Comprueba si sale por los bordes + const float min_x = param.game.game_area.rect.x - WIDTH_; + const float max_x = param.game.game_area.rect.x + param.game.game_area.rect.w; + switch (destiny_) { - x_ = std::clamp(x_, min_x, max_x); - speed_ = -speed_; - sprite_->setFlip(speed_ > 0.0f ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE); + case TabeDirection::TO_THE_LEFT: + { + if (x_ < min_x) + { + enabled_ = false; + } + if (x_ > param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_ && direction_ == TabeDirection::TO_THE_RIGHT) + { + setRandomFlyPath(TabeDirection::TO_THE_LEFT, 80); + x_ = param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_; + } + break; } + + case TabeDirection::TO_THE_RIGHT: + { + if (x_ > max_x) + { + enabled_ = false; + } + if (x_ < param.game.game_area.rect.x && direction_ == TabeDirection::TO_THE_LEFT) + { + setRandomFlyPath(TabeDirection::TO_THE_RIGHT, 80); + x_ = param.game.game_area.rect.x; + } + break; + } + default: + break; + } + + if (fly_distance_ <= 0) + { + if (waiting_counter_ > 0) + { + accel_ = speed_ = 0.0f; + --waiting_counter_; + } + else + { + constexpr int CHOICES = 4; + const TabeDirection left[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT}; + const TabeDirection right[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT}; + const TabeDirection direction = destiny_ == TabeDirection::TO_THE_LEFT ? left[rand() % CHOICES] : right[rand() % CHOICES]; + setRandomFlyPath(direction, 20 + rand() % 40); + } + } + shiftSprite(); } // Habilita el objeto void Tabe::enable() { - enabled_ = true; - speed_ = 5.0f; - x_ = 50.0f; - y_ = 20.0f; - sprite_->setFlip(speed_ > 0.0f ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE); - shiftSprite(); + if (!enabled_) + { + enabled_ = true; + y_ = 20.0f; + + // Establece una dirección aleatoria + destiny_ = direction_ = rand() % 2 == 0 ? TabeDirection::TO_THE_LEFT : TabeDirection::TO_THE_RIGHT; + + // Establece la posición inicial + x_ = (direction_ == TabeDirection::TO_THE_LEFT) ? param.game.game_area.rect.x + param.game.game_area.rect.w : param.game.game_area.rect.x - WIDTH_; + + // Crea una ruta de vuelo + setRandomFlyPath(direction_, 60); + shiftSprite(); + } +} + +// Establece un vuelo aleatorio +void Tabe::setRandomFlyPath(TabeDirection direction, int lenght) +{ + direction_ = direction; + fly_distance_ = lenght; + waiting_counter_ = 5 + rand() % 15; + JA_PlaySound(Resource::get()->getSound("tabe.wav")); + + constexpr float SPEED = 2.0f; + + switch (direction) + { + case TabeDirection::TO_THE_LEFT: + { + speed_ = -1.0f * SPEED; + accel_ = -1.0f * (1 + rand() % 10) / 30.0f; + sprite_->setFlip(SDL_FLIP_NONE); + break; + } + + case TabeDirection::TO_THE_RIGHT: + { + speed_ = SPEED; + accel_ = (1 + rand() % 10) / 30.0f; + sprite_->setFlip(SDL_FLIP_HORIZONTAL); + break; + } + + default: + break; + } } \ No newline at end of file diff --git a/source/tabe.h b/source/tabe.h index 56d3ffb..0ece92a 100644 --- a/source/tabe.h +++ b/source/tabe.h @@ -3,6 +3,12 @@ #include "animated_sprite.h" #include +enum class TabeDirection : int +{ + TO_THE_LEFT = 0, + TO_THE_RIGHT = 1, +}; + // Clase Tabe class Tabe { @@ -15,10 +21,15 @@ private: std::unique_ptr sprite_; // Sprite con los graficos y animaciones // Variables - float x_; // Posición del objeto - float y_; // Posición del objeto - float speed_; // Velocidad de movimiento del objeto - bool enabled_ = false; // Indica si el objeto está activo + float x_ = 0; // Posición del objeto + float y_ = 0; // Posición del objeto + float speed_ = 0.0f; // Velocidad de movimiento del objeto + float accel_ = 0.0f; // Aceleración del objeto + int fly_distance_ = 0; // Distancia de vuelo + int waiting_counter_ = 0; // Tiempo que pasa quieto el objeto + bool enabled_ = false; // Indica si el objeto está activo + TabeDirection direction_; // Dirección del objeto + TabeDirection destiny_; // Destino del objeto // Mueve el objeto void move(); @@ -26,6 +37,9 @@ private: // Actualiza la posición del sprite void shiftSprite() { sprite_->setPos(x_, y_); } + // Establece un vuelo aleatorio + void setRandomFlyPath(TabeDirection direction, int lenght); + public: // Constructor Tabe();