Compare commits

4 Commits

17 changed files with 438 additions and 335 deletions

View File

@@ -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

109
source/bullet_manager.cpp Normal file
View File

@@ -0,0 +1,109 @@
#include "bullet_manager.h"
#include <algorithm> // 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<Bullet>(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>& 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>& 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>& 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);
}

79
source/bullet_manager.h Normal file
View File

@@ -0,0 +1,79 @@
#pragma once
#include <SDL3/SDL.h> // Para SDL_FRect
#include <functional> // Para function
#include <memory> // Para shared_ptr, unique_ptr
#include <vector> // Para vector
#include "bullet.h" // Para Bullet
#include "utils.h" // Para Circle
// --- Types ---
using Bullets = std::vector<std::shared_ptr<Bullet>>;
// --- 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<bool(const std::shared_ptr<Bullet>&)>;
using OutOfBoundsCallback = std::function<void(const std::shared_ptr<Bullet>&)>;
// --- 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>& bullet, float deltaTime); // Procesa actualización individual
auto isBulletOutOfBounds(const std::shared_ptr<Bullet>& bullet) -> bool; // Verifica si la bala está fuera de límites
};

View File

@@ -95,6 +95,29 @@ struct Color {
return Color(new_r, new_g, new_b, new_a);
}
// Interpolación lineal hacia otro color (t=0.0: this, t=1.0: target)
[[nodiscard]] constexpr auto LERP(const Color &target, float t) const -> Color {
// Asegurar que t esté en el rango [0.0, 1.0]
t = std::clamp(t, 0.0f, 1.0f);
// Interpolación lineal para cada componente
auto lerp_component = [t](Uint8 start, Uint8 end) -> Uint8 {
return static_cast<Uint8>(start + (end - start) * t);
};
return Color(
lerp_component(r, target.r),
lerp_component(g, target.g),
lerp_component(b, target.b),
lerp_component(a, target.a)
);
}
// Sobrecarga para aceptar componentes RGBA directamente
[[nodiscard]] constexpr auto LERP(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha, float t) const -> Color {
return LERP(Color(red, green, blue, alpha), t);
}
// Convierte el color a un entero de 32 bits en formato RGBA
[[nodiscard]] constexpr auto TO_UINT32() const -> Uint32 {
return (static_cast<Uint32>(r) << 24) |

View File

@@ -42,7 +42,7 @@ Director::Director(int argc, std::span<char *> argv) {
Section::name = Section::Name::GAME;
Section::options = Section::Options::GAME_PLAY_1P;
#elif _DEBUG
Section::name = Section::Name::TITLE;
Section::name = Section::Name::GAME;
Section::options = Section::Options::GAME_PLAY_1P;
#else // NORMAL GAME
Section::name = Section::Name::LOGO;

View File

@@ -1,147 +1,96 @@
#include "enter_name.h"
#include <cstddef> // Para size_t
#include <array> // Para array
#include <cstdlib> // Para rand
#include <string_view> // Para basic_string_view, string_view
#include "utils.h" // Para trim
// Constructor
EnterName::EnterName()
: character_list_(" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789."),
character_index_{0} {}
: character_list_("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789. "),
selected_index_(0) {}
// Inicializa el objeto
void EnterName::init(const std::string &name) {
// No se pasa ningún nombre
if (name.empty()) {
name_ = "A";
position_ = 0;
position_overflow_ = false;
}
// Se pasa un nombre
else {
name_ = name;
position_ = name_.length();
position_overflow_ = position_ >= NAME_SIZE;
}
// Inicializa el vector de indices con el nombre y espacios
initCharacterIndex(name_);
name_ = sanitizeName(name);
selected_index_ = 0;
}
// Incrementa la posición
void EnterName::incPosition() {
if (position_overflow_) {
// Si ya estamos en overflow, no incrementamos más.
return;
}
++position_;
if (position_ >= NAME_SIZE) {
position_ = NAME_SIZE; // Mantenemos en el índice máximo válido.
position_overflow_ = true; // Activamos el flag de overflow.
} else if (position_ > 0) // No es necesario verificar position_ < MAX_NAME_LENGTH
{
// Copiamos el índice del carácter anterior si es posible.
// character_index_[position_] = character_index_[position_ - 1];
// Ponemos el caracter "espacio"
character_index_[position_] = 0;
} else {
// Si position_ es 0, inicializamos el carácter actual.
character_index_[position_] = 0;
}
updateNameFromCharacterIndex();
}
// Decrementa la posición
void EnterName::decPosition() {
if (position_overflow_) {
// Si estaba en overflow, lo desactivamos y mantenemos position_ en el máximo.
position_overflow_ = false;
position_ = NAME_SIZE - 1;
} else {
if (position_ > 0) {
--position_;
// Limpiamos el carácter siguiente si el índice es válido.
if (position_ + 1 < NAME_SIZE) {
character_index_[position_ + 1] = 0;
}
} else {
// Si position_ es 0, aseguramos que no vaya a ser negativo y limpiamos el carácter actual.
position_ = 0;
// character_index_[position_] = 0;
}
// Si position_ es menor que NAME_LENGTH, aseguramos que el overflow esté desactivado.
if (position_ < NAME_SIZE) {
position_overflow_ = false;
}
}
updateNameFromCharacterIndex();
}
// Incrementa el índice
// Incrementa el índice del carácter seleccionado
void EnterName::incIndex() {
if (position_overflow_) {
return;
++selected_index_;
if (selected_index_ >= static_cast<int>(character_list_.size())) {
selected_index_ = 0;
}
++character_index_[position_];
if (character_index_[position_] >= static_cast<int>(character_list_.size())) {
character_index_[position_] = 0;
}
updateNameFromCharacterIndex();
}
// Decrementa el índice
// Decrementa el índice del carácter seleccionado
void EnterName::decIndex() {
if (position_overflow_) {
return;
}
--character_index_[position_];
if (character_index_[position_] < 0) {
character_index_[position_] = character_list_.size() - 1;
}
updateNameFromCharacterIndex();
}
// Actualiza el nombre a partir de la lista de índices
void EnterName::updateNameFromCharacterIndex() {
name_.clear();
for (size_t i = 0; i < NAME_SIZE; ++i) {
name_.push_back(character_list_[character_index_[i]]);
}
name_ = trim(name_);
}
// Actualiza la variable
void EnterName::initCharacterIndex(const std::string &name) {
// Rellena de espacios
for (size_t i = 0; i < NAME_SIZE; ++i) {
character_index_[i] = 0;
}
// Coloca los índices en función de los caracteres que forman el nombre
for (size_t i = 0; i < name.substr(0, NAME_SIZE).size(); ++i) {
character_index_[i] = findIndex(name.at(i));
--selected_index_;
if (selected_index_ < 0) {
selected_index_ = character_list_.size() - 1;
}
}
// Encuentra el indice de un caracter en "character_list_"
auto EnterName::findIndex(char character) const -> int {
for (size_t i = 0; i < character_list_.size(); ++i) {
if (character == character_list_.at(i)) {
return i;
// Añade el carácter seleccionado al nombre
void EnterName::addCharacter() {
if (name_.length() < MAX_NAME_SIZE) {
name_.push_back(character_list_[selected_index_]);
}
}
// Elimina el último carácter del nombre
void EnterName::removeLastCharacter() {
if (!name_.empty()) {
name_.pop_back();
}
}
// Devuelve el carácter seleccionado con offset relativo como string
auto EnterName::getSelectedCharacter(int offset) const -> std::string {
// Calcular el índice con offset, con wrap-around circular
int size = static_cast<int>(character_list_.size());
int index = (selected_index_ + offset) % size;
// Manejar índices negativos (hacer wrap-around hacia atrás)
if (index < 0) {
index += size;
}
return std::string(1, character_list_[index]);
}
// Devuelve el carrusel completo de caracteres centrado en el seleccionado
auto EnterName::getCarousel(int size) const -> std::string {
// Asegurar que el tamaño sea impar para tener un centro claro
if (size % 2 == 0) {
++size;
}
std::string carousel;
carousel.reserve(size); // Optimización: reservar memoria de antemano
int half = size / 2;
// Construir desde -half hasta +half (inclusive)
for (int offset = -half; offset <= half; ++offset) {
carousel += getSelectedCharacter(offset);
}
return carousel;
}
// Valida y limpia el nombre: solo caracteres legales y longitud máxima
auto EnterName::sanitizeName(const std::string &name) const -> std::string {
std::string sanitized;
for (size_t i = 0; i < name.length() && sanitized.length() < MAX_NAME_SIZE; ++i) {
// Verifica si el carácter está en la lista permitida
if (character_list_.find(name[i]) != std::string::npos) {
sanitized.push_back(name[i]);
}
}
return 0;
return sanitized;
}
// Devuelve un nombre al azar
@@ -157,12 +106,11 @@ auto EnterName::getRandomName() -> std::string {
"PEPE"};
return std::string(NAMES[rand() % NAMES.size()]);
}
// Obtiene el nombre final introducido
auto EnterName::getFinalName() -> std::string {
auto name = trim(name_.substr(0, position_ + 1)); // Devuelve el texto intruducido incluyendo el del selector
if (name.empty()) {
name = getRandomName();
if (name_.empty()) {
name_ = getRandomName();
}
name_ = name;
return name_;
}

View File

@@ -1,43 +1,36 @@
#pragma once
#include <array> // Para array
#include <cstddef> // Para size_t
#include <string> // Para allocator, string
#include "utils.h" // Para trim
// --- Constantes ---
constexpr size_t NAME_SIZE = 5; // Tamaño máximo del nombre
// --- Clase EnterName: gestor de entrada de nombre del jugador ---
class EnterName {
public:
// --- Constantes ---
static constexpr size_t MAX_NAME_SIZE = 6; // Tamaño máximo del nombre
EnterName();
~EnterName() = default;
void init(const std::string &name = ""); // Inicializa con un nombre opcional
void init(const std::string &name = ""); // Inicializa con nombre opcional (vacío por defecto)
void incPosition(); // Incrementa la posición del carácter actual
void decPosition(); // Decrementa la posición del carácter actual
void incIndex(); // Incrementa el índice del carácter en la lista
void decIndex(); // Decrementa el índice del carácter en la lista
void incIndex(); // Incrementa el índice del carácter seleccionado en la lista
void decIndex(); // Decrementa el índice del carácter seleccionado en la lista
auto getFinalName() -> std::string; // Obtiene el nombre final introducido
[[nodiscard]] auto getCurrentName() const -> std::string { return trim(name_); } // Obtiene el nombre actual en proceso
void addCharacter(); // Añade el carácter seleccionado al nombre
void removeLastCharacter(); // Elimina el último carácter del nombre
[[nodiscard]] auto getPosition() const -> int { return position_; } // Posición actual del carácter editado
[[nodiscard]] auto getPositionOverflow() const -> bool { return position_overflow_; } // Indica si la posición excede el límite
auto getFinalName() -> std::string; // Obtiene el nombre final (o aleatorio si vacío)
[[nodiscard]] auto getCurrentName() const -> std::string { return name_; } // Obtiene el nombre actual en proceso
[[nodiscard]] auto getSelectedCharacter(int offset = 0) const -> std::string; // Devuelve el carácter seleccionado con offset relativo
[[nodiscard]] auto getCarousel(int size) const -> std::string; // Devuelve el carrusel de caracteres (size debe ser impar)
private:
// --- Variables de estado ---
std::string character_list_; // Lista de caracteres permitidos
std::string name_; // Nombre en proceso
std::array<int, NAME_SIZE> character_index_; // Índices a "character_list_"
size_t position_ = 0; // Índice del carácter que se edita
bool position_overflow_ = false; // Flag para exceder límite
std::string character_list_; // Lista de caracteres permitidos
std::string name_; // Nombre en proceso
int selected_index_ = 0; // Índice del carácter seleccionado en "character_list_"
void updateNameFromCharacterIndex(); // Actualiza "name_" según "character_index_"
void initCharacterIndex(const std::string &name); // Inicializa índices desde el nombre
[[nodiscard]] auto findIndex(char character) const -> int; // Busca el índice de un carácter en "character_list_"
static auto getRandomName() -> std::string; // Devuelve un nombre al azar
[[nodiscard]] auto sanitizeName(const std::string &name) const -> std::string; // Valida y limpia el nombre
static auto getRandomName() -> std::string; // Devuelve un nombre al azar
};

View File

@@ -128,11 +128,11 @@ void Player::setInputPlaying(Input::Action action) {
// Procesa inputs para cuando está introduciendo el nombre
void Player::setInputEnteringName(Input::Action action) {
switch (action) {
case Input::Action::LEFT:
enter_name_->decPosition();
case Input::Action::FIRE_LEFT:
enter_name_->addCharacter();
break;
case Input::Action::RIGHT:
enter_name_->incPosition();
case Input::Action::FIRE_CENTER:
enter_name_->removeLastCharacter();
break;
case Input::Action::UP:
enter_name_->incIndex();
@@ -540,8 +540,9 @@ void Player::updateScoreboard() {
}
case State::ENTERING_NAME:
case State::ENTERING_NAME_GAME_COMPLETED: {
Scoreboard::get()->setRecordName(scoreboard_panel_, enter_name_->getCurrentName());
Scoreboard::get()->setSelectorPos(scoreboard_panel_, getRecordNamePos());
Scoreboard::get()->setEnterName(scoreboard_panel_, enter_name_->getCurrentName());
Scoreboard::get()->setCharacterSelected(scoreboard_panel_, enter_name_->getSelectedCharacter());
Scoreboard::get()->setCarousel(scoreboard_panel_, enter_name_->getCarousel(7));
break;
}
default:
@@ -616,7 +617,7 @@ void Player::setPlayingState(State state) {
case State::SHOWING_NAME: {
showing_name_time_accumulator_ = 0.0f; // Inicializar acumulador time-based
setScoreboardMode(Scoreboard::Mode::SHOW_NAME);
Scoreboard::get()->setRecordName(scoreboard_panel_, last_enter_name_);
Scoreboard::get()->setEnterName(scoreboard_panel_, last_enter_name_);
addScoreToScoreBoard();
break;
}
@@ -901,15 +902,6 @@ void Player::decNameEntryCounter() {
}
}
// Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones
auto Player::getRecordNamePos() const -> int {
if (enter_name_) {
return enter_name_->getPosition();
}
return 0;
}
// Recoloca los sprites
void Player::shiftSprite() {
player_sprite_->setPosX(pos_x_);

View File

@@ -204,10 +204,8 @@ class Player {
// Contadores y timers
[[nodiscard]] auto getContinueCounter() const -> int { return continue_counter_; }
[[nodiscard]] auto getRecordNamePos() const -> int; // Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones
[[nodiscard]] auto getRecordName() const -> std::string { return enter_name_ ? enter_name_->getFinalName() : "xxx"; }
[[nodiscard]] auto getLastEnterName() const -> std::string { return last_enter_name_; }
[[nodiscard]] auto getEnterNamePositionOverflow() const -> bool { return enter_name_ ? enter_name_->getPositionOverflow() : false; }
// --- Configuración e interfaz externa ---
void setName(const std::string& name) { name_ = name; }

View File

@@ -18,7 +18,7 @@
#include "texture.h" // Para Texture
// .at(SINGLETON) Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Scoreboard *Scoreboard::instance = nullptr;
Scoreboard* Scoreboard::instance = nullptr;
// .at(SINGLETON) Crearemos el objeto score_board con esta función estática
void Scoreboard::init() {
@@ -31,7 +31,7 @@ void Scoreboard::destroy() {
}
// .at(SINGLETON) Con este método obtenemos el objeto score_board y podemos trabajar con él
auto Scoreboard::get() -> Scoreboard * {
auto Scoreboard::get() -> Scoreboard* {
return Scoreboard::instance;
}
@@ -40,12 +40,11 @@ Scoreboard::Scoreboard()
: renderer_(Screen::get()->getRenderer()),
game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")),
power_meter_sprite_(std::make_unique<Sprite>(game_power_meter_texture_)),
text_(Resource::get()->getText("8bithud")),
enter_name_text_(Resource::get()->getText("smb2")) {
text_(Resource::get()->getText("8bithud")) {
// Inicializa variables
for (size_t i = 0; i < static_cast<size_t>(Id::SIZE); ++i) {
name_.at(i).clear();
record_name_.at(i).clear();
enter_name_.at(i).clear();
selector_pos_.at(i) = 0;
score_.at(i) = 0;
mult_.at(i) = 0;
@@ -74,8 +73,9 @@ Scoreboard::Scoreboard()
// Rellena la textura de fondo
fillBackgroundTexture();
// Inicializa el vector de colores para el nombre
iniNameColors();
// Inicializa el ciclo de colores para el nombre
name_color_cycle_ = Colors::generateMirroredCycle(color_.INVERSE(), ColorCycleStyle::VIBRANT);
animated_color_ = name_color_cycle_.at(0);
}
Scoreboard::~Scoreboard() {
@@ -83,7 +83,7 @@ Scoreboard::~Scoreboard() {
SDL_DestroyTexture(background_);
}
for (auto *texture : panel_texture_) {
for (auto* texture : panel_texture_) {
if (texture != nullptr) {
SDL_DestroyTexture(texture);
}
@@ -107,11 +107,24 @@ void Scoreboard::updateTimeCounter() {
}
}
// Actualiza el índice del color animado del nombre
void Scoreboard::updateNameColorIndex() {
constexpr Uint64 COLOR_UPDATE_INTERVAL = 100; // 100ms entre cambios de color
if (SDL_GetTicks() - name_color_last_update_ >= COLOR_UPDATE_INTERVAL) {
++name_color_index_;
name_color_last_update_ = SDL_GetTicks();
}
// Precalcular el color actual del ciclo
animated_color_ = name_color_cycle_.at(name_color_index_ % name_color_cycle_.size());
}
// Actualiza la lógica del marcador
void Scoreboard::update() {
fillBackgroundTexture();
updateTimeCounter();
++loop_counter_;
updateNameColorIndex();
}
// Pinta el marcador
@@ -129,7 +142,7 @@ void Scoreboard::setColor(Color color) {
// Aplica los colores
power_meter_sprite_->getTexture()->setColor(text_color2_);
fillBackgroundTexture();
iniNameColors();
name_color_cycle_ = Colors::generateMirroredCycle(color_.INVERSE(), ColorCycleStyle::VIBRANT);
}
// Establece el valor de la variable
@@ -145,7 +158,7 @@ void Scoreboard::setPos(SDL_FRect rect) {
// Rellena los diferentes paneles del marcador
void Scoreboard::fillPanelTextures() {
// Guarda a donde apunta actualmente el renderizador
auto *temp = SDL_GetRenderTarget(renderer_);
auto* temp = SDL_GetRenderTarget(renderer_);
// Genera el contenido de cada panel_
for (size_t i = 0; i < static_cast<int>(Id::SIZE); ++i) {
@@ -267,6 +280,7 @@ void Scoreboard::renderContinueMode(size_t panel_index) {
}
void Scoreboard::renderEnterNameMode(size_t panel_index) {
/*
// SCORE
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y, name_.at(panel_index), 1, text_color1_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_.at(panel_index)), 1, text_color2_);
@@ -275,29 +289,19 @@ void Scoreboard::renderEnterNameMode(size_t panel_index) {
text_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
renderNameInputField(panel_index);
}
*/
void Scoreboard::renderNameInputField(size_t panel_index) {
SDL_FRect rect = {
.x = enter_name_pos_.x,
.y = enter_name_pos_.y,
.w = static_cast<float>(enter_name_text_->getCharacterSize() - 2),
.h = static_cast<float>(enter_name_text_->getCharacterSize())};
// SCORE
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y, updateScoreText(score_.at(panel_index)), 1, text_color2_);
// Recorre todos los slots de letras del nombre
for (size_t j = 0; j < NAME_SIZE; ++j) {
// Dibuja la linea. Si coincide con el selector solo se dibuja 2 de cada 4 veces
if (j != selector_pos_.at(panel_index) || time_counter_ % 4 >= 2) {
SDL_SetRenderDrawColor(renderer_, text_color1_.r, text_color1_.g, text_color1_.b, 255);
SDL_RenderLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
}
// ENTER NAME
text_->writeDX(Text::CENTER | Text::COLOR, slot4_2_.x, slot4_2_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
// Dibuja la letra
if (j < record_name_.at(panel_index).size()) {
enter_name_text_->writeColored(rect.x, rect.y, record_name_.at(panel_index).substr(j, 1), text_color2_);
}
rect.x += enter_name_text_->getCharacterSize();
}
// NAME
text_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y, enter_name_.at(panel_index), 1, text_color2_);
// CARRUSEL
text_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y, carousel_.at(panel_index), 1, animated_color_);
}
void Scoreboard::renderShowNameMode(size_t panel_index) {
@@ -309,7 +313,7 @@ void Scoreboard::renderShowNameMode(size_t panel_index) {
text_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
// NOMBRE INTRODUCIDO
enter_name_text_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y, record_name_.at(panel_index), 1, Colors::getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
text_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y, enter_name_.at(panel_index), 1, animated_color_);
}
void Scoreboard::renderGameCompletedMode(size_t panel_index) {
@@ -329,7 +333,7 @@ void Scoreboard::fillBackgroundTexture() {
fillPanelTextures();
// Cambia el destino del renderizador
SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
SDL_Texture* temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, background_);
// Dibuja el fondo del marcador
@@ -379,7 +383,7 @@ void Scoreboard::recalculateAnchors() {
slot4_4_ = {.x = COL, .y = ROW4};
// Primer cuadrado para poner el nombre de record
const int ENTER_NAME_LENGTH = enter_name_text_->length(std::string(NAME_SIZE, 'A'));
const int ENTER_NAME_LENGTH = text_->length(std::string(EnterName::MAX_NAME_SIZE, 'A'));
enter_name_pos_.x = COL - (ENTER_NAME_LENGTH / 2);
enter_name_pos_.y = ROW4;
@@ -405,7 +409,7 @@ void Scoreboard::createBackgroundTexture() {
// Crea las texturas de los paneles
void Scoreboard::createPanelTextures() {
// Elimina las texturas en caso de existir
for (auto *texture : panel_texture_) {
for (auto* texture : panel_texture_) {
if (texture != nullptr) {
SDL_DestroyTexture(texture);
}
@@ -413,8 +417,8 @@ void Scoreboard::createPanelTextures() {
panel_texture_.clear();
// Crea las texturas para cada panel_
for (auto &i : panel_) {
SDL_Texture *tex = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, i.pos.w, i.pos.h);
for (auto& i : panel_) {
SDL_Texture* tex = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, i.pos.w, i.pos.h);
SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
panel_texture_.push_back(tex);
}
@@ -426,15 +430,4 @@ void Scoreboard::renderSeparator() {
auto color = param.scoreboard.separator_autocolor ? color_.DARKEN() : param.scoreboard.separator_color;
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 255);
SDL_RenderLine(renderer_, 0, 0, rect_.w, 0);
}
// Inicializa el vector de colores para el nombre
void Scoreboard::iniNameColors() {
Color color = color_.INVERSE();
name_colors_.clear();
name_colors_.emplace_back(color.LIGHTEN(50));
name_colors_.emplace_back(color.LIGHTEN(25));
name_colors_.emplace_back(color);
name_colors_.emplace_back(color.DARKEN(25));
}

View File

@@ -45,9 +45,9 @@ class Scoreboard {
};
// --- Métodos de singleton ---
static void init(); // Crea el objeto Scoreboard
static void destroy(); // Libera el objeto Scoreboard
static auto get() -> Scoreboard *; // Obtiene el puntero al objeto Scoreboard
static void init(); // Crea el objeto Scoreboard
static void destroy(); // Libera el objeto Scoreboard
static auto get() -> Scoreboard*; // Obtiene el puntero al objeto Scoreboard
// --- Métodos principales ---
void update(); // Actualiza la lógica del marcador
@@ -58,44 +58,49 @@ class Scoreboard {
void setPos(SDL_FRect rect); // Establece la posición y tamaño del marcador
void setContinue(Id id, int continue_counter) { continue_counter_.at(static_cast<size_t>(id)) = continue_counter; }
void setHiScore(int hi_score) { hi_score_ = hi_score; }
void setHiScoreName(const std::string &name) { hi_score_name_ = name; }
void setHiScoreName(const std::string& name) { hi_score_name_ = name; }
void setMode(Id id, Mode mode) { panel_.at(static_cast<size_t>(id)).mode = mode; }
void setMult(Id id, float mult) { mult_.at(static_cast<size_t>(id)) = mult; }
void setName(Id id, const std::string &name) { name_.at(static_cast<size_t>(id)) = name; }
void setName(Id id, const std::string& name) { name_.at(static_cast<size_t>(id)) = name; }
void setPower(float power) { power_ = power; }
void setRecordName(Id id, const std::string &record_name) { record_name_.at(static_cast<size_t>(id)) = record_name; }
void setEnterName(Id id, const std::string& enter_name) { enter_name_.at(static_cast<size_t>(id)) = enter_name; }
void setCharacterSelected(Id id, const std::string& character_selected) { character_selected_.at(static_cast<size_t>(id)) = character_selected; }
void setCarousel(Id id, const std::string& carousel) { carousel_.at(static_cast<size_t>(id)) = carousel; }
void setScore(Id id, int score) { score_.at(static_cast<size_t>(id)) = score; }
void setSelectorPos(Id id, int pos) { selector_pos_.at(static_cast<size_t>(id)) = pos; }
void setStage(int stage) { stage_ = stage; }
private:
// --- Objetos y punteros ---
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Renderer* renderer_; // El renderizador de la ventana
std::shared_ptr<Texture> game_power_meter_texture_; // Textura con el marcador de poder de la fase
std::unique_ptr<Sprite> power_meter_sprite_; // Sprite para el medidor de poder de la fase
std::shared_ptr<Text> text_; // Fuente para el marcador del juego
std::shared_ptr<Text> enter_name_text_; // Fuente para la introducción de nombre del jugador
SDL_Texture *background_ = nullptr; // Textura para dibujar el marcador
std::vector<SDL_Texture *> panel_texture_; // Texturas para dibujar cada panel
SDL_Texture* background_ = nullptr; // Textura para dibujar el marcador
std::vector<SDL_Texture*> panel_texture_; // Texturas para dibujar cada panel
// --- Variables de estado ---
std::array<std::string, static_cast<int>(Id::SIZE)> name_ = {}; // Nombre de cada jugador
std::array<std::string, static_cast<int>(Id::SIZE)> record_name_ = {}; // Nombre introducido para la tabla de records
std::array<Panel, static_cast<int>(Id::SIZE)> panel_ = {}; // Lista con todos los paneles del marcador
std::vector<Color> name_colors_; // Colores para destacar el nombre una vez introducido
std::string hi_score_name_; // Nombre del jugador con la máxima puntuación
SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
Color color_; // Color del marcador
std::array<size_t, static_cast<int>(Id::SIZE)> selector_pos_ = {}; // Posición del selector de letra para introducir el nombre
std::array<int, static_cast<int>(Id::SIZE)> score_ = {}; // Puntuación de los jugadores
std::array<int, static_cast<int>(Id::SIZE)> continue_counter_ = {}; // Tiempo para continuar de los jugadores
std::array<float, static_cast<int>(Id::SIZE)> mult_ = {}; // Multiplicador de los jugadores
Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks()
int stage_ = 1; // Número de fase actual
int hi_score_ = 0; // Máxima puntuación
int time_counter_ = 0; // Contador de segundos
int loop_counter_ = 0; // Contador de bucle
float power_ = 0; // Poder actual de la fase
std::array<std::string, static_cast<int>(Id::SIZE)> name_ = {}; // Nombre de cada jugador
std::array<std::string, static_cast<int>(Id::SIZE)> enter_name_ = {}; // Nombre introducido para la tabla de records
std::array<std::string, static_cast<int>(Id::SIZE)> character_selected_ = {}; // Caracter seleccionado
std::array<std::string, static_cast<int>(Id::SIZE)> carousel_ = {}; // Caracter seleccionado
std::array<Panel, static_cast<int>(Id::SIZE)> panel_ = {}; // Lista con todos los paneles del marcador
Colors::Cycle name_color_cycle_; // Ciclo de colores para destacar el nombre una vez introducido
Color animated_color_; // Color actual animado (ciclo automático cada 100ms)
std::string hi_score_name_; // Nombre del jugador con la máxima puntuación
SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
Color color_; // Color del marcador
std::array<size_t, static_cast<int>(Id::SIZE)> selector_pos_ = {}; // Posición del selector de letra para introducir el nombre
std::array<int, static_cast<int>(Id::SIZE)> score_ = {}; // Puntuación de los jugadores
std::array<int, static_cast<int>(Id::SIZE)> continue_counter_ = {}; // Tiempo para continuar de los jugadores
std::array<float, static_cast<int>(Id::SIZE)> mult_ = {}; // Multiplicador de los jugadores
Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks()
int stage_ = 1; // Número de fase actual
int hi_score_ = 0; // Máxima puntuación
int time_counter_ = 0; // Contador de segundos
Uint32 name_color_index_ = 0; // Índice actual del color en el ciclo de animación del nombre
Uint64 name_color_last_update_ = 0; // Último tick de actualización del color del nombre
float power_ = 0; // Poder actual de la fase
// --- Variables de aspecto ---
Color text_color1_, text_color2_; // Colores para los marcadores del texto;
@@ -112,8 +117,8 @@ class Scoreboard {
void fillPanelTextures(); // Rellena los diferentes paneles del marcador
void fillBackgroundTexture(); // Rellena la textura de fondo
void updateTimeCounter(); // Actualiza el contador
void updateNameColorIndex(); // Actualiza el índice del color animado del nombre
void renderSeparator(); // Dibuja la línea que separa la zona de juego del marcador
void iniNameColors(); // Inicializa el vector de colores para el nombre
void renderPanelContent(size_t panel_index);
void renderScoreMode(size_t panel_index);
void renderDemoMode();
@@ -131,5 +136,5 @@ class Scoreboard {
~Scoreboard(); // Destructor privado
// --- Instancia singleton ---
static Scoreboard *instance; // Instancia única de Scoreboard
static Scoreboard* instance; // Instancia única de Scoreboard
};

View File

@@ -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<PauseManager>([this](bool is_paused) { onPauseStateChanged(is_paused); })),
stage_manager_(std::make_unique<StageManager>()),
balloon_manager_(std::make_unique<BalloonManager>(stage_manager_.get())),
bullet_manager_(std::make_unique<BulletManager>()),
background_(std::make_unique<Background>(stage_manager_->getPowerNeededToReachStage(stage_manager_->getTotalStages() - 1))),
fade_in_(std::make_unique<Fade>()),
fade_out_(std::make_unique<Fade>()),
@@ -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>& bullet) {
return checkBulletTabeCollision(bullet);
});
bullet_manager_->setBalloonCollisionCallback([this](const std::shared_ptr<Bullet>& bullet) {
return checkBulletBalloonCollision(bullet);
});
bullet_manager_->setOutOfBoundsCallback([this](const std::shared_ptr<Bullet>& bullet) {
getPlayer(static_cast<Player::Id>(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>& 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>& bullet) -> bool {
@@ -601,37 +600,6 @@ void Game::handleBalloonDestruction(std::shared_ptr<Balloon> 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<Player::Id>(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<Bullet>(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>& player, Bullet::Type t
default:
break;
}
createBullet(bullet.x, bullet.y, type, player->getNextBulletColor(), static_cast<int>(player->getId()));
bullet_manager_->createBullet(bullet.x, bullet.y, type, player->getNextBulletColor(), static_cast<int>(player->getId()));
playSound(player->getBulletSoundFile());
// Establece un tiempo de espera para el próximo disparo.
@@ -1467,14 +1435,7 @@ void Game::handleNameInput(const std::shared_ptr<Player>& player) {
player->passShowingName();
return;
}
if (player->getEnterNamePositionOverflow()) {
player->setInput(Input::Action::START);
player->setPlayingState(Player::State::SHOWING_NAME);
playSound("service_menu_select.wav");
updateHiScoreName();
return;
}
player->setInput(Input::Action::RIGHT);
player->setInput(Input::Action::FIRE_LEFT);
playSound("service_menu_select.wav");
return;
}
@@ -1485,7 +1446,7 @@ void Game::handleNameInput(const std::shared_ptr<Player>& player) {
player->passShowingName();
return;
}
player->setInput(Input::Action::LEFT);
player->setInput(Input::Action::FIRE_CENTER);
playSound("service_menu_back.wav");
return;
}
@@ -1833,14 +1794,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 +1810,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();

View File

@@ -7,6 +7,7 @@
#include <vector> // 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<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::shared_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
std::vector<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los pathsprites
@@ -137,6 +137,7 @@ class Game {
std::unique_ptr<PauseManager> pause_manager_; // Objeto para gestionar la pausa
std::unique_ptr<StageManager> stage_manager_; // Objeto para gestionar las fases
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
std::unique_ptr<BulletManager> bullet_manager_; // Objeto para gestionar las balas
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
@@ -260,11 +261,7 @@ class Game {
void demoHandlePlayerInput(const std::shared_ptr<Player>& 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>& bullet) -> bool; // Detecta colisión bala-Tabe

View File

@@ -208,7 +208,7 @@ void Intro::switchText(int from_index, int to_index) {
// Actualiza las variables del objeto
void Intro::update(float delta_time) {
static auto *const SCREEN = Screen::get();
static auto* const SCREEN = Screen::get();
SCREEN->update(delta_time); // Actualiza el objeto screen
Audio::update(); // Actualiza el objeto Audio
@@ -229,7 +229,7 @@ void Intro::update(float delta_time) {
// Dibuja el objeto en pantalla
void Intro::render() {
static auto *const SCREEN = Screen::get();
static auto* const SCREEN = Screen::get();
SCREEN->start(); // Prepara para empezar a dibujar en la textura de juego
SCREEN->clean(); // Limpia la pantalla
@@ -302,7 +302,7 @@ void Intro::initSprites() {
card_texture->setBlendMode(SDL_BLENDMODE_BLEND);
// Apuntamos el renderizador a la textura
auto *temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
auto* temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
card_texture->setAsRenderTarget(Screen::get()->getRenderer());
// Limpia la textura
@@ -343,7 +343,7 @@ void Intro::initSprites() {
card_sprites_.at(2)->addPath(-CARD_HEIGHT, Y_DEST, PathType::VERTICAL, X_DEST, CARD_ANIM_DURATION_FAST, easeOutQuint, 0.0f);
card_sprites_.at(3)->addPath(param.game.height, Y_DEST, PathType::VERTICAL, X_DEST, CARD_ANIM_DURATION_VERY_SLOW, easeInOutExpo, 0.0f);
card_sprites_.at(4)->addPath(-CARD_HEIGHT, Y_DEST, PathType::VERTICAL, X_DEST, CARD_ANIM_DURATION_MEDIUM, easeOutElastic, 0.0f);
card_sprites_.at(5)->addPath(-CARD_HEIGHT, Y_DEST, PathType::VERTICAL, X_DEST, CARD_ANIM_DURATION_SLOW, easeOutQuad, CARD_ANIM_DELAY_LONG);
card_sprites_.at(5)->addPath(-CARD_HEIGHT, Y_DEST, PathType::VERTICAL, X_DEST, CARD_ANIM_DURATION_SLOW, easeOutQuad, CARD_ANIM_DELAY_LONG_S);
card_sprites_.at(5)->addPath(X_DEST, -CARD_WIDTH, PathType::HORIZONTAL, Y_DEST, CARD_ANIM_DURATION_SHORT, easeInElastic, 0.0f);
// Constantes
@@ -357,7 +357,7 @@ void Intro::initSprites() {
shadow_texture->setBlendMode(SDL_BLENDMODE_BLEND);
// Apuntamos el renderizador a la textura
auto *temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
auto* temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
shadow_texture->setAsRenderTarget(Screen::get()->getRenderer());
// Limpia la textura
@@ -394,7 +394,7 @@ void Intro::initSprites() {
shadow_sprites_.at(2)->addPath(-SHADOW_SPRITE_WIDTH, S_X_DEST, PathType::HORIZONTAL, S_Y_DEST, CARD_ANIM_DURATION_FAST, easeOutQuint, 0.0f);
shadow_sprites_.at(3)->addPath(-SHADOW_SPRITE_HEIGHT, S_Y_DEST, PathType::VERTICAL, S_X_DEST, CARD_ANIM_DURATION_VERY_SLOW, easeInOutExpo, 0.0f);
shadow_sprites_.at(4)->addPath(param.game.height, S_Y_DEST, PathType::VERTICAL, S_X_DEST, CARD_ANIM_DURATION_MEDIUM, easeOutElastic, 0.0f);
shadow_sprites_.at(5)->addPath(param.game.width, S_X_DEST, PathType::HORIZONTAL, S_Y_DEST, CARD_ANIM_DURATION_SLOW, easeOutQuad, CARD_ANIM_DELAY_LONG);
shadow_sprites_.at(5)->addPath(param.game.width, S_X_DEST, PathType::HORIZONTAL, S_Y_DEST, CARD_ANIM_DURATION_SLOW, easeOutQuad, CARD_ANIM_DELAY_LONG_S);
shadow_sprites_.at(5)->addPath(S_X_DEST, param.game.width, PathType::HORIZONTAL, S_Y_DEST, CARD_ANIM_DURATION_SHORT, easeInElastic, 0.0f);
}
@@ -447,25 +447,25 @@ void Intro::initTexts() {
texts_.at(8)->setCaption(Lang::getText("[INTRO] 9"));
texts_.at(8)->setSpeedS(TEXT_SPEED_ULTRA_FAST);
for (auto &text : texts_) {
for (auto& text : texts_) {
text->center(param.game.game_area.center_x);
}
}
// Actualiza los sprites
void Intro::updateSprites(float delta_time) {
for (auto &sprite : card_sprites_) {
for (auto& sprite : card_sprites_) {
sprite->update(delta_time);
}
for (auto &sprite : shadow_sprites_) {
for (auto& sprite : shadow_sprites_) {
sprite->update(delta_time);
}
}
// Actualiza los textos
void Intro::updateTexts(float delta_time) {
for (auto &text : texts_) {
for (auto& text : texts_) {
text->updateS(delta_time); // Usar updateS para delta_time en segundos
}
}
@@ -478,7 +478,7 @@ void Intro::renderSprites() {
// Dibuja los textos
void Intro::renderTexts() {
for (const auto &text : texts_) {
for (const auto& text : texts_) {
text->render();
}
}

View File

@@ -65,8 +65,8 @@ class Intro {
static constexpr float CARD_ANIM_DURATION_SLOW = 250.0f / 60.0f; // ≈ 4.1667 s
static constexpr float CARD_ANIM_DURATION_VERY_SLOW = 300.0f / 60.0f; // ≈ 5.0000 s
static constexpr float CARD_ANIM_DELAY_LONG = 0.45f; // Retraso largo antes de animación
static constexpr float CARD_OFFSET_MARGIN = 10.0f; // Margen fuera de pantalla
static constexpr float CARD_ANIM_DELAY_LONG_S = 7.5F; // Retraso largo antes de animación
static constexpr float CARD_OFFSET_MARGIN = 10.0F; // Margen fuera de pantalla
// --- Estados internos ---
enum class State {

View File

@@ -91,10 +91,7 @@ void Title::update(float deltaTime) {
updateFade();
updateState(deltaTime);
updateStartPrompt(deltaTime);
for (auto& player : players_) {
player->update(deltaTime);
}
updatePlayers(deltaTime);
}
// Calcula el tiempo transcurrido desde el último frame
@@ -569,6 +566,13 @@ void Title::initPlayers() {
}
}
// Actualiza los jugadores
void Title::updatePlayers(float deltaTime) {
for (auto& player : players_) {
player->update(deltaTime);
}
}
// Renderiza los jugadores
void Title::renderPlayers() {
for (auto const& player : players_) {

View File

@@ -125,7 +125,7 @@ class Title {
// --- Gestión de jugadores ---
void initPlayers(); // Inicializa los jugadores
void updatePlayers(); // Actualiza los jugadores
void updatePlayers(float deltaTime); // Actualiza los jugadores
void renderPlayers(); // Renderiza los jugadores
auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador a partir de su "id"