diff --git a/data/music/credits.ogg b/data/music/credits.ogg new file mode 100644 index 0000000..3e159ca Binary files /dev/null and b/data/music/credits.ogg differ diff --git a/source/balloon.cpp b/source/balloon.cpp index 3af74b6..dd0b1df 100644 --- a/source/balloon.cpp +++ b/source/balloon.cpp @@ -7,7 +7,7 @@ #include "texture.h" // Para Texture // Constructor -Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr texture, const std::vector &animation) +Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, SDL_Rect play_area, std::shared_ptr texture, const std::vector &animation) : sprite_(std::make_unique(texture, animation)), x_(x), y_(y), @@ -19,7 +19,8 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel creation_counter_ini_(creation_timer), type_(type), size_(size), - speed_(speed) + speed_(speed), + play_area_(play_area) { switch (type_) { @@ -91,8 +92,8 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel void Balloon::alignTo(int x) { x_ = static_cast(x - (w_ / 2)); - const int min_x = param.game.play_area.rect.x; - const int max_x = param.game.play_area.rect.w - w_; + const int min_x = play_area_.x; + const int max_x = play_area_.w - w_; x_ = std::clamp(x_, static_cast(min_x), static_cast(max_x)); } @@ -149,8 +150,8 @@ void Balloon::move() // Colisión en las partes laterales de la zona de juego const int clip = 2; - const float min_x = param.game.play_area.rect.x - clip; - const float max_x = param.game.play_area.rect.w - w_ + clip; + const float min_x = play_area_.x - clip; + const float max_x = play_area_.w - w_ + clip; if (x_ < min_x || x_ > max_x) { x_ = std::clamp(x_, min_x, max_x); @@ -172,7 +173,7 @@ void Balloon::move() // Colisión en la parte superior de la zona de juego excepto para la PowerBall if (type_ != BalloonType::POWERBALL) { - const int min_y = param.game.play_area.rect.y; + const int min_y = play_area_.y; if (y_ < min_y) { y_ = min_y; @@ -182,7 +183,7 @@ void Balloon::move() } // Colisión en la parte inferior de la zona de juego - const int max_y = param.game.play_area.rect.h - h_; + const int max_y = play_area_.h - h_; if (y_ > max_y) { y_ = max_y; @@ -254,8 +255,8 @@ void Balloon::updateState() x_ += vx_; // Comprueba no se salga por los laterales - const int min_x = param.game.play_area.rect.x; - const int max_x = param.game.play_area.rect.w - w_; + const int min_x = play_area_.x; + const int max_x = play_area_.w - w_; if (x_ < min_x || x_ > max_x) { diff --git a/source/balloon.h b/source/balloon.h index b66aa88..e92eed2 100644 --- a/source/balloon.h +++ b/source/balloon.h @@ -111,6 +111,7 @@ private: float travel_y_ = 1.0f; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad float speed_; // Velocidad a la que se mueven los globos Uint8 power_; // Cantidad de poder que alberga el globo + SDL_Rect play_area_; // Zona por donde se puede mover el globo // Alinea el circulo de colisión con la posición del objeto globo void shiftColliders(); @@ -138,7 +139,17 @@ private: public: // Constructor - Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr texture, const std::vector &animation); + Balloon( + float x, + float y, + BalloonType type, + BalloonSize size, + float vel_x, + float speed, + Uint16 creation_timer, + SDL_Rect play_area, + std::shared_ptr texture, + const std::vector &animation); // Destructor ~Balloon() = default; diff --git a/source/balloon_manager.cpp b/source/balloon_manager.cpp index 9988018..0ec9b14 100644 --- a/source/balloon_manager.cpp +++ b/source/balloon_manager.cpp @@ -150,7 +150,7 @@ int BalloonManager::calculateScreenPower() std::shared_ptr BalloonManager::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer) { const int index = static_cast(size); - balloons_.emplace_back(std::make_shared(x, y, type, size, velx, speed, creation_timer, balloon_textures_.at(index), balloon_animations_.at(index))); + balloons_.emplace_back(std::make_shared(x, y, type, size, velx, speed, creation_timer, play_area_, balloon_textures_.at(index), balloon_animations_.at(index))); return balloons_.back(); } @@ -188,7 +188,7 @@ void BalloonManager::createPowerBall() const int x[values] = {left, left, center, center, right, right}; const float vx[values] = {BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE}; - balloons_.emplace_back(std::make_unique(x[luck], pos_y, BalloonType::POWERBALL, BalloonSize::SIZE4, vx[luck], balloon_speed_, creation_time, balloon_textures_[4], balloon_animations_[4])); + balloons_.emplace_back(std::make_unique(x[luck], pos_y, BalloonType::POWERBALL, BalloonSize::SIZE4, vx[luck], balloon_speed_, creation_time, play_area_, balloon_textures_[4], balloon_animations_[4])); power_ball_enabled_ = true; power_ball_counter_ = POWERBALL_COUNTER; diff --git a/source/balloon_manager.h b/source/balloon_manager.h index bf3e5b0..5cd9958 100644 --- a/source/balloon_manager.h +++ b/source/balloon_manager.h @@ -6,6 +6,7 @@ #include "balloon.h" // Para BALLOON_SPEED, Balloon #include "balloon_formations.h" // Para BalloonFormations #include "explosions.h" // Para Explosions +#include "param.h" class Texture; using Balloons = std::vector>; @@ -29,6 +30,7 @@ private: bool power_ball_enabled_ = false; // Indica si hay una powerball ya activa int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra int last_balloon_deploy_ = 0; // Guarda cual ha sido la última formación desplegada para no repetir; + SDL_Rect play_area_ = param.game.play_area.rect; // Zona por donde se moveran los globos // Inicializa void init(); @@ -110,4 +112,5 @@ public: // Setters void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; } void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); } + void setPlayArea(SDL_Rect play_area) { play_area_ = play_area; } }; \ No newline at end of file diff --git a/source/credits.cpp b/source/credits.cpp index c9cca36..326d4c7 100644 --- a/source/credits.cpp +++ b/source/credits.cpp @@ -5,19 +5,28 @@ #include "jail_audio.h" // Para JA_StopMusic #include "screen.h" // Para Screen #include "balloon_manager.h" // Para BalloonManager +#include "param.h" +#include "resource.h" +#include "text.h" // Constructor Credits::Credits() - : balloon_manager_(std::make_unique()) - + : balloon_manager_(std::make_unique()), + text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), + tiled_bg_(std::make_unique((SDL_Rect){0, 0, param.game.width, param.game.height}, TiledBGMode::DIAGONAL)) { section::name = section::Name::CREDITS; + balloon_manager_->setPlayArea(param.game.game_area.rect); balloon_manager_->createTwoBigBalloons(); + SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND); + fillTextTexture(); + JA_PlayMusic(Resource::get()->getMusic("credits.ogg")); } // Destructor Credits::~Credits() { + SDL_DestroyTexture(text_texture_); } // Bucle principal @@ -40,7 +49,9 @@ void Credits::update() if (SDL_GetTicks() - ticks_ > TICKS_SPEED) { ticks_ = SDL_GetTicks(); + tiled_bg_->update(); balloon_manager_->update(); + Screen::get()->update(); } } @@ -53,7 +64,9 @@ void Credits::render() // Limpia la pantalla Screen::get()->clean(); + tiled_bg_->render(); balloon_manager_->render(); + SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, nullptr, nullptr); // Vuelca el contenido del renderizador en pantalla Screen::get()->blit(); @@ -84,11 +97,74 @@ void Credits::checkInput() if (Input::get()->checkAnyButtonPressed()) { JA_StopMusic(); - section::name = section::Name::TITLE; - section::options = section::Options::TITLE_1; + section::name = section::Name::LOGO; return; } // Comprueba los inputs que se pueden introducir en cualquier sección del juego globalInputs::check(); +} + +// Crea la textura con el texto +void Credits::fillTextTexture() +{ + auto text = Resource::get()->getText("smb2"); + SDL_SetRenderTarget(Screen::get()->getRenderer(), text_texture_); + + SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0); + SDL_RenderClear(Screen::get()->getRenderer()); + + std::vector texts = { + "PROGRAMACIO I DISSENY", + "GRAFICS", + "MUSICA", + "SONS", + "JAILDESIGNER", + "JAILDOCTOR (INTRO)", + "ERIC MATYAS (SOUNDIMAGE.ORG)", + "WWW.THEMOTIONMONKEY.CO.UK", + "WWW.KENNEY.NL", + "JAILDOCTOR"}; + + const int space_post_title = 3 + text->getCharacterSize(); + const int space_pre_title = text->getCharacterSize() * 3; + const int texts_height = 1 * text->getCharacterSize() + 7 * space_post_title + 3 * space_pre_title; + + int y = (param.game.height - texts_height) / 2; + text->setPalette(1); + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(0), 1, no_color, 1, shdw_txt_color); + + text->setPalette(0); + y += space_post_title; + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(4), 1, no_color, 1, shdw_txt_color); + + y += space_pre_title; + text->setPalette(1); + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(1), 1, no_color, 1, shdw_txt_color); + text->setPalette(0); + y += space_post_title; + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(4), 1, no_color, 1, shdw_txt_color); + + y += space_pre_title; + text->setPalette(1); + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(2), 1, no_color, 1, shdw_txt_color); + text->setPalette(0); + + y += space_post_title; + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(5), 1, no_color, 1, shdw_txt_color); + y += space_post_title; + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(6), 1, no_color, 1, shdw_txt_color); + + y += space_pre_title; + text->setPalette(1); + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(3), 1, no_color, 1, shdw_txt_color); + text->setPalette(0); + y += space_post_title; + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(7), 1, no_color, 1, shdw_txt_color); + y += space_post_title; + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(8), 1, no_color, 1, shdw_txt_color); + y += space_post_title; + text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.width / 2, y, texts.at(9), 1, no_color, 1, shdw_txt_color); + + SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr); } \ No newline at end of file diff --git a/source/credits.h b/source/credits.h index feb7695..a0f9676 100644 --- a/source/credits.h +++ b/source/credits.h @@ -2,12 +2,16 @@ #include "SDL2/SDL.h" #include #include "balloon_manager.h" +#include "texture.h" +#include "tiled_bg.h" class Credits { private: // Objetos std::unique_ptr balloon_manager_; // Objeto para gestionar los globos + SDL_Texture *text_texture_; // Textura con el texto + std::unique_ptr tiled_bg_; // Objeto para dibujar el mosaico animado de fondo // Variables Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa @@ -24,6 +28,9 @@ private: // Comprueba las entradas void checkInput(); + // Crea la textura con el texto + void fillTextTexture(); + public: // Constructor Credits(); diff --git a/source/director.cpp b/source/director.cpp index 86dbedd..c577f41 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -362,6 +362,7 @@ void Director::setFileList() Asset::get()->add(prefix + "/data/music/intro.ogg", AssetType::MUSIC); Asset::get()->add(prefix + "/data/music/playing.ogg", AssetType::MUSIC); Asset::get()->add(prefix + "/data/music/title.ogg", AssetType::MUSIC); + Asset::get()->add(prefix + "/data/music/credits.ogg", AssetType::MUSIC); // Sonidos Asset::get()->add(prefix + "/data/sound/balloon.wav", AssetType::SOUND); diff --git a/source/instructions.cpp b/source/instructions.cpp index 8375744..5f0b238 100644 --- a/source/instructions.cpp +++ b/source/instructions.cpp @@ -30,10 +30,8 @@ Instructions::Instructions() tiled_bg_(std::make_unique((SDL_Rect){0, 0, param.game.width, param.game.height}, TiledBGMode::STATIC)), fade_(std::make_unique()) { - // Crea un backbuffer para el renderizador + // Configura las texturas SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); - - // Crea una textura para el texto fijo SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND); // Inicializa variables @@ -211,7 +209,9 @@ void Instructions::update() // Mantiene la música sonando if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) + { JA_PlayMusic(Resource::get()->getMusic("title.ogg")); + } // Actualiza el objeto screen Screen::get()->update(); diff --git a/source/player.cpp b/source/player.cpp index a6de8ee..c62e14b 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -164,7 +164,7 @@ void Player::move() pos_x_ += vel_x_; // Si el jugador abandona el area de juego por los laterales, restaura su posición - const float min_x = param.game.play_area.rect.x - 5; + const float min_x = play_area_.x - 5; const float max_x = play_area_.w + 5 - WIDTH_; pos_x_ = std::clamp(pos_x_, min_x, max_x); @@ -174,13 +174,13 @@ void Player::move() case PlayerState::DYING: { // Si el cadaver abandona el area de juego por los laterales lo hace rebotar - if ((player_sprite_->getPosX() < param.game.play_area.rect.x) || (player_sprite_->getPosX() + WIDTH_ > play_area_.w)) + if ((player_sprite_->getPosX() < play_area_.x) || (player_sprite_->getPosX() + WIDTH_ > play_area_.w)) { player_sprite_->setVelX(-player_sprite_->getVelX()); } // Si el cadaver toca el suelo cambia el estado - if (player_sprite_->getPosY() > param.game.play_area.rect.h - HEIGHT_) + if (player_sprite_->getPosY() > play_area_.h - HEIGHT_) { if (player_sprite_->getVelY() < 2.0f) { @@ -194,7 +194,7 @@ void Player::move() else { // Decrementa las velocidades de rebote - player_sprite_->setPosY(param.game.play_area.rect.h - HEIGHT_); + player_sprite_->setPosY(play_area_.h - HEIGHT_); player_sprite_->setVelY(player_sprite_->getVelY() * -0.5f); player_sprite_->setVelX(player_sprite_->getVelX() * 0.75f); } @@ -615,9 +615,13 @@ void Player::decEnterNameCounter() { enter_name_counter_ = param.game.enter_name_seconds; if (playing_state_ == PlayerState::ENTERING_NAME) + { setPlayingState(PlayerState::CONTINUE); + } else + { setPlayingState(PlayerState::LEAVING_SCREEN); + } } } @@ -625,7 +629,9 @@ void Player::decEnterNameCounter() int Player::getRecordNamePos() const { if (enter_name_) + { return enter_name_->getPosition(); + } return 0; } diff --git a/source/text.cpp b/source/text.cpp index dfef3d3..b8db3af 100644 --- a/source/text.cpp +++ b/source/text.cpp @@ -264,4 +264,13 @@ void Text::reLoadTexture() void Text::setFixedWidth(bool value) { fixed_width_ = value; +} + +// Establece una paleta +void Text::setPalette(int number) +{ + auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer()); + SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr); + sprite_->getTexture()->setPalette(number); + SDL_SetRenderTarget(Screen::get()->getRenderer(), temp); } \ No newline at end of file diff --git a/source/text.h b/source/text.h index 6eb8a87..baba6f1 100644 --- a/source/text.h +++ b/source/text.h @@ -78,4 +78,7 @@ public: // Establece si se usa un tamaño fijo de letra void setFixedWidth(bool value); + + // Establece una paleta + void setPalette(int number); }; \ No newline at end of file