From ba05eab79ec0df366ce3ed238fb5e139d48cd49a Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 29 Oct 2024 20:05:05 +0100 Subject: [PATCH] Reduida la dependencia de PathSprite a Sprite Treballant en els missatges de text que ixen durant la partida --- source/game.cpp | 91 +++++++++++++++++++----------------------- source/game.h | 12 +++--- source/path_sprite.cpp | 58 ++++++++++++++------------- source/path_sprite.h | 46 +++++++++++---------- source/resource.cpp | 13 +++++- source/text.cpp | 24 ++++++++--- source/text.h | 3 +- 7 files changed, 134 insertions(+), 113 deletions(-) diff --git a/source/game.cpp b/source/game.cpp index 4739176..3e83ca0 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -201,14 +201,6 @@ void Game::setResources() item_animations_.emplace_back(Resource::get()->getAnimation("item_coffee.ani")); item_animations_.emplace_back(Resource::get()->getAnimation("item_coffee_machine.ani")); } - - // Texto - { - text_ = std::make_unique(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt")); - text_nokia2_ = std::make_unique(Resource::get()->getTexture("nokia.png"), Resource::get()->getTextFile("nokia.txt")); - text_nokia2_big_ = std::make_unique(Resource::get()->getTexture("nokia.png"), Resource::get()->getTextFile("nokia.txt")); - text_04b_25_ = std::make_unique(Resource::get()->getTexture("04b_25.png"), Resource::get()->getTextFile("04b_25.txt")); - } } // Crea una formación de enemigos @@ -652,28 +644,28 @@ void Game::checkPlayerItemCollision(std::shared_ptr &player) { player->addScore(1000); const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[0]->getWidth()) / 2; - createPathSprite(x, game_text_textures_[0]); + createItemText(x, game_text_textures_[0]); break; } case ItemType::GAVINA: { player->addScore(2500); const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[1]->getWidth()) / 2; - createPathSprite(x, game_text_textures_[1]); + createItemText(x, game_text_textures_[1]); break; } case ItemType::PACMAR: { player->addScore(5000); const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[2]->getWidth()) / 2; - createPathSprite(x, game_text_textures_[2]); + createItemText(x, game_text_textures_[2]); break; } case ItemType::CLOCK: { enableTimeStopItem(); const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[5]->getWidth()) / 2; - createPathSprite(x, game_text_textures_[5]); + createItemText(x, game_text_textures_[5]); break; } case ItemType::COFFEE: @@ -682,13 +674,13 @@ void Game::checkPlayerItemCollision(std::shared_ptr &player) { player->addScore(5000); const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[2]->getWidth()) / 2; - createPathSprite(x, game_text_textures_[2]); + createItemText(x, game_text_textures_[2]); } else { player->giveExtraHit(); const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[4]->getWidth()) / 2; - createPathSprite(x, game_text_textures_[4]); + createItemText(x, game_text_textures_[4]); } break; } @@ -697,7 +689,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr &player) player->setPowerUp(); coffee_machine_enabled_ = false; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_[3]->getWidth()) / 2; - createPathSprite(x, game_text_textures_[3]); + createItemText(x, game_text_textures_[3]); break; } default: @@ -897,7 +889,7 @@ void Game::freeItems() } // Crea un objeto PathSprite -void Game::createPathSprite(int x, std::shared_ptr texture) +void Game::createItemText(int x, std::shared_ptr texture) { path_sprites_.emplace_back(std::make_unique(texture)); @@ -905,7 +897,7 @@ void Game::createPathSprite(int x, std::shared_ptr texture) const auto h = texture->getHeight(); const int y0 = param.game.play_area.rect.h - h; - const int y1 = 160; + const int y1 = 155; const int y2 = -h; // Ajusta para que no se dibuje fuera de pantalla @@ -920,6 +912,17 @@ void Game::createPathSprite(int x, std::shared_ptr texture) path_sprites_.back()->enable(); } +// Crea un objeto PathSprite +void Game::createMessage(std::vector paths, std::shared_ptr texture) +{ + path_sprites_.emplace_back(std::make_unique(texture)); + + // Inicializa + for (const auto &path : paths) + path_sprites_.back()->addPath(path); + path_sprites_.back()->enable(); +} + // Vacia el vector de smartsprites void Game::freeSmartSprites() { @@ -1286,8 +1289,11 @@ void Game::updateMenace() void Game::renderMessages() { // GetReady - if (counter_ < STAGE_COUNTER_ && !demo_.enabled) - text_nokia2_big_->write((int)get_ready_bitmap_path_[counter_], param.game.play_area.center_y - 8, lang::getText(75), -2); + if (counter_ == 10 && !demo_.enabled) + { // text_04b_25_->write2X((int)get_ready_bitmap_path_[counter_], param.game.play_area.center_y - 8, lang::getText(75), -2); + std::vector paths = {paths_.at(0), paths_.at(1)}; + createMessage(paths, Resource::get()->getTexture("get_ready")); + } // STAGE NUMBER if (stage_bitmap_counter_ < STAGE_COUNTER_) @@ -1309,14 +1315,14 @@ void Game::renderMessages() if (!game_completed_) { // Escribe el número de fases restantes - text_nokia2_big_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_], text, -2, no_color, 2, shdw_txt_color); + //text_04b_25_->write2X(param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_], text, -2); } else { // Escribe el texto de juego completado text = lang::getText(50); - text_nokia2_big_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_], text, -2, no_color, 1, shdw_txt_color); - text_nokia2_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_] + text_nokia2_big_->getCharacterSize() + 2, lang::getText(76), -1, no_color, 1, shdw_txt_color); + //text_nokia2_big_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_], text, -2, no_color, 1, shdw_txt_color); + //text_nokia2_->writeDX(TEXT_CENTER, param.game.play_area.center_x, stage_bitmap_path_[stage_bitmap_counter_] + text_nokia2_big_->getCharacterSize() + 2, lang::getText(76), -1, no_color, 1, shdw_txt_color); } } } @@ -1379,6 +1385,18 @@ int Game::calculateScreenPower() // Inicializa las variables que contienen puntos de ruta para mover objetos void Game::initPaths() { + // Recorrido para el texto de "Get Ready!" + const auto &texture = Resource::get()->getTexture("get_ready"); + const auto w = texture->getWidth(); + const auto h = texture->getHeight(); + + const int x0 = -w; + const int x1 = param.game.play_area.center_x - w / 2; + const int x2 = param.game.play_area.rect.w; + const int y = param.game.play_area.center_y - h / 2; + paths_.emplace_back(Path(createPath(x0, x1, PathType::HORIZONTAL, y, 80, easeOutQuint), 10)); + paths_.emplace_back(Path(createPath(x1, x2, PathType::HORIZONTAL, y, 80, easeInQuint), 0)); + // Vector con los valores del seno para 360 grados float sin[360]; for (int i = 0; i < 360; ++i) @@ -1404,33 +1422,6 @@ void Game::initPaths() int index = static_cast(((i - 149) * 1.8f) + 90) % 360; stage_bitmap_path_[i] = sin[index] * (center_point + 17) - 17; } - - // Letrero de GetReady - const auto size = text_nokia2_big_->lenght(lang::getText(75), -2); - - const float start1 = param.game.play_area.rect.x - size; - const float finish1 = param.game.play_area.center_x - (size / 2); - const float finish2 = param.game.play_area.rect.w; - - const float distance1 = finish1 - start1; - const float distance2 = finish2 - finish1; - - for (int i = 0; i < first_part; ++i) - { - get_ready_bitmap_path_[i] = sin[(int)(i * 1.8f)]; - get_ready_bitmap_path_[i] *= distance1; - get_ready_bitmap_path_[i] -= size; - } - - for (int i = first_part; i < second_part; ++i) - get_ready_bitmap_path_[i] = (int)finish1; - - for (int i = second_part; i < STAGE_COUNTER_; ++i) - { - get_ready_bitmap_path_[i] = sin[(int)((i - second_part) * 1.8f)]; - get_ready_bitmap_path_[i] *= distance2; - get_ready_bitmap_path_[i] += finish1; - } } // Actualiza el tramo final de juego, una vez completado @@ -1565,7 +1556,7 @@ void Game::checkEvents() case SDLK_5: // Crea un PathSprite { const int x = players_.at(0)->getPosX() + (players_.at(0)->getWidth() - game_text_textures_[3]->getWidth()) / 2; - createPathSprite(x, game_text_textures_.at(3)); + createItemText(x, game_text_textures_.at(3)); break; } default: diff --git a/source/game.h b/source/game.h index b2791b1..027ae16 100644 --- a/source/game.h +++ b/source/game.h @@ -10,6 +10,7 @@ #include "options.h" // Para Options, OptionsGame, options #include "player.h" // Para Player #include "utils.h" // Para Demo +#include "path_sprite.h" class Asset; // lines 12-12 class Background; // lines 13-13 class BalloonFormations; // lines 14-14 @@ -144,12 +145,8 @@ private: std::vector> balloon_animations_; // Vector con las animaciones de los globos std::vector> explosions_animations_; // Vector con las animaciones de las explosiones - std::unique_ptr text_; // Fuente para los textos del juego - std::unique_ptr text_04b_25_; // Fuente de texto grande - std::unique_ptr text_nokia2_; // Otra fuente de texto para mensajes - std::unique_ptr text_nokia2_big_; // Y la versión en grande - std::unique_ptr fade_; // Objeto para renderizar fades + std::vector paths_; // Vector con los recorridos precalculados almacenados // Variables HiScoreEntry hi_score_ = HiScoreEntry( @@ -304,7 +301,10 @@ private: void freeItems(); // Crea un objeto PathSprite - void createPathSprite(int x, std::shared_ptr texture); + void createItemText(int x, std::shared_ptr texture); + + // Crea un objeto PathSprite + void createMessage(std::vector paths, std::shared_ptr texture); // Vacia el vector de smartsprites void freeSmartSprites(); diff --git a/source/path_sprite.cpp b/source/path_sprite.cpp index a654d4c..53297d8 100644 --- a/source/path_sprite.cpp +++ b/source/path_sprite.cpp @@ -7,34 +7,8 @@ #include class Texture; // lines 3-3 -// Constructor -PathSprite::PathSprite(std::shared_ptr texture) - : AnimatedSprite(texture) {} - -// Actualiza la posición y comprueba si ha llegado a su destino -void PathSprite::update() -{ - if (enabled_) - { - moveThroughCurrentPath(); - goToNextPathOrDie(); - } -} - -// Añade un recorrido -void PathSprite::addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction, int waiting_counter) -{ - paths_.emplace_back(createPath(start, end, type, fixed_pos, steps, easingFunction), waiting_counter); -} - -// Añade un recorrido -void PathSprite::addPath(std::vector spots, int waiting_counter) -{ - paths_.emplace_back(std::move(spots), waiting_counter); -} - // Devuelve un vector con los puntos que conforman la ruta -std::vector PathSprite::createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction) +std::vector createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction) { std::vector v; v.reserve(steps); @@ -69,6 +43,34 @@ std::vector PathSprite::createPath(int start, int end, PathType type, return v; } +// Actualiza la posición y comprueba si ha llegado a su destino +void PathSprite::update() +{ + if (enabled_) + { + moveThroughCurrentPath(); + goToNextPathOrDie(); + } +} + +// Añade un recorrido +void PathSprite::addPath(Path path) +{ + paths_.emplace_back(path); +} + +// Añade un recorrido +void PathSprite::addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction, int waiting_counter) +{ + paths_.emplace_back(createPath(start, end, type, fixed_pos, steps, easingFunction), waiting_counter); +} + +// Añade un recorrido +void PathSprite::addPath(std::vector spots, int waiting_counter) +{ + paths_.emplace_back(std::move(spots), waiting_counter); +} + // Habilita el objeto void PathSprite::enable() { @@ -82,7 +84,7 @@ void PathSprite::moveThroughCurrentPath() // Establece la posición const auto &p = path.spots.at(path.counter); - MovingSprite::setPos(p.x, p.y); + setPosition(p); // Comprobar si ha terminado el recorrido if (!path.on_destination) diff --git a/source/path_sprite.h b/source/path_sprite.h index 393afb3..4a50f2e 100644 --- a/source/path_sprite.h +++ b/source/path_sprite.h @@ -1,7 +1,7 @@ #pragma once -#include // Para SDL_Point -#include // Para shared_ptr +#include // Para SDL_Point +#include // Para shared_ptr #include #include // Para vector #include "animated_sprite.h" // Para AnimatedSprite @@ -13,24 +13,27 @@ enum class PathType HORIZONTAL, }; +// Estructuras +struct Path +{ + std::vector spots; // Puntos por los que se desplazará el sprite + int waiting_counter; // Tiempo de espera una vez en el destino + bool on_destination = false; // Indica si ha llegado al destino + bool finished = false; // Indica si ha terminado de esperarse + int counter = 0; // Contador interno + + // Constructor + Path(const std::vector &spots_init, int waiting_counter_init) + : spots(spots_init), waiting_counter(waiting_counter_init) {} +}; + +// Devuelve un vector con los puntos que conforman la ruta +std::vector createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction); + // Clase PathSprite -class PathSprite : public AnimatedSprite +class PathSprite : public Sprite { private: - // Estructuras - struct Path - { - std::vector spots; // Puntos por los que se desplazará el sprite - int waiting_counter; // Tiempo de espera una vez en el destino - bool on_destination = false; // Indica si ha llegado al destino - bool finished = false; // Indica si ha terminado de esperarse - int counter = 0; // Contador interno - - // Constructor - Path(const std::vector &spots_init, int waiting_counter_init) - : spots(spots_init), waiting_counter(waiting_counter_init) {} - }; - // Variables bool finished_ = false; // Indica si ya ha terminado bool enabled_ = false; // Indica si el objeto está habilitado @@ -45,21 +48,20 @@ private: public: // Constructor - explicit PathSprite(std::shared_ptr texture); + explicit PathSprite(std::shared_ptr texture) + : Sprite(texture) {} // Destructor ~PathSprite() = default; // Actualiza la posición del sprite - void update() override; + void update(); // Añade un recorrido + void addPath(Path path); void addPath(std::vector spots, int waiting_counter); void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction, int waiting_counter); - // Devuelve un vector con los puntos que conforman la ruta - std::vector createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction); - // Habilita el objeto void enable(); diff --git a/source/resource.cpp b/source/resource.cpp index c38c544..9bca5e7 100644 --- a/source/resource.cpp +++ b/source/resource.cpp @@ -3,6 +3,7 @@ #include // Para basic_ostream, operator<<, endl, cout, cerr #include // Para runtime_error #include "asset.h" // Para Asset, AssetType +#include "lang.h" // Para lang #include "jail_audio.h" // Para JA_LoadMusic, JA_LoadSound #include "screen.h" // Para Screen #include "text.h" // Para Text @@ -250,7 +251,17 @@ void Resource::createTextures() std::cout << "\n>> CREATING TEXTURES" << std::endl; for (const auto &s : strings) { - textures_.emplace_back(ResourceTexture(s.name, text->writeToTexture(s.text, -2))); + textures_.emplace_back(ResourceTexture(s.name, text->writeToTexture(s.text, 1, -2))); + printWithDots("Texture : ", s.name, "[ DONE ]"); + } + + std::vector strings2X = { + NameAndText("get_ready", lang::getText(75)), + NameAndText("stages_remaining", "9 " + lang::getText(38))}; + + for (const auto &s : strings2X) + { + textures_.emplace_back(ResourceTexture(s.name, text->writeToTexture(s.text, 2, -2))); printWithDots("Texture : ", s.name, "[ DONE ]"); } } diff --git a/source/text.cpp b/source/text.cpp index 703c359..d2c019a 100644 --- a/source/text.cpp +++ b/source/text.cpp @@ -139,16 +139,30 @@ void Text::write(int x, int y, const std::string &text, int kerning, int lenght) } } +// Escribe texto en pantalla +void Text::write2X(int x, int y, const std::string &text, int kerning) +{ + int shift = 0; + for (size_t i = 0; i < text.length(); ++i) + { + auto index = static_cast(text[i]); + SDL_Rect rect = {offset_[index].x, offset_[index].y, box_width_, box_height_}; + sprite_->getTexture()->render(x + shift, y, &rect, 2.0f, 2.0f); + shift += (offset_[index].w + kerning) * 2; + } +} + // Escribe el texto en una textura -std::shared_ptr Text::writeToTexture(const std::string &text, int kerning) +std::shared_ptr Text::writeToTexture(const std::string &text, int zoom, int kerning) { auto renderer = Screen::get()->getRenderer(); auto texture = std::make_shared(renderer); - auto width = lenght(text, kerning); - texture->createBlank(width, box_height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET); - texture->setBlendMode(SDL_BLENDMODE_BLEND); + auto width = lenght(text, kerning) * zoom; + auto height = box_height_ * zoom; + texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET); + texture->setBlendMode(SDL_BLENDMODE_BLEND); texture->setAsRenderTarget(renderer); - write(0, 0, text, kerning); + zoom == 1 ? write(0, 0, text, kerning) : write2X(0, 0, text, kerning); return texture; } diff --git a/source/text.h b/source/text.h index ae22c45..6eb8a87 100644 --- a/source/text.h +++ b/source/text.h @@ -50,9 +50,10 @@ public: // Escribe el texto en pantalla void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1); + void write2X(int x, int y, const std::string &text, int kerning = 1); // Escribe el texto en una textura - std::shared_ptr writeToTexture(const std::string &text, int kerning = 1); + std::shared_ptr writeToTexture(const std::string &text, int zoom = 1, int kerning = 1); // Escribe el texto con colores void writeColored(int x, int y, const std::string &text, Color color, int kerning = 1, int lenght = -1);