From bddb790fe2957ff866f4714d7a6ff327bd030a38 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 30 Sep 2025 20:41:35 +0200 Subject: [PATCH] creat bullet_manager.cpp --- CMakeLists.txt | 1 + source/bullet_manager.cpp | 109 ++++++++++++++++++++++++++++++++++++++ source/bullet_manager.h | 79 +++++++++++++++++++++++++++ source/sections/game.cpp | 78 ++++++++------------------- source/sections/game.h | 11 ++-- 5 files changed, 216 insertions(+), 62 deletions(-) create mode 100644 source/bullet_manager.cpp create mode 100644 source/bullet_manager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fe751b..f067580 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,7 @@ set(APP_SOURCES source/balloon_manager.cpp source/balloon.cpp source/bullet.cpp + source/bullet_manager.cpp source/enter_name.cpp source/explosions.cpp source/game_logo.cpp diff --git a/source/bullet_manager.cpp b/source/bullet_manager.cpp new file mode 100644 index 0000000..a637630 --- /dev/null +++ b/source/bullet_manager.cpp @@ -0,0 +1,109 @@ +#include "bullet_manager.h" + +#include // Para remove_if + +#include "bullet.h" // Para Bullet +#include "param.h" // Para param +#include "player.h" // Para Player + +// Constructor +BulletManager::BulletManager() + : play_area_(param.game.play_area.rect) { +} + +// Actualiza el estado de todas las balas +void BulletManager::update(float deltaTime) { + for (auto& bullet : bullets_) { + if (bullet->isEnabled()) { + processBulletUpdate(bullet, deltaTime); + } + } +} + +// Renderiza todas las balas activas +void BulletManager::render() { + for (auto& bullet : bullets_) { + if (bullet->isEnabled()) { + bullet->render(); + } + } +} + +// Crea una nueva bala +void BulletManager::createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner) { + bullets_.emplace_back(std::make_shared(x, y, type, color, owner)); +} + +// Libera balas que ya no están habilitadas +void BulletManager::freeBullets() { + if (!bullets_.empty()) { + // Elimina las balas deshabilitadas del vector + bullets_.erase( + std::remove_if(bullets_.begin(), bullets_.end(), + [](const std::shared_ptr& bullet) { + return !bullet->isEnabled(); + }), + bullets_.end()); + } +} + +// Elimina todas las balas +void BulletManager::clearAllBullets() { + bullets_.clear(); +} + +// Verifica colisiones de todas las balas +void BulletManager::checkCollisions() { + for (auto& bullet : bullets_) { + if (!bullet->isEnabled()) { + continue; + } + + // Verifica colisión con Tabe + if (tabe_collision_callback_ && tabe_collision_callback_(bullet)) { + break; // Sale del bucle si hubo colisión + } + + // Verifica colisión con globos + if (balloon_collision_callback_ && balloon_collision_callback_(bullet)) { + break; // Sale del bucle si hubo colisión + } + } +} + +// Establece el callback para colisión con Tabe +void BulletManager::setTabeCollisionCallback(CollisionCallback callback) { + tabe_collision_callback_ = callback; +} + +// Establece el callback para colisión con globos +void BulletManager::setBalloonCollisionCallback(CollisionCallback callback) { + balloon_collision_callback_ = callback; +} + +// Establece el callback para balas fuera de límites +void BulletManager::setOutOfBoundsCallback(OutOfBoundsCallback callback) { + out_of_bounds_callback_ = callback; +} + +// --- Métodos privados --- + +// Procesa la actualización individual de una bala +void BulletManager::processBulletUpdate(const std::shared_ptr& bullet, float deltaTime) { + auto status = bullet->update(deltaTime); + + // Si la bala salió de los límites, llama al callback + if (status == Bullet::MoveStatus::OUT && out_of_bounds_callback_) { + out_of_bounds_callback_(bullet); + } +} + +// Verifica si la bala está fuera de los límites del área de juego +auto BulletManager::isBulletOutOfBounds(const std::shared_ptr& bullet) -> bool { + auto collider = bullet->getCollider(); + + return (collider.x < play_area_.x || + collider.x > play_area_.x + play_area_.w || + collider.y < play_area_.y || + collider.y > play_area_.y + play_area_.h); +} \ No newline at end of file diff --git a/source/bullet_manager.h b/source/bullet_manager.h new file mode 100644 index 0000000..740497a --- /dev/null +++ b/source/bullet_manager.h @@ -0,0 +1,79 @@ +#pragma once + +#include // Para SDL_FRect + +#include // Para function +#include // Para shared_ptr, unique_ptr +#include // Para vector + +#include "bullet.h" // Para Bullet +#include "utils.h" // Para Circle + +// --- Types --- +using Bullets = std::vector>; + +// --- Forward declarations --- +class Player; + +// --- Clase BulletManager: gestiona todas las balas del juego --- +// +// Esta clase se encarga de la gestión completa de las balas del juego, +// incluyendo su creación, actualización, renderizado y colisiones. +// +// Funcionalidades principales: +// • Gestión del ciclo de vida: creación, actualización y destrucción de balas +// • Renderizado: dibuja todas las balas activas en pantalla +// • Detección de colisiones: mediante sistema de callbacks +// • Limpieza automática: elimina balas deshabilitadas del contenedor +// • Configuración flexible: permite ajustar parámetros de las balas +// +// La clase utiliza un sistema de callbacks para manejar las colisiones, +// permitiendo que la lógica específica del juego permanezca en Game. +class BulletManager { + public: + // --- Types para callbacks --- + using CollisionCallback = std::function&)>; + using OutOfBoundsCallback = std::function&)>; + + // --- Constructor y destructor --- + BulletManager(); + ~BulletManager() = default; + + // --- Métodos principales --- + void update(float deltaTime); // Actualiza el estado de las balas (time-based) + void render(); // Renderiza las balas en pantalla + + // --- Gestión de balas --- + void createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner); // Crea una nueva bala + void freeBullets(); // Libera balas que ya no sirven + void clearAllBullets(); // Elimina todas las balas + + // --- Detección de colisiones --- + void checkCollisions(); // Verifica colisiones de todas las balas + void setTabeCollisionCallback(CollisionCallback callback); // Establece callback para colisión con Tabe + void setBalloonCollisionCallback(CollisionCallback callback); // Establece callback para colisión con globos + void setOutOfBoundsCallback(OutOfBoundsCallback callback); // Establece callback para balas fuera de límites + + // --- Configuración --- + void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego + + // --- Getters --- + auto getBullets() -> Bullets& { return bullets_; } // Obtiene referencia al vector de balas + [[nodiscard]] auto getNumBullets() const -> int { return bullets_.size(); } // Obtiene el número de balas activas + + private: + // --- Objetos y punteros --- + Bullets bullets_; // Vector con las balas activas + + // --- Variables de configuración --- + SDL_FRect play_area_; // Área de juego para límites + + // --- Callbacks para colisiones --- + CollisionCallback tabe_collision_callback_; // Callback para colisión con Tabe + CollisionCallback balloon_collision_callback_; // Callback para colisión con globos + OutOfBoundsCallback out_of_bounds_callback_; // Callback para balas fuera de límites + + // --- Métodos internos --- + void processBulletUpdate(const std::shared_ptr& bullet, float deltaTime); // Procesa actualización individual + auto isBulletOutOfBounds(const std::shared_ptr& bullet) -> bool; // Verifica si la bala está fuera de límites +}; \ No newline at end of file diff --git a/source/sections/game.cpp b/source/sections/game.cpp index 2867fd4..1c441a2 100644 --- a/source/sections/game.cpp +++ b/source/sections/game.cpp @@ -17,6 +17,7 @@ #include "balloon.h" // Para Balloon #include "balloon_manager.h" // Para BalloonManager #include "bullet.h" // Para Bullet, Bullet::Type, BulletMoveStatus +#include "bullet_manager.h" // Para BulletManager #include "color.h" // Para Color, Colors::FLASH #include "difficulty.h" // Para Code #include "fade.h" // Para Fade, FadeType, FadeMode @@ -57,6 +58,7 @@ Game::Game(Player::Id player_id, int current_stage, bool demo_enabled) pause_manager_(std::make_unique([this](bool is_paused) { onPauseStateChanged(is_paused); })), stage_manager_(std::make_unique()), balloon_manager_(std::make_unique(stage_manager_.get())), + bullet_manager_(std::make_unique()), background_(std::make_unique(stage_manager_->getPowerNeededToReachStage(stage_manager_->getTotalStages() - 1))), fade_in_(std::make_unique()), fade_out_(std::make_unique()), @@ -112,6 +114,19 @@ Game::Game(Player::Id player_id, int current_stage, bool demo_enabled) pause_manager_->setServiceMenuPause(is_active); } }); + + // Configura callbacks del BulletManager + bullet_manager_->setTabeCollisionCallback([this](const std::shared_ptr& bullet) { + return checkBulletTabeCollision(bullet); + }); + + bullet_manager_->setBalloonCollisionCallback([this](const std::shared_ptr& bullet) { + return checkBulletBalloonCollision(bullet); + }); + + bullet_manager_->setOutOfBoundsCallback([this](const std::shared_ptr& bullet) { + getPlayer(static_cast(bullet->getOwner()))->decScoreMultiplier(); + }); #ifdef RECORDING setState(State::PLAYING); #endif @@ -333,12 +348,12 @@ void Game::updateGameStateGameOver(float deltaTime) { updateBackground(deltaTime); balloon_manager_->update(deltaTime); tabe_->update(deltaTime); - updateBullets(deltaTime); + bullet_manager_->update(deltaTime); updateItems(deltaTime); updateSmartSprites(deltaTime); updatePathSprites(deltaTime); updateTimeStopped(deltaTime); - checkBulletCollision(); + bullet_manager_->checkCollisions(); cleanVectors(); if (game_over_timer_ < GAME_OVER_DURATION_S) { @@ -369,7 +384,7 @@ void Game::updateGameStateCompleted(float deltaTime) { updateBackground(deltaTime); balloon_manager_->update(deltaTime); tabe_->update(deltaTime); - updateBullets(deltaTime); + bullet_manager_->update(deltaTime); updateItems(deltaTime); updateSmartSprites(deltaTime); updatePathSprites(deltaTime); @@ -498,22 +513,6 @@ void Game::checkPlayerItemCollision(std::shared_ptr& player) { } } -// Comprueba y procesa la colisión de las balas -void Game::checkBulletCollision() { - for (auto& bullet : bullets_) { - if (!bullet->isEnabled()) { - continue; - } - - if (checkBulletTabeCollision(bullet)) { - break; - } - - if (checkBulletBalloonCollision(bullet)) { - break; - } - } -} // Maneja la colisión entre bala y Tabe auto Game::checkBulletTabeCollision(const std::shared_ptr& bullet) -> bool { @@ -601,37 +600,6 @@ void Game::handleBalloonDestruction(std::shared_ptr balloon, const std: updateHiScore(); } -// Mueve las balas activas -void Game::updateBullets(float deltaTime) { - for (auto& bullet : bullets_) { - if (bullet->update(deltaTime) == Bullet::MoveStatus::OUT) { - getPlayer(static_cast(bullet->getOwner()))->decScoreMultiplier(); - } - } -} - -// Pinta las balas activas -void Game::renderBullets() { - for (auto& bullet : bullets_) { - bullet->render(); - } -} - -// Crea un objeto bala -void Game::createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner) { - bullets_.emplace_back(std::make_shared(x, y, type, color, owner)); -} - -// Vacia el vector de balas -void Game::freeBullets() { - if (!bullets_.empty()) { - for (int i = bullets_.size() - 1; i >= 0; --i) { - if (!bullets_[i]->isEnabled()) { - bullets_.erase(bullets_.begin() + i); - } - } - } -} // Actualiza los items void Game::updateItems(float deltaTime) { @@ -982,7 +950,7 @@ void Game::fillCanvas() { renderSmartSprites(); // El cafe que sale cuando te golpean renderItems(); tabe_->render(); - renderBullets(); + bullet_manager_->render(); renderPlayers(); renderPathSprites(); @@ -1343,7 +1311,7 @@ void Game::handleFireInput(const std::shared_ptr& player, Bullet::Type t default: break; } - createBullet(bullet.x, bullet.y, type, player->getNextBulletColor(), static_cast(player->getId())); + bullet_manager_->createBullet(bullet.x, bullet.y, type, player->getNextBulletColor(), static_cast(player->getId())); playSound(player->getBulletSoundFile()); // Establece un tiempo de espera para el próximo disparo. @@ -1833,14 +1801,14 @@ void Game::updateGameStatePlaying(float deltaTime) { updateBackground(deltaTime); balloon_manager_->update(deltaTime); tabe_->update(deltaTime); - updateBullets(deltaTime); + bullet_manager_->update(deltaTime); updateItems(deltaTime); updateStage(); updateSmartSprites(deltaTime); updatePathSprites(deltaTime); updateTimeStopped(deltaTime); updateHelper(); - checkBulletCollision(); + bullet_manager_->checkCollisions(); updateMenace(); checkAndUpdateBalloonSpeed(); checkState(); @@ -1849,7 +1817,7 @@ void Game::updateGameStatePlaying(float deltaTime) { // Vacía los vectores de elementos deshabilitados void Game::cleanVectors() { - freeBullets(); + bullet_manager_->freeBullets(); balloon_manager_->freeBalloons(); freeItems(); freeSmartSprites(); diff --git a/source/sections/game.h b/source/sections/game.h index cb0b993..edcb6a4 100644 --- a/source/sections/game.h +++ b/source/sections/game.h @@ -7,6 +7,7 @@ #include // Para vector #include "bullet.h" // Para Bullet +#include "bullet_manager.h" // Para BulletManager #include "hit.h" // Para Hit #include "item.h" // Para Item, ItemType #include "manage_hiscore_table.h" // Para HiScoreEntry @@ -21,7 +22,7 @@ class Background; class Balloon; class BalloonManager; -class Bullet; +class BulletManager; class Fade; class Input; class PauseManager; @@ -121,7 +122,6 @@ class Game { SDL_Texture* canvas_; // Textura para dibujar la zona de juego std::vector> players_; // Vector con los jugadores - 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 pathsprites @@ -137,6 +137,7 @@ class Game { std::unique_ptr pause_manager_; // Objeto para gestionar la pausa std::unique_ptr stage_manager_; // Objeto para gestionar las fases std::unique_ptr balloon_manager_; // Objeto para gestionar los globos + std::unique_ptr bullet_manager_; // Objeto para gestionar las balas std::unique_ptr background_; // Objeto para dibujar el fondo del juego std::unique_ptr fade_in_; // Objeto para renderizar fades std::unique_ptr fade_out_; // Objeto para renderizar fades @@ -260,11 +261,7 @@ class Game { void demoHandlePlayerInput(const std::shared_ptr& player, int index); // Procesa entrada de jugador en demo // --- Sistema de balas y proyectiles --- - void updateBullets(float deltaTime); // Actualiza posición y estado de todas las balas (time-based) - void renderBullets(); // Renderiza todas las balas activas - void createBullet(int x, int y, Bullet::Type kind, Bullet::Color color, int owner); // Crea una nueva bala - void checkBulletCollision(); // Verifica colisiones de todas las balas - void freeBullets(); // Libera memoria del vector de balas + void checkBulletCollision(); // Verifica colisiones de todas las balas (delegado a BulletManager) // --- Colisiones específicas de balas --- auto checkBulletTabeCollision(const std::shared_ptr& bullet) -> bool; // Detecta colisión bala-Tabe