treballant en Background i Stage

This commit is contained in:
2025-08-14 09:53:01 +02:00
parent ea3e704d34
commit b2139d8e06
6 changed files with 340 additions and 252 deletions

View File

@@ -15,11 +15,12 @@
// Constructor
Background::Background(float total_progress_to_complete)
: renderer_(Screen::get()->getRenderer()),
total_progress_to_complete_(total_progress_to_complete),
: total_progress_to_complete_(total_progress_to_complete),
progress_per_stage_(total_progress_to_complete_ / STAGES),
sun_completion_progress_(total_progress_to_complete_ * SUN_COMPLETION_FACTOR),
renderer_(Screen::get()->getRenderer()),
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")),
@@ -31,81 +32,16 @@ Background::Background(float total_progress_to_complete)
rect_(SDL_FRect{0, 0, static_cast<float>(gradients_texture_->getWidth() / 2), static_cast<float>(gradients_texture_->getHeight() / 2)}),
src_rect_({0, 0, 320, 240}),
dst_rect_({0, 0, 320, 240}),
base_(rect_.h),
attenuate_color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
alpha_color_texture_(param.background.attenuate_color.a),
previous_alpha_color_texture_(param.background.attenuate_color.a)
{
// Precalcula rutas
createSunPath();
createMoonPath();
// Inicializa variables
{
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i) {
top_clouds_rect_[i] = {0, i * TOP_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(top_clouds_texture_->getWidth()), TOP_CLOUDS_TEXTURE_HEIGHT};
bottom_clouds_rect_[i] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_CLOUDS_TEXTURE_HEIGHT};
}
}
// Crea los sprites
{
const float TOP_CLOUDS_Y = base_ - 165;
const float BOTTOM_CLOUDS_Y = base_ - 101;
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){0, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){rect_.w, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){0, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){rect_.w, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_);
gradient_sprite_ = std::make_unique<Sprite>(gradients_texture_, 0, 0, rect_.w, rect_.h);
grass_sprite_ = std::make_unique<Sprite>(grass_texture_, 0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2);
sun_sprite_ = std::make_unique<Sprite>(sun_texture_);
moon_sprite_ = std::make_unique<Sprite>(moon_texture_);
}
// Inicializa objetos
{
constexpr float TOP_CLOUDS_SPEED = 0.1F;
constexpr float BOTTOM_CLOUDS_SPEED = 0.05F;
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_a_->setVelX(-TOP_CLOUDS_SPEED);
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_b_->setVelX(-TOP_CLOUDS_SPEED);
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_a_->setVelX(-BOTTOM_CLOUDS_SPEED);
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_b_->setVelX(-BOTTOM_CLOUDS_SPEED);
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
sun_sprite_->setPosition(sun_path_.front());
moon_sprite_->setPosition(moon_path_.front());
}
// Crea la textura para componer el fondo
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
// Crea la textura para atenuar el fondo
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(attenuate_color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_texture_);
previous_alpha_color_texture_(param.background.attenuate_color.a),
base_(rect_.h) {
initializePaths();
initializeRects();
initializeSprites();
initializeSpriteProperties();
initializeTextures();
}
// Destructor
@@ -114,14 +50,88 @@ Background::~Background() {
SDL_DestroyTexture(color_texture_);
}
// Inicializa las rutas del sol y la luna
void Background::initializePaths() {
createSunPath();
createMoonPath();
}
// Inicializa los rectángulos de gradientes y nubes
void Background::initializeRects() {
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i) {
top_clouds_rect_[i] = {0, i * TOP_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(top_clouds_texture_->getWidth()), TOP_CLOUDS_TEXTURE_HEIGHT};
bottom_clouds_rect_[i] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_CLOUDS_TEXTURE_HEIGHT};
}
}
// Crea los sprites
void Background::initializeSprites() {
const float TOP_CLOUDS_Y = base_ - 165;
const float BOTTOM_CLOUDS_Y = base_ - 101;
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){0, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){rect_.w, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){0, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){rect_.w, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_);
gradient_sprite_ = std::make_unique<Sprite>(gradients_texture_, 0, 0, rect_.w, rect_.h);
grass_sprite_ = std::make_unique<Sprite>(grass_texture_, 0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2);
sun_sprite_ = std::make_unique<Sprite>(sun_texture_);
moon_sprite_ = std::make_unique<Sprite>(moon_texture_);
}
// Configura las propiedades iniciales de los sprites
void Background::initializeSpriteProperties() {
constexpr float TOP_CLOUDS_SPEED = 0.1F;
constexpr float BOTTOM_CLOUDS_SPEED = 0.05F;
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_a_->setVelX(-TOP_CLOUDS_SPEED);
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_b_->setVelX(-TOP_CLOUDS_SPEED);
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_a_->setVelX(-BOTTOM_CLOUDS_SPEED);
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_b_->setVelX(-BOTTOM_CLOUDS_SPEED);
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
sun_sprite_->setPosition(sun_path_.front());
moon_sprite_->setPosition(moon_path_.front());
}
// Inicializa las texturas de renderizado
void Background::initializeTextures() {
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(attenuate_color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_texture_);
}
// Actualiza la lógica del objeto
void Background::update() {
// Actualiza la progresión y calcula transiciones (solo si no está en modo manual)
// Actualiza la progresión y calcula transiciones
if (!manual_mode_) {
updateProgression();
}
// Actualiza el valor de alpha_
// Actualiza el valor de alpha
updateAlphaColorTexture();
// Actualiza las nubes
@@ -130,7 +140,7 @@ void Background::update() {
// Calcula el frame de la hierba
grass_sprite_->setSpriteClip(0, (10 * (counter_ / 20 % 2)), 320, 10);
// Calcula el valor de alpha_
// Calcula el valor de alpha
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// Mueve el sol y la luna según la progresión
@@ -147,8 +157,25 @@ void Background::update() {
// Incrementa la progresión interna
void Background::incrementProgress(float amount) {
if (state_ == State::NORMAL) {
float old_progress = progress_;
progress_ += amount;
progress_ = std::min(progress_, total_progress_to_complete_);
// Notifica el cambio si hay callback y el progreso cambió
if (progress_callback_ && progress_ != old_progress) {
progress_callback_(progress_);
}
}
}
// Establece la progresión absoluta
void Background::setProgress(float absolute_progress) {
float old_progress = progress_;
progress_ = std::clamp(absolute_progress, 0.0f, total_progress_to_complete_);
// Notifica el cambio si hay callback y el progreso cambió
if (progress_callback_ && progress_ != old_progress) {
progress_callback_(progress_);
}
}
@@ -159,6 +186,7 @@ void Background::setState(State new_state) {
// Reinicia la progresión
void Background::reset() {
float old_progress = progress_;
progress_ = 0.0f;
state_ = State::NORMAL;
manual_mode_ = false;
@@ -166,6 +194,11 @@ void Background::reset() {
transition_ = 0.0f;
sun_index_ = 0;
moon_index_ = 0;
// Notifica el cambio si hay callback
if (progress_callback_ && progress_ != old_progress) {
progress_callback_(progress_);
}
}
// Activa/desactiva el modo manual
@@ -173,9 +206,26 @@ void Background::setManualMode(bool manual) {
manual_mode_ = manual;
}
// Establece callback para sincronización automática
void Background::setProgressCallback(ProgressCallback callback) {
progress_callback_ = callback;
}
// Elimina el callback
void Background::removeProgressCallback() {
progress_callback_ = nullptr;
}
// Ajusta la velocidad de las nubes
void Background::setCloudsSpeed(float value) {
clouds_speed_ = value;
// En modo manual, aplicar la velocidad directamente
// Las nubes inferiores van a la mitad de velocidad que las superiores
top_clouds_sprite_a_->setVelX(value);
top_clouds_sprite_b_->setVelX(value);
bottom_clouds_sprite_a_->setVelX(value / 2.0f);
bottom_clouds_sprite_b_->setVelX(value / 2.0f);
}
// Establece el degradado de fondo
@@ -212,10 +262,10 @@ void Background::updateProgression() {
}
// Calcula la transición de los diferentes fondos
const float gradient_float = std::min(progress_ / progress_per_stage_, static_cast<float>(STAGES - 1));
const float percent = gradient_float - static_cast<int>(gradient_float);
gradient_number_ = static_cast<size_t>(gradient_float);
const float gradient_number_float = std::min(progress_ / progress_per_stage_, 3.0F);
const float percent = gradient_number_float - static_cast<int>(gradient_number_float);
gradient_number_ = static_cast<size_t>(gradient_number_float);
transition_ = percent;
// Calcula la posición del sol
@@ -232,22 +282,60 @@ void Background::updateProgression() {
// Actualiza la velocidad de las nubes según el estado y progresión
void Background::updateCloudsSpeed() {
// Velocidades base
constexpr float BASE_TOP_CLOUDS_SPEED = -0.1F;
constexpr float BASE_BOTTOM_CLOUDS_SPEED = -0.05F;
// Cálculo de velocidad según progreso
constexpr float CLOUDS_INITIAL_SPEED = 0.05F;
constexpr float CLOUDS_FINAL_SPEED = 2.00F - CLOUDS_INITIAL_SPEED;
// Velocidad base según progreso (de -0.05 a -2.00)
float base_clouds_speed = (-CLOUDS_INITIAL_SPEED) +
(-CLOUDS_FINAL_SPEED * (progress_ / total_progress_to_complete_));
// Factor de velocidad basado en la progresión (más rápido durante el día)
float speed_factor = 1.0f;
// En estado completado, las nubes se ralentizan gradualmente
if (state_ == State::COMPLETED) {
// Factor de ralentización basado en qué tan cerca está de MINIMUM_COMPLETED_PROGRESS
float completion_factor = (progress_ - MINIMUM_COMPLETED_PROGRESS) /
(total_progress_to_complete_ - MINIMUM_COMPLETED_PROGRESS);
speed_factor = std::max(0.1f, completion_factor);
float completion_factor = (progress_ - MINIMUM_COMPLETED_PROGRESS) /
(total_progress_to_complete_ - MINIMUM_COMPLETED_PROGRESS);
completion_factor = std::max(0.1f, completion_factor);
base_clouds_speed *= completion_factor;
}
clouds_speed_ = BASE_TOP_CLOUDS_SPEED * speed_factor;
// Aplicar velocidades diferentes para nubes superiores e inferiores
const float top_clouds_speed = base_clouds_speed;
const float bottom_clouds_speed = base_clouds_speed / 2.0f;
// Aplicar las velocidades a los sprites correspondientes
top_clouds_sprite_a_->setVelX(top_clouds_speed);
top_clouds_sprite_b_->setVelX(top_clouds_speed);
bottom_clouds_sprite_a_->setVelX(bottom_clouds_speed);
bottom_clouds_sprite_b_->setVelX(bottom_clouds_speed);
// Guardar la velocidad principal
clouds_speed_ = top_clouds_speed;
}
// Actualiza las nubes
void Background::updateClouds() {
// Mueve las nubes
top_clouds_sprite_a_->update();
top_clouds_sprite_b_->update();
bottom_clouds_sprite_a_->update();
bottom_clouds_sprite_b_->update();
// Calcula el offset de las nubes
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
}
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
}
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
}
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
}
}
// Dibuja el gradiente de fondo
@@ -346,7 +434,7 @@ void Background::setPos(SDL_FRect pos) {
src_rect_.h = pos.h;
}
// Establece el color_ de atenuación
// Establece el color de atenuación
void Background::setColor(Color color) {
attenuate_color_ = color;
@@ -363,14 +451,14 @@ void Background::setColor(Color color) {
// Establece la transparencia de la atenuación
void Background::setAlpha(int alpha) {
// Evita que se asignen valores fuera de rango
alpha_ = std::clamp(alpha, 0, 255);
alpha = std::clamp(alpha, 0, 255);
// Guarda el valor actual y establece el nuevo valor
previous_alpha_color_texture_ = alpha_color_texture_;
alpha_color_texture_ = alpha_;
alpha_color_texture_ = alpha;
}
// Actualiza el valor de alpha_
// Actualiza el valor de alpha
void Background::updateAlphaColorTexture() {
if (alpha_color_texture_ == previous_alpha_color_texture_) {
return;
@@ -379,38 +467,6 @@ void Background::updateAlphaColorTexture() {
SDL_SetTextureAlphaMod(color_texture_, previous_alpha_color_texture_);
}
// Actualiza las nubes
void Background::updateClouds() {
// Aplica la velocidad calculada a las nubes
top_clouds_sprite_a_->setVelX(clouds_speed_);
top_clouds_sprite_b_->setVelX(clouds_speed_);
bottom_clouds_sprite_a_->setVelX(clouds_speed_ / 2);
bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2);
// Mueve las nubes
top_clouds_sprite_a_->update();
top_clouds_sprite_b_->update();
bottom_clouds_sprite_a_->update();
bottom_clouds_sprite_b_->update();
// Calcula el offset de las nubes
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
}
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
}
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
}
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
}
}
// Precalcula el vector con el recorrido del sol
void Background::createSunPath() {
constexpr float CENTER_X = 170;

View File

@@ -2,10 +2,11 @@
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_FPoint, SDL_Texture, SDL_Renderer
#include <array> // Para array
#include <cstddef> // Para size_t
#include <memory> // Para unique_ptr, shared_ptr
#include <vector> // Para vector
#include <array> // Para array
#include <cstddef> // Para size_t
#include <functional> // Para std::function
#include <memory> // Para unique_ptr, shared_ptr
#include <vector> // Para vector
#include "color.h" // Para Color
@@ -50,16 +51,22 @@ class Background {
// Control de progresión
void incrementProgress(float amount = 1.0f); // Incrementa la progresión interna
void setProgress(float absolute_progress); // Establece la progresión absoluta
void setState(State new_state); // Cambia el estado del fondo
void reset(); // Reinicia la progresión
// Sistema de callback para sincronización automática
using ProgressCallback = std::function<void(float)>;
void setProgressCallback(ProgressCallback callback); // Establece callback para sincronización
void removeProgressCallback(); // Elimina el callback
// Configuración manual (para uso fuera del juego principal)
void setManualMode(bool manual); // Activa/desactiva el modo manual
void setCloudsSpeed(float value); // Ajusta la velocidad de las nubes
void setGradientNumber(int value); // Establece el degradado de fondo
void setTransition(float value); // Ajusta la transición entre texturas
void setSunProgression(float progress); // Establece la posición del sol
void setMoonProgression(float progress); // Establece la posición de la luna
void setManualMode(bool manual); // Activa/desactiva el modo manual
void setCloudsSpeed(float value); // Ajusta la velocidad de las nubes
void setGradientNumber(int value); // Establece el degradado de fondo
void setTransition(float value); // Ajusta la transición entre texturas
void setSunProgression(float progress); // Establece la posición del sol
void setMoonProgression(float progress); // Establece la posición de la luna
// Configuración de efectos visuales
void setColor(Color color); // Establece el color de atenuación
@@ -111,8 +118,9 @@ class Background {
// Variables de estado y progresión
State state_ = State::NORMAL;
float progress_ = 0.0f; // Progresión interna (0 a total_progress_to_complete_)
bool manual_mode_ = false; // Si está en modo manual, no actualiza automáticamente
float progress_ = 0.0f; // Progresión interna (0 a total_progress_to_complete_)
bool manual_mode_ = false; // Si está en modo manual, no actualiza automáticamente
ProgressCallback progress_callback_; // Callback para notificar cambios de progreso
// Variables de renderizado
SDL_FRect rect_; // Tamaño del objeto
@@ -140,14 +148,19 @@ class Background {
Uint8 alpha_ = 0; // Transparencia entre fases
// Métodos internos
void updateProgression(); // Actualiza la progresión y calcula transiciones (solo si no está en modo manual)
void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado
void renderGradient(); // Dibuja el gradiente de fondo
void renderTopClouds(); // Dibuja las nubes superiores
void renderBottomClouds(); // Dibuja las nubes inferiores
void fillCanvas(); // Compone todos los elementos en la textura
void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación
void updateClouds(); // Actualiza el movimiento de las nubes
void createSunPath(); // Precalcula el recorrido del sol
void createMoonPath(); // Precalcula el recorrido de la luna
void initializePaths(); // Inicializa las rutas del sol y la luna
void initializeRects(); // Inicializa los rectángulos de gradientes y nubes
void initializeSprites(); // Crea los sprites
void initializeSpriteProperties(); // Configura las propiedades iniciales de los sprites
void initializeTextures(); // Inicializa las texturas de renderizado
void updateProgression(); // Actualiza la progresión y calcula transiciones
void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado
void renderGradient(); // Dibuja el gradiente de fondo
void renderTopClouds(); // Dibuja las nubes superiores
void renderBottomClouds(); // Dibuja las nubes inferiores
void fillCanvas(); // Compone todos los elementos en la textura
void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación
void updateClouds(); // Actualiza el movimiento de las nubes
void createSunPath(); // Precalcula el recorrido del sol
void createMoonPath(); // Precalcula el recorrido de la luna
};

View File

@@ -52,13 +52,13 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
: renderer_(Screen::get()->getRenderer()),
screen_(Screen::get()),
input_(Input::get()),
background_(std::make_unique<Background>()),
canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)),
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())),
background_(std::make_unique<Background>(stage_manager_->getTotalPowerNeededToCompleteGame())),
fade_in_(std::make_unique<Fade>()),
fade_out_(std::make_unique<Fade>()),
balloon_manager_(std::make_unique<BalloonManager>(stage_manager_.get())),
tabe_(std::make_unique<Tabe>()),
hit_(Hit(Resource::get()->getTexture("hit.png"))) {
// Pasa variables
@@ -68,6 +68,7 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
Section::name = Section::Name::GAME;
Section::options = Section::Options::NONE;
stage_manager_->initialize();
stage_manager_->setPowerChangeCallback([this](int amount) { background_->incrementProgress(amount); });
stage_manager_->jumpToStage(current_stage);
// Asigna texturas y animaciones

View File

@@ -101,29 +101,28 @@ class Game {
Input *input_; // Manejador de entrada
Scoreboard *scoreboard_; // Objeto para dibujar el marcador
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
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
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
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<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
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados

View File

@@ -1,14 +1,16 @@
#include "stage.h"
#include <algorithm>
// ===== IMPLEMENTACIÓN DE StageData =====
StageData::StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name)
: power_to_complete_(power_to_complete), min_menace_(min_menace), max_menace_(max_menace), name_(name), status_(StageStatus::LOCKED) {}
: power_to_complete_(power_to_complete), min_menace_(min_menace),
max_menace_(max_menace), name_(name), status_(StageStatus::LOCKED) {}
// ===== IMPLEMENTACIÓN DE StageManager =====
StageManager::StageManager()
: current_power_(0), total_power_(0), current_stage_index_(0), power_collection_state_(PowerCollectionState::ENABLED) {
: current_power_(0), total_power_(0), current_stage_index_(0),
power_collection_state_(PowerCollectionState::ENABLED),
power_change_callback_(nullptr) {
initialize();
}
@@ -44,9 +46,9 @@ bool StageManager::advanceToNextStage() {
if (!isCurrentStageCompleted() || current_stage_index_ >= stages_.size() - 1) {
return false;
}
current_stage_index_++;
current_power_ = 0; // Reiniciar poder para la nueva fase
current_power_ = 0; // Reiniciar poder para la nueva fase
updateStageStatuses();
return true;
}
@@ -55,18 +57,18 @@ bool StageManager::jumpToStage(size_t target_stage_index) {
if (!validateStageIndex(target_stage_index)) {
return false;
}
// Calcular el poder total acumulado hasta la fase objetivo
int accumulated_power = 0;
for (size_t i = 0; i < target_stage_index; ++i) {
accumulated_power += stages_[i].getPowerToComplete();
}
// Actualizar estado
current_stage_index_ = target_stage_index;
current_power_ = 0; // Empezar la fase objetivo sin poder
current_power_ = 0; // Empezar la fase objetivo sin poder
total_power_ = accumulated_power; // Poder total como si hubiéramos completado las anteriores
updateStageStatuses();
return true;
}
@@ -75,7 +77,7 @@ bool StageManager::subtractPower(int amount) {
if (amount <= 0 || current_power_ < amount) {
return false;
}
current_power_ -= amount;
updateStageStatuses();
return true;
@@ -105,7 +107,7 @@ bool StageManager::isCurrentStageCompleted() const {
if (!current_stage.has_value()) {
return false;
}
return current_power_ >= current_stage->getPowerToComplete();
}
@@ -115,10 +117,10 @@ bool StageManager::isGameCompleted() const {
double StageManager::getProgressPercentage() const {
if (stages_.empty()) return 0.0;
int total_power_needed = getTotalPowerNeededToCompleteGame();
int total_power_needed = getTotalPowerNeededToCompleteGame(); // ⬅️ Usar el nuevo método
if (total_power_needed == 0) return 100.0;
return (static_cast<double>(total_power_) / total_power_needed) * 100.0;
}
@@ -131,12 +133,12 @@ double StageManager::getCurrentStageProgressFraction() const {
if (!current_stage.has_value()) {
return 0.0;
}
int power_needed = current_stage->getPowerToComplete();
if (power_needed == 0) {
return 1.0;
}
// Retorna fracción entre 0.0 y 1.0
double fraction = static_cast<double>(current_power_) / power_needed;
return std::min(fraction, 1.0);
@@ -147,7 +149,7 @@ int StageManager::getPowerNeededForCurrentStage() const {
if (!current_stage.has_value()) {
return 0;
}
return std::max(0, current_stage->getPowerToComplete() - current_power_);
}
@@ -168,10 +170,14 @@ void StageManager::addPower(int amount) {
if (amount <= 0 || !canCollectPower()) {
return;
}
current_power_ += amount;
total_power_ += amount;
if (power_change_callback_) {
power_change_callback_(amount);
}
// Verificar si se completó la fase actual
if (isCurrentStageCompleted()) {
auto current_stage = getCurrentStage();
@@ -179,7 +185,7 @@ void StageManager::addPower(int amount) {
stages_[current_stage_index_].setStatus(StageStatus::COMPLETED);
}
}
updateStageStatuses();
}
@@ -188,7 +194,7 @@ int StageManager::getCurrentMenaceLevel() const {
if (!current_stage.has_value()) {
return 0;
}
return current_stage->getMinMenace();
}
@@ -207,4 +213,12 @@ void StageManager::updateStageStatuses() {
stages_[i].setStatus(StageStatus::LOCKED);
}
}
}
void StageManager::setPowerChangeCallback(PowerChangeCallback callback) {
power_change_callback_ = callback;
}
void StageManager::removePowerChangeCallback() {
power_change_callback_ = nullptr;
}

View File

@@ -1,10 +1,10 @@
#pragma once
#include "stage_interface.h"
#include <vector>
#include <optional>
#include <string>
#include <vector>
#include "stage_interface.h"
#include <functional> // ⬅️ Para std::function
enum class PowerCollectionState {
ENABLED,
@@ -18,79 +18,84 @@ enum class StageStatus {
};
class StageData {
private:
int power_to_complete_;
int min_menace_;
int max_menace_;
std::string name_;
StageStatus status_;
private:
int power_to_complete_;
int min_menace_;
int max_menace_;
std::string name_;
StageStatus status_;
public:
StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name = "");
public:
StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name = "");
// Getters
int getPowerToComplete() const { return power_to_complete_; }
int getMinMenace() const { return min_menace_; }
int getMaxMenace() const { return max_menace_; }
const std::string& getName() const { return name_; }
StageStatus getStatus() const { return status_; }
// Getters
int getPowerToComplete() const { return power_to_complete_; }
int getMinMenace() const { return min_menace_; }
int getMaxMenace() const { return max_menace_; }
const std::string& getName() const { return name_; }
StageStatus getStatus() const { return status_; }
// Setters
void setStatus(StageStatus status) { status_ = status; }
// Utilidades
bool isCompleted() const { return status_ == StageStatus::COMPLETED; }
// Setters
void setStatus(StageStatus status) { status_ = status; }
// Utilidades
bool isCompleted() const { return status_ == StageStatus::COMPLETED; }
};
class StageManager : public IStageInfo { // Hereda de la interfaz
private:
std::vector<StageData> stages_;
int current_power_;
int total_power_;
size_t current_stage_index_;
PowerCollectionState power_collection_state_;
class StageManager : public IStageInfo { // ⬅️ Hereda de la interfaz
private:
std::vector<StageData> stages_;
int current_power_;
int total_power_;
size_t current_stage_index_;
PowerCollectionState power_collection_state_;
public:
StageManager();
public:
StageManager();
// Métodos principales para Game
void initialize();
void reset();
bool advanceToNextStage();
// Gestión de poder
bool subtractPower(int amount);
void enablePowerCollection();
void disablePowerCollection();
// Navegación avanzada
bool jumpToStage(size_t target_stage_index);
// Consultas de estado
std::optional<StageData> getCurrentStage() const;
std::optional<StageData> getStage(size_t index) const;
size_t getCurrentStageIndex() const { return current_stage_index_; }
int getCurrentPower() const { return current_power_; }
int getTotalPower() const { return total_power_; }
int getTotalPowerNeededToCompleteGame() const; // ⬅️ Nuevo método
size_t getTotalStages() const { return stages_.size(); }
// Progreso
bool isCurrentStageCompleted() const;
bool isGameCompleted() const;
double getProgressPercentage() const; // Progreso total del juego
double getCurrentStageProgressPercentage() const; // Progreso de la fase actual (0-100%)
double getCurrentStageProgressFraction() const; // Progreso de la fase actual (0.0-1.0)
int getPowerNeededForCurrentStage() const;
// ===== IMPLEMENTACIÓN DE IStageInfo =====
// (Esto es lo que ven Player y Balloon)
bool canCollectPower() const override;
void addPower(int amount) override;
int getCurrentMenaceLevel() const override;
using PowerChangeCallback = std::function<void(int)>;
void setPowerChangeCallback(PowerChangeCallback callback);
void removePowerChangeCallback();
// Métodos principales para Game
void initialize();
void reset();
bool advanceToNextStage();
private:
PowerChangeCallback power_change_callback_;
// Gestión de poder
bool subtractPower(int amount);
void enablePowerCollection();
void disablePowerCollection();
// Navegación avanzada
bool jumpToStage(size_t target_stage_index);
// Consultas de estado
std::optional<StageData> getCurrentStage() const;
std::optional<StageData> getStage(size_t index) const;
size_t getCurrentStageIndex() const { return current_stage_index_; }
int getCurrentPower() const { return current_power_; }
int getTotalPower() const { return total_power_; }
int getTotalPowerNeededToCompleteGame() const;
size_t getTotalStages() const { return stages_.size(); }
// Progreso
bool isCurrentStageCompleted() const;
bool isGameCompleted() const;
double getProgressPercentage() const; // Progreso total del juego
double getCurrentStageProgressPercentage() const; // Progreso de la fase actual (0-100%)
double getCurrentStageProgressFraction() const; // Progreso de la fase actual (0.0-1.0)
int getPowerNeededForCurrentStage() const;
// ===== IMPLEMENTACIÓN DE IStageInfo =====
// (Esto es lo que ven Player y Balloon)
bool canCollectPower() const override;
void addPower(int amount) override;
int getCurrentMenaceLevel() const override;
private:
void createDefaultStages();
bool validateStageIndex(size_t index) const;
void updateStageStatuses();
void createDefaultStages();
bool validateStageIndex(size_t index) const;
void updateStageStatuses();
};