From 1dd96cfaff3d3e96757b27b55da2d42d6c222900 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 27 Oct 2024 22:28:44 +0100 Subject: [PATCH] Completada la classe PathSprite --- source/game.cpp | 80 ++++++++++++++++++++++++----- source/game.h | 20 ++++++-- source/path_sprite.cpp | 110 ++++++++++++++++++++++++++++++++++++++++ source/path_sprite.h | 61 ++++++++++++++++++++++ source/smart_sprite.cpp | 1 + source/smart_sprite.h | 1 + 6 files changed, 257 insertions(+), 16 deletions(-) create mode 100644 source/path_sprite.cpp create mode 100644 source/path_sprite.h diff --git a/source/game.cpp b/source/game.cpp index 270fcdc..db0b29a 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -27,6 +27,7 @@ #include "manage_hiscore_table.h" // para ManageHiScoreTable #include "notifier.h" // para Notifier #include "param.h" // para param +#include "path_sprite.h" // para PathSprite #include "player.h" // para Player, PlayerStatus #include "resource.h" // para Resource #include "scoreboard.h" // para Scoreboard, ScoreboardMode, SCOREB... @@ -917,8 +918,24 @@ void Game::createItemScoreSprite(int x, int y, std::shared_ptr texture) smart_sprites_.back()->setFinishedCounter(100); } +// Crea un objeto PathSprite +void Game::createPathSprite(SDL_Point start, SDL_Point end, std::shared_ptr texture) +{ + path_sprites_.emplace_back(std::make_unique(texture)); + + const auto w = texture->getWidth(); + const auto h = texture->getHeight(); + + // Inicializa + path_sprites_.back()->setWidth(w); + path_sprites_.back()->setHeight(h); + path_sprites_.back()->setSpriteClip({0, 0, w, h}); + path_sprites_.back()->addVerticalPath(start, end, 50, 10); + path_sprites_.back()->enable(); +} + // Vacia el vector de smartsprites -void Game::freeSpriteSmarts() +void Game::freeSmartSprites() { if (!smart_sprites_.empty()) for (int i = smart_sprites_.size() - 1; i >= 0; --i) @@ -926,6 +943,15 @@ void Game::freeSpriteSmarts() smart_sprites_.erase(smart_sprites_.begin() + i); } +// Vacia el vector de pathsprites +void Game::freePathSprites() +{ + if (!path_sprites_.empty()) + for (int i = path_sprites_.size() - 1; i >= 0; --i) + if (path_sprites_[i]->hasFinished()) + path_sprites_.erase(path_sprites_.begin() + i); +} + // Crea un SpriteSmart para arrojar el item café al recibir un impacto void Game::throwCoffee(int x, int y) { @@ -949,18 +975,32 @@ void Game::throwCoffee(int x, int y) smart_sprites_.back()->setRotateAmount(90.0); } -// Actualiza los SpriteSmarts -void Game::updateSpriteSmarts() +// Actualiza los SmartSprites +void Game::updateSmartSprites() { - for (auto &ss : smart_sprites_) - ss->update(); + for (auto &sprite : smart_sprites_) + sprite->update(); } -// Pinta los SpriteSmarts activos -void Game::renderSpriteSmarts() +// Pinta los SmartSprites activos +void Game::renderSmartSprites() { - for (auto &ss : smart_sprites_) - ss->render(); + for (auto &sprite : smart_sprites_) + sprite->render(); +} + +// Actualiza los PathSprites +void Game::updatePathSprites() +{ + for (auto &sprite : path_sprites_) + sprite->update(); +} + +// Pinta los PathSprites activos +void Game::renderPathSprites() +{ + for (auto &sprite : path_sprites_) + sprite->render(); } // Acciones a realizar cuando el jugador muere @@ -1122,7 +1162,10 @@ void Game::update() updateGameOver(); // Actualiza los SpriteSmarts - updateSpriteSmarts(); + updateSmartSprites(); + + // Actualiza los PathSmarts + updatePathSprites(); // Actualiza los contadores de estado y efectos updateTimeStopped(); @@ -1150,7 +1193,8 @@ void Game::update() freeBullets(); freeBalloons(); freeItems(); - freeSpriteSmarts(); + freeSmartSprites(); + freePathSprites(); } // Comprueba si la música ha de estar sonando @@ -1197,7 +1241,8 @@ void Game::fillCanvas() // Dibuja los objetos background_->render(); renderItems(); - renderSpriteSmarts(); + renderSmartSprites(); + renderPathSprites(); explosions_->render(); renderBalloons(); renderBullets(); @@ -1506,7 +1551,7 @@ void Game::checkEvents() } #ifdef DEBUG - else if (event.type == SDL_KEYDOWN) + else if (event.type == SDL_KEYDOWN && event.key.repeat == 0) { switch (event.key.keysym.sym) { @@ -1531,6 +1576,15 @@ void Game::checkEvents() createItem(ItemType::CLOCK, players_.at(0)->getPosX(), players_.at(0)->getPosY() - 40); break; } + case SDLK_5: // Crea un PathSprite + { + const auto x = players_.at(0)->getPosX(); + const SDL_Point start = {x, 200}; + const SDL_Point end = {x, 170}; + createPathSprite(start, end, game_text_textures_.at(3)); + path_sprites_.back()->addVerticalPath({x,170}, {x,0}, 100, 1); + break; + } default: break; } diff --git a/source/game.h b/source/game.h index 72fcdca..37af78b 100644 --- a/source/game.h +++ b/source/game.h @@ -17,6 +17,7 @@ class Explosions; class Fade; class Input; class Item; +class PathSprite; class Scoreboard; class Screen; class SmartSprite; @@ -129,6 +130,7 @@ private: std::vector> bullets_; // Vector con las balas std::vector> items_; // Vector con los items std::vector> smart_sprites_; // Vector con los smartsprites + std::vector> path_sprites_; // Vector con los smartsprites std::shared_ptr bullet_texture_; // Textura para las balas std::vector> item_textures_; // Vector con las texturas de los items @@ -305,17 +307,29 @@ private: // Crea un objeto SpriteSmart void createItemScoreSprite(int x, int y, std::shared_ptr texture); + // Crea un objeto PathSprite + void createPathSprite(SDL_Point x, SDL_Point y, std::shared_ptr texture); + // Vacia el vector de smartsprites - void freeSpriteSmarts(); + void freeSmartSprites(); + + // Vacia el vector de pathsprites + void freePathSprites(); // Crea un SpriteSmart para arrojar el item café al recibir un impacto void throwCoffee(int x, int y); // Actualiza los SpriteSmarts - void updateSpriteSmarts(); + void updateSmartSprites(); // Pinta los SpriteSmarts activos - void renderSpriteSmarts(); + void renderSmartSprites(); + + // Actualiza los PathSprites + void updatePathSprites(); + + // Pinta los PathSprites activos + void renderPathSprites(); // Acciones a realizar cuando el jugador muere void killPlayer(std::shared_ptr &player); diff --git a/source/path_sprite.cpp b/source/path_sprite.cpp new file mode 100644 index 0000000..7b21017 --- /dev/null +++ b/source/path_sprite.cpp @@ -0,0 +1,110 @@ +#include "path_sprite.h" +#include "utils.h" +class Texture; + +// 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 path vertical +void PathSprite::addVerticalPath(SDL_Point start, SDL_Point end, int steps, int waiting_counter) +{ + paths_.emplace_back(createVerticalPath(start, end, steps), waiting_counter); +} + +// Añade un path horizontal +void PathSprite::addHorizontalPath(SDL_Point start, SDL_Point end, int steps, int waiting_counter) +{ + paths_.emplace_back(createHorizontalPath(start, end, steps), waiting_counter); +} + +// Devuelve un vector con los puntos que conforman la ruta +std::vector PathSprite::createVerticalPath(SDL_Point start, SDL_Point end, int steps) +{ + std::vector v; + v.reserve(steps); + + for (int i = 0; i < steps; ++i) + { + double t = static_cast(i) / steps; + double value = static_cast(start.y) + (end.y - start.y) * easeOutQuint(t); + v.emplace_back(SDL_Point{start.x, static_cast(value)}); + } + + return v; +} + +// Devuelve un vector con los puntos que conforman la ruta +std::vector PathSprite::createHorizontalPath(SDL_Point start, SDL_Point end, int steps) +{ + std::vector v; + v.reserve(steps); + + for (int i = 0; i < steps; ++i) + { + double t = static_cast(i) / steps; + double value = static_cast(start.x) + (end.x - start.x) * easeOutQuint(t); + v.emplace_back(SDL_Point{static_cast(value), start.y}); + } + + return v; +} + +// Habilita el objeto +void PathSprite::enable() +{ + enabled_ = true; +} + +void PathSprite::moveThroughCurrentPath() +{ + auto &path = paths_.at(current_path_); + + // Establece la posición + const SDL_Point p = path.spots.at(path.counter); + MovingSprite::setPos(p.x, p.y); + + // Comprobar si ha terminado el recorrido + if (!path.on_destination) + { + ++path.counter; + if (path.counter >= static_cast(path.spots.size())) + { + path.on_destination = true; + path.counter = static_cast(path.spots.size()) - 1; + } + } + + // Comprobar si ha terminado la espera + if (path.waiting_counter == 0) + path.finished = true; + else if (path.on_destination) + --path.waiting_counter; +} + +void PathSprite::goToNextPathOrDie() +{ + // Comprueba si ha terminado el recorrdo actual + if (paths_.at(current_path_).finished) + ++current_path_; + + // Comprueba si quedan mas recorridos + if (current_path_ >= static_cast(paths_.size())) + enabled_ = false; +} + +// Indica si ha terminado todos los recorridos +bool PathSprite::hasFinished() +{ + return !enabled_; +} \ No newline at end of file diff --git a/source/path_sprite.h b/source/path_sprite.h new file mode 100644 index 0000000..d610bd1 --- /dev/null +++ b/source/path_sprite.h @@ -0,0 +1,61 @@ +#pragma once + +#include // para shared_ptr +#include "animated_sprite.h" // para SpriteAnimated +class Texture; + +// Clase PathSprite +class PathSprite : public AnimatedSprite +{ +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 + int current_path_ = 0; // Path que se está recorriendo actualmente + std::vector paths_; // Caminos a recorrer por el sprite + + // Devuelve un vector con los puntos que conforman la ruta + std::vector createVerticalPath(SDL_Point start, SDL_Point end, int steps); + + // Devuelve un vector con los puntos que conforman la ruta + std::vector createHorizontalPath(SDL_Point start, SDL_Point end, int steps); + + void moveThroughCurrentPath(); + void goToNextPathOrDie(); + +public: + // Constructor + explicit PathSprite(std::shared_ptr texture); + + // Destructor + ~PathSprite() = default; + + // Actualiza la posición del sprite + void update() override; + + // Añade un path vertical + void addVerticalPath(SDL_Point start, SDL_Point end, int steps, int waiting_counter); + + // Añade un path horizontal + void addHorizontalPath(SDL_Point start, SDL_Point end, int steps, int waiting_counter); + + // Habilita el objeto + void enable(); + + // Indica si ha terminado todos los recorridos + bool hasFinished(); +}; \ No newline at end of file diff --git a/source/smart_sprite.cpp b/source/smart_sprite.cpp index cd7f653..68617d8 100644 --- a/source/smart_sprite.cpp +++ b/source/smart_sprite.cpp @@ -127,6 +127,7 @@ bool SmartSprite::hasFinished() const return finished_; } +// Habilita el objeto void SmartSprite::setEnabled(bool value) { enabled_ = value; diff --git a/source/smart_sprite.h b/source/smart_sprite.h index 6ec7348..a2e3de3 100644 --- a/source/smart_sprite.h +++ b/source/smart_sprite.h @@ -53,5 +53,6 @@ public: // Obtiene el valor de la variable bool hasFinished() const; + // Habilita el objeto void setEnabled(bool value); }; \ No newline at end of file