posant ordre en Stage i Background
This commit is contained in:
@@ -14,8 +14,11 @@
|
||||
#include "texture.h" // Para Texture
|
||||
|
||||
// Constructor
|
||||
Background::Background()
|
||||
Background::Background(float total_progress_to_complete)
|
||||
: renderer_(Screen::get()->getRenderer()),
|
||||
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),
|
||||
|
||||
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
|
||||
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
|
||||
@@ -30,8 +33,8 @@ Background::Background()
|
||||
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_text_(param.background.attenuate_color.a),
|
||||
alpha_color_text_temp_(param.background.attenuate_color.a)
|
||||
alpha_color_texture_(param.background.attenuate_color.a),
|
||||
previous_alpha_color_texture_(param.background.attenuate_color.a)
|
||||
|
||||
{
|
||||
// Precalcula rutas
|
||||
@@ -102,7 +105,7 @@ Background::Background()
|
||||
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_text_);
|
||||
SDL_SetTextureAlphaMod(color_texture_, alpha_color_texture_);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@@ -113,6 +116,11 @@ Background::~Background() {
|
||||
|
||||
// Actualiza la lógica del objeto
|
||||
void Background::update() {
|
||||
// Actualiza la progresión y calcula transiciones (solo si no está en modo manual)
|
||||
if (!manual_mode_) {
|
||||
updateProgression();
|
||||
}
|
||||
|
||||
// Actualiza el valor de alpha_
|
||||
updateAlphaColorTexture();
|
||||
|
||||
@@ -125,7 +133,7 @@ void Background::update() {
|
||||
// Calcula el valor de alpha_
|
||||
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
|
||||
|
||||
// Mueve el sol
|
||||
// Mueve el sol y la luna según la progresión
|
||||
sun_sprite_->setPosition(sun_path_.at(sun_index_));
|
||||
moon_sprite_->setPosition(moon_path_.at(moon_index_));
|
||||
|
||||
@@ -136,6 +144,112 @@ void Background::update() {
|
||||
fillCanvas();
|
||||
}
|
||||
|
||||
// Incrementa la progresión interna
|
||||
void Background::incrementProgress(float amount) {
|
||||
if (state_ == State::NORMAL) {
|
||||
progress_ += amount;
|
||||
progress_ = std::min(progress_, total_progress_to_complete_);
|
||||
}
|
||||
}
|
||||
|
||||
// Cambia el estado del fondo
|
||||
void Background::setState(State new_state) {
|
||||
state_ = new_state;
|
||||
}
|
||||
|
||||
// Reinicia la progresión
|
||||
void Background::reset() {
|
||||
progress_ = 0.0f;
|
||||
state_ = State::NORMAL;
|
||||
manual_mode_ = false;
|
||||
gradient_number_ = 0;
|
||||
transition_ = 0.0f;
|
||||
sun_index_ = 0;
|
||||
moon_index_ = 0;
|
||||
}
|
||||
|
||||
// Activa/desactiva el modo manual
|
||||
void Background::setManualMode(bool manual) {
|
||||
manual_mode_ = manual;
|
||||
}
|
||||
|
||||
// Ajusta la velocidad de las nubes
|
||||
void Background::setCloudsSpeed(float value) {
|
||||
clouds_speed_ = value;
|
||||
}
|
||||
|
||||
// Establece el degradado de fondo
|
||||
void Background::setGradientNumber(int value) {
|
||||
gradient_number_ = value % STAGES;
|
||||
}
|
||||
|
||||
// Ajusta la transición entre texturas
|
||||
void Background::setTransition(float value) {
|
||||
transition_ = std::clamp(value, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
// Establece la posición del sol
|
||||
void Background::setSunProgression(float progress) {
|
||||
progress = std::clamp(progress, 0.0F, 1.0F);
|
||||
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
|
||||
}
|
||||
|
||||
// Establece la posición de la luna
|
||||
void Background::setMoonProgression(float progress) {
|
||||
progress = std::clamp(progress, 0.0F, 1.0F);
|
||||
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
|
||||
}
|
||||
|
||||
// Actualiza la progresión y calcula las transiciones
|
||||
void Background::updateProgression() {
|
||||
// Si el juego está completado, reduce la progresión gradualmente
|
||||
if (state_ == State::COMPLETED) {
|
||||
if (progress_ > MINIMUM_COMPLETED_PROGRESS) {
|
||||
progress_ -= COMPLETED_REDUCTION_RATE;
|
||||
} else {
|
||||
progress_ = MINIMUM_COMPLETED_PROGRESS;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
transition_ = percent;
|
||||
|
||||
// Calcula la posición del sol
|
||||
const float sun_progression = std::min(progress_ / sun_completion_progress_, 1.0f);
|
||||
sun_index_ = static_cast<size_t>(sun_progression * (sun_path_.size() - 1));
|
||||
|
||||
// Calcula la posición de la luna
|
||||
const float moon_progression = std::min(progress_ / total_progress_to_complete_, 1.0f);
|
||||
moon_index_ = static_cast<size_t>(moon_progression * (moon_path_.size() - 1));
|
||||
|
||||
// Actualiza la velocidad de las nubes
|
||||
updateCloudsSpeed();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
clouds_speed_ = BASE_TOP_CLOUDS_SPEED * speed_factor;
|
||||
}
|
||||
|
||||
// Dibuja el gradiente de fondo
|
||||
void Background::renderGradient() {
|
||||
// Dibuja el gradiente de detras
|
||||
@@ -221,21 +335,6 @@ void Background::render() {
|
||||
SDL_RenderTexture(renderer_, color_texture_, &src_rect_, &dst_rect_);
|
||||
}
|
||||
|
||||
// Ajusta el valor de la variable
|
||||
void Background::setCloudsSpeed(float value) {
|
||||
clouds_speed_ = value;
|
||||
}
|
||||
|
||||
// Ajusta el valor de la variable
|
||||
void Background::setGradientNumber(int value) {
|
||||
gradient_number_ = value % 4;
|
||||
}
|
||||
|
||||
// Ajusta el valor de la variable
|
||||
void Background::setTransition(float value) {
|
||||
transition_ = std::clamp(value, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
// Establece la posición del objeto
|
||||
void Background::setPos(SDL_FRect pos) {
|
||||
dst_rect_ = pos;
|
||||
@@ -267,17 +366,17 @@ void Background::setAlpha(int alpha) {
|
||||
alpha_ = std::clamp(alpha, 0, 255);
|
||||
|
||||
// Guarda el valor actual y establece el nuevo valor
|
||||
alpha_color_text_temp_ = alpha_color_text_;
|
||||
alpha_color_text_ = alpha_;
|
||||
previous_alpha_color_texture_ = alpha_color_texture_;
|
||||
alpha_color_texture_ = alpha_;
|
||||
}
|
||||
|
||||
// Actualiza el valor de alpha_
|
||||
void Background::updateAlphaColorTexture() {
|
||||
if (alpha_color_text_ == alpha_color_text_temp_) {
|
||||
if (alpha_color_texture_ == previous_alpha_color_texture_) {
|
||||
return;
|
||||
}
|
||||
alpha_color_text_ > alpha_color_text_temp_ ? ++alpha_color_text_temp_ : --alpha_color_text_temp_;
|
||||
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_temp_);
|
||||
alpha_color_texture_ > previous_alpha_color_texture_ ? ++previous_alpha_color_texture_ : --previous_alpha_color_texture_;
|
||||
SDL_SetTextureAlphaMod(color_texture_, previous_alpha_color_texture_);
|
||||
}
|
||||
|
||||
// Actualiza las nubes
|
||||
@@ -353,16 +452,4 @@ void Background::createMoonPath() {
|
||||
float y = CENTER_Y - (RADIUS * sin(theta));
|
||||
moon_path_.push_back({x, y});
|
||||
}
|
||||
}
|
||||
|
||||
// Establece la posición del sol
|
||||
void Background::setSunProgression(float progress) {
|
||||
progress = std::clamp(progress, 0.0F, 1.0F);
|
||||
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
|
||||
}
|
||||
|
||||
// Establece la posición de la luna
|
||||
void Background::setMoonProgression(float progress) {
|
||||
progress = std::clamp(progress, 0.0F, 1.0F);
|
||||
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
|
||||
}
|
||||
@@ -16,21 +16,29 @@ class Texture;
|
||||
/*
|
||||
Esta clase gestiona el fondo que aparece en la sección jugable.
|
||||
|
||||
Usa una textura compuesta y una capa superior con un color sólido cuya opacidad es ajustable.
|
||||
Su área total está definida por "rect", pero solo se pinta la región "srcRect" en la pantalla en "dstRect".
|
||||
Maneja internamente su progresión a través de diferentes estados del día/noche,
|
||||
controlando las transiciones entre gradientes, posiciones del sol/luna y velocidad de nubes.
|
||||
|
||||
Estados:
|
||||
- NORMAL: Progresión normal del día
|
||||
- COMPLETED: Reducción gradual de la actividad (nubes más lentas)
|
||||
|
||||
Métodos clave:
|
||||
- setCloudsSpeed(float value) -> Define la velocidad de las nubes
|
||||
- setGradientNumber(int value) -> Ajusta el índice del color de cielo
|
||||
- setTransition(float value) -> Configura la transición entre texturas
|
||||
- setColor(Color color) -> Aplica un color de atenuación
|
||||
- setAlpha(int alpha) -> Ajusta la transparencia de la capa de atenuación
|
||||
- incrementProgress() -> Avanza la progresión del fondo
|
||||
- setState() -> Cambia el estado del fondo
|
||||
- setColor/setAlpha -> Efectos de atenuación
|
||||
*/
|
||||
|
||||
class Background {
|
||||
public:
|
||||
// Enumeración de estados
|
||||
enum class State {
|
||||
NORMAL,
|
||||
COMPLETED
|
||||
};
|
||||
|
||||
// Constructor y Destructor
|
||||
Background();
|
||||
Background(float total_progress_to_complete = 6100.0f);
|
||||
~Background();
|
||||
|
||||
// Actualización y renderizado
|
||||
@@ -40,20 +48,40 @@ class Background {
|
||||
// Configuración de posición
|
||||
void setPos(SDL_FRect pos); // Establece la posición del objeto
|
||||
|
||||
// Configuración de animaciones y efectos
|
||||
void setCloudsSpeed(float value); // Ajusta la velocidad de desplazamiento de las nubes
|
||||
void setGradientNumber(int value); // Establece el degradado de fondo a usar
|
||||
void setTransition(float value); // Ajusta la transición entre texturas de fondo
|
||||
// Control de progresión
|
||||
void incrementProgress(float amount = 1.0f); // Incrementa la progresión interna
|
||||
void setState(State new_state); // Cambia el estado del fondo
|
||||
void reset(); // Reinicia la progresión
|
||||
|
||||
// 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
|
||||
|
||||
// Configuración de efectos visuales
|
||||
void setColor(Color color); // Establece el color de atenuación
|
||||
void setAlpha(int alpha); // Ajusta la transparencia del fondo
|
||||
|
||||
// Configuración del sol y la luna
|
||||
void setSunProgression(float progress); // Establece la posición del sol
|
||||
void setMoonProgression(float progress); // Establece la posición de la luna
|
||||
// Getters para información del estado
|
||||
float getProgress() const { return progress_; }
|
||||
State getState() const { return state_; }
|
||||
int getCurrentGradient() const { return static_cast<int>(gradient_number_); }
|
||||
|
||||
private:
|
||||
// Constantes de configuración
|
||||
static constexpr size_t STAGES = 4;
|
||||
static constexpr float COMPLETED_REDUCTION_RATE = 25.0f;
|
||||
static constexpr float MINIMUM_COMPLETED_PROGRESS = 200.0f;
|
||||
static constexpr float SUN_COMPLETION_FACTOR = 0.5f; // El sol completa su recorrido a la mitad del progreso total
|
||||
|
||||
// Configuración paramétrica
|
||||
const float total_progress_to_complete_;
|
||||
const float progress_per_stage_;
|
||||
const float sun_completion_progress_;
|
||||
|
||||
// Objetos y punteros
|
||||
SDL_Renderer *renderer_; // Renderizador de la ventana
|
||||
|
||||
@@ -81,28 +109,39 @@ class Background {
|
||||
SDL_Texture *canvas_; // Textura para componer el fondo
|
||||
SDL_Texture *color_texture_; // Textura para atenuar el fondo
|
||||
|
||||
// Variables de control
|
||||
std::array<SDL_FRect, 4> gradient_rect_;
|
||||
std::array<SDL_FRect, 4> top_clouds_rect_;
|
||||
std::array<SDL_FRect, 4> bottom_clouds_rect_;
|
||||
int gradient_number_ = 0;
|
||||
int alpha_ = 0;
|
||||
float clouds_speed_ = 0;
|
||||
float transition_ = 0;
|
||||
int counter_ = 0;
|
||||
SDL_FRect rect_;
|
||||
SDL_FRect src_rect_;
|
||||
SDL_FRect dst_rect_;
|
||||
int base_;
|
||||
Color attenuate_color_;
|
||||
int alpha_color_text_;
|
||||
int alpha_color_text_temp_;
|
||||
std::vector<SDL_FPoint> sun_path_;
|
||||
std::vector<SDL_FPoint> moon_path_;
|
||||
size_t sun_index_ = 0;
|
||||
size_t moon_index_ = 0;
|
||||
// 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
|
||||
|
||||
// Variables de renderizado
|
||||
SDL_FRect rect_; // Tamaño del objeto
|
||||
SDL_FRect src_rect_; // Parte del objeto para copiar en pantalla
|
||||
SDL_FRect dst_rect_; // Posición en pantalla donde se copia el objeto
|
||||
std::array<SDL_FRect, STAGES> gradient_rect_; // Fondos degradados
|
||||
std::array<SDL_FRect, 4> top_clouds_rect_; // Nubes superiores
|
||||
std::array<SDL_FRect, 4> bottom_clouds_rect_; // Nubes inferiores
|
||||
Color attenuate_color_; // Color de atenuación
|
||||
|
||||
std::vector<SDL_FPoint> sun_path_; // Recorrido del sol
|
||||
std::vector<SDL_FPoint> moon_path_; // Recorrido de la luna
|
||||
|
||||
float clouds_speed_ = 0; // Velocidad de las nubes
|
||||
float transition_ = 0; // Porcentaje de transición
|
||||
|
||||
size_t gradient_number_ = 0; // Índice de fondo degradado
|
||||
size_t counter_ = 0; // Contador interno
|
||||
size_t alpha_color_texture_ = 0; // Transparencia de atenuación
|
||||
size_t previous_alpha_color_texture_ = 0; // Transparencia anterior
|
||||
size_t sun_index_ = 0; // Índice del recorrido del sol
|
||||
size_t moon_index_ = 0; // Índice del recorrido de la luna
|
||||
int base_ = 0; // Posición base del fondo
|
||||
|
||||
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
|
||||
@@ -111,4 +150,4 @@ class Background {
|
||||
void updateClouds(); // Actualiza el movimiento de las nubes
|
||||
void createSunPath(); // Precalcula el recorrido del sol
|
||||
void createMoonPath(); // Precalcula el recorrido de la luna
|
||||
};
|
||||
};
|
||||
@@ -12,13 +12,14 @@
|
||||
#include "param.h" // Para Param, ParamGame, param
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "stage.h" // Para addPower
|
||||
#include "stage_interface.h" // Para IStageInfo
|
||||
#include "utils.h"
|
||||
|
||||
// Constructor
|
||||
BalloonManager::BalloonManager()
|
||||
BalloonManager::BalloonManager(IStageInfo *stage_info)
|
||||
: explosions_(std::make_unique<Explosions>()),
|
||||
balloon_formations_(std::make_unique<BalloonFormations>()) { init(); }
|
||||
balloon_formations_(std::make_unique<BalloonFormations>()),
|
||||
stage_info_(stage_info) { init(); }
|
||||
|
||||
// Inicializa
|
||||
void BalloonManager::init() {
|
||||
@@ -227,7 +228,7 @@ void BalloonManager::setBalloonSpeed(float speed) {
|
||||
|
||||
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
||||
auto BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon) -> int {
|
||||
Stage::addPower(1);
|
||||
stage_info_->addPower(1);
|
||||
int score = 0;
|
||||
|
||||
if (balloon->getType() == Balloon::Type::POWERBALL) {
|
||||
@@ -274,7 +275,7 @@ auto BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon) -> int {
|
||||
}
|
||||
|
||||
// Aumenta el poder de la fase
|
||||
Stage::addPower(balloon->getPower());
|
||||
stage_info_->addPower(balloon->getPower());
|
||||
|
||||
// Destruye el globo
|
||||
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "balloon_formations.h" // Para BalloonFormations
|
||||
#include "explosions.h" // Para Explosions
|
||||
#include "param.h" // Para Param, ParamGame, param
|
||||
#include "stage_interface.h" // Para IStageInfo
|
||||
#include "utils.h" // Para Zone
|
||||
|
||||
class Texture;
|
||||
@@ -22,7 +23,7 @@ using Balloons = std::vector<std::shared_ptr<Balloon>>;
|
||||
class BalloonManager {
|
||||
public:
|
||||
// Constructor y Destructor
|
||||
BalloonManager();
|
||||
BalloonManager(IStageInfo *stage_info);
|
||||
~BalloonManager() = default;
|
||||
|
||||
// Actualización y Renderizado
|
||||
@@ -103,6 +104,7 @@ class BalloonManager {
|
||||
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
||||
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
||||
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
||||
IStageInfo *stage_info_; // Informacion de la pantalla actual
|
||||
|
||||
// Metodos privados
|
||||
void init();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "param.h" // Para Param, ParamGame, param
|
||||
#include "scoreboard.h" // Para Scoreboard
|
||||
#include "stage.h" // Para power_can_be_added
|
||||
#include "stage_interface.h" // Para IStageInfo
|
||||
#include "texture.h" // Para Texture
|
||||
#ifdef _DEBUG
|
||||
#include <iostream>
|
||||
@@ -26,6 +27,7 @@ Player::Player(const Config &config)
|
||||
enter_name_(std::make_unique<EnterName>()),
|
||||
hi_score_table_(config.hi_score_table),
|
||||
glowing_entry_(config.glowing_entry),
|
||||
stage_info_(config.stage_info),
|
||||
play_area_(*config.play_area),
|
||||
id_(config.id),
|
||||
default_pos_x_(config.x),
|
||||
@@ -635,7 +637,7 @@ void Player::setPlayingState(State state) {
|
||||
init();
|
||||
setInvulnerable(true);
|
||||
setScoreboardMode(Scoreboard::Mode::SCORE);
|
||||
Stage::power_can_be_added = true;
|
||||
stage_info_->canCollectPower();
|
||||
break;
|
||||
}
|
||||
case State::CONTINUE: {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "input.h" // Para Input
|
||||
#include "manage_hiscore_table.h" // Para Table
|
||||
#include "scoreboard.h" // Para Scoreboard
|
||||
#include "stage_interface.h" // Para IStageInfo
|
||||
#include "utils.h" // Para Circle
|
||||
|
||||
class Texture;
|
||||
@@ -82,8 +83,9 @@ class Player {
|
||||
SDL_FRect *play_area; // Usamos puntero para mantener la referencia
|
||||
std::vector<std::shared_ptr<Texture>> texture;
|
||||
std::vector<std::vector<std::string>> animations;
|
||||
Table *hi_score_table; // También como puntero para referencia
|
||||
int *glowing_entry; // Puntero para mantener la referencia
|
||||
Table *hi_score_table; // También como puntero para referencia
|
||||
int *glowing_entry; // Puntero para mantener la referencia
|
||||
IStageInfo *stage_info; // Puntero para el gestor de pantallas
|
||||
};
|
||||
|
||||
// --- Constructor y destructor ---
|
||||
@@ -204,6 +206,7 @@ class Player {
|
||||
std::shared_ptr<Input::Gamepad> gamepad_ = nullptr; // Dispositivo asociado
|
||||
Table *hi_score_table_ = nullptr; // Tabla de máximas puntuaciones
|
||||
int *glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar
|
||||
IStageInfo *stage_info_; // Informacion de la pantalla actual
|
||||
std::string name_; // Nombre del jugador
|
||||
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner";
|
||||
|
||||
// Constructor
|
||||
Credits::Credits()
|
||||
: balloon_manager_(std::make_unique<BalloonManager>()),
|
||||
: balloon_manager_(std::make_unique<BalloonManager>(nullptr)),
|
||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)),
|
||||
fade_in_(std::make_unique<Fade>()),
|
||||
fade_out_(std::make_unique<Fade>()),
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "texture.h" // Para Texture
|
||||
#include "ui/service_menu.h" // Para ServiceMenu
|
||||
#ifdef _DEBUG
|
||||
#include <iostream> // Para Notifier
|
||||
#include <iostream> // Para std::cout
|
||||
|
||||
#include "ui/notifier.h" // Para Notifier
|
||||
#endif
|
||||
@@ -55,9 +55,10 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
||||
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>()),
|
||||
fade_in_(std::make_unique<Fade>()),
|
||||
fade_out_(std::make_unique<Fade>()),
|
||||
balloon_manager_(std::make_unique<BalloonManager>()),
|
||||
balloon_manager_(std::make_unique<BalloonManager>(stage_manager_.get())),
|
||||
tabe_(std::make_unique<Tabe>()),
|
||||
hit_(Hit(Resource::get()->getTexture("hit.png"))) {
|
||||
// Pasa variables
|
||||
@@ -66,8 +67,8 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
||||
// Otras variables
|
||||
Section::name = Section::Name::GAME;
|
||||
Section::options = Section::Options::NONE;
|
||||
Stage::init();
|
||||
Stage::number = current_stage;
|
||||
stage_manager_->initialize();
|
||||
stage_manager_->jumpToStage(current_stage);
|
||||
|
||||
// Asigna texturas y animaciones
|
||||
setResources();
|
||||
@@ -99,7 +100,6 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
||||
initDifficultyVars();
|
||||
initDemo(player_id);
|
||||
initPaths();
|
||||
setTotalPower();
|
||||
|
||||
// Registra callbacks
|
||||
ServiceMenu::get()->setStateChangeCallback([this](bool is_active) {
|
||||
@@ -109,14 +109,14 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
||||
}
|
||||
});
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Si se empieza en una fase que no es la primera
|
||||
if (!demo_.enabled) {
|
||||
for (int i = 0; i < Stage::number; ++i) {
|
||||
Stage::total_power += Stage::get(i).power_to_complete;
|
||||
/* #ifdef _DEBUG
|
||||
// Si se empieza en una fase que no es la primera
|
||||
if (!demo_.enabled) {
|
||||
for (int i = 0; i < Stage::number; ++i) {
|
||||
Stage::total_power += Stage::get(i).power_to_complete;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif */
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
@@ -260,7 +260,7 @@ void Game::renderPlayers() {
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si hay cambio de fase y actualiza las variables
|
||||
/* // Comprueba si hay cambio de fase y actualiza las variables
|
||||
void Game::updateStage() {
|
||||
if (Stage::power >= Stage::get(Stage::number).power_to_complete) {
|
||||
// Cambio de fase
|
||||
@@ -289,6 +289,64 @@ void Game::updateStage() {
|
||||
background_->setAlpha(96);
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
// Comprueba si hay cambio de fase y actualiza las variables
|
||||
void Game::updateStage() {
|
||||
if (!stage_manager_->isCurrentStageCompleted()) {
|
||||
return; // No hay cambio de fase
|
||||
}
|
||||
|
||||
// Calcular poder sobrante antes de avanzar
|
||||
int power_overflow = 0;
|
||||
auto current_stage = stage_manager_->getCurrentStage();
|
||||
if (current_stage.has_value()) {
|
||||
int current_power = stage_manager_->getCurrentPower();
|
||||
int power_needed = current_stage->getPowerToComplete();
|
||||
power_overflow = current_power - power_needed; // Poder que sobra
|
||||
}
|
||||
|
||||
// Intentar avanzar a la siguiente fase
|
||||
if (!stage_manager_->advanceToNextStage()) {
|
||||
// No se pudo avanzar (probablemente juego completado)
|
||||
return;
|
||||
}
|
||||
|
||||
// Aplicar el poder sobrante a la nueva fase
|
||||
if (power_overflow > 0) {
|
||||
stage_manager_->addPower(power_overflow);
|
||||
}
|
||||
|
||||
// Efectos de cambio de fase
|
||||
playSound("stage_change.wav");
|
||||
balloon_manager_->resetBalloonSpeed();
|
||||
screen_->flash(FLASH_COLOR, 3);
|
||||
screen_->shake();
|
||||
|
||||
// Obtener datos de la nueva fase
|
||||
size_t current_stage_index = stage_manager_->getCurrentStageIndex();
|
||||
size_t total_stages = stage_manager_->getTotalStages();
|
||||
|
||||
// Escribir texto por pantalla
|
||||
if (current_stage_index < total_stages - 1) { // No es la última fase
|
||||
std::vector<Path> paths = {paths_.at(2), paths_.at(3)};
|
||||
|
||||
if (current_stage_index == total_stages - 2) { // Penúltima fase (será la última)
|
||||
createMessage(paths, Resource::get()->getTexture("game_text_last_stage"));
|
||||
} else {
|
||||
auto text = Resource::get()->getText("04b_25_2x");
|
||||
const std::string CAPTION = Lang::getText("[GAME_TEXT] 2") +
|
||||
std::to_string(total_stages - current_stage_index) +
|
||||
Lang::getText("[GAME_TEXT] 2A");
|
||||
createMessage(paths, text->writeToTexture(CAPTION, 1, -4));
|
||||
}
|
||||
}
|
||||
|
||||
// Modificar color de fondo en la última fase
|
||||
if (current_stage_index == total_stages - 1) { // Última fase
|
||||
background_->setColor(Color(0xdd, 0x19, 0x1d).DARKEN());
|
||||
background_->setAlpha(96);
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza el estado de fin de la partida
|
||||
@@ -363,11 +421,11 @@ void Game::updateGameStateCompleted() {
|
||||
// Para la música y elimina todos los globos e items
|
||||
if (game_completed_counter_ == 0) {
|
||||
stopMusic();
|
||||
Stage::number = 9; // Deja el valor dentro de los limites
|
||||
// Stage::number = 9; // Deja el valor dentro de los limites
|
||||
balloon_manager_->destroyAllBalloons(); // Destruye a todos los globos
|
||||
playSound("power_ball_explosion.wav");
|
||||
destroyAllItems(); // Destruye todos los items
|
||||
Stage::power = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos los globos
|
||||
destroyAllItems(); // Destruye todos los items
|
||||
// Stage::power = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos los globos
|
||||
background_->setAlpha(0); // Elimina el tono rojo de las últimas pantallas
|
||||
}
|
||||
|
||||
@@ -409,8 +467,10 @@ void Game::updateGameStateCompleted() {
|
||||
|
||||
// Comprueba el estado del juego
|
||||
void Game::checkState() {
|
||||
if (state_ != State::COMPLETED && Stage::number == 10) {
|
||||
// if (state_ != State::COMPLETED && Stage::number == 10) {
|
||||
if (state_ != State::COMPLETED && stage_manager_->isGameCompleted()) {
|
||||
setState(State::COMPLETED);
|
||||
background_->setState(Background::State::COMPLETED);
|
||||
}
|
||||
|
||||
if (state_ != State::GAME_OVER && allPlayersAreGameOver()) {
|
||||
@@ -876,7 +936,8 @@ void Game::handlePlayerCollision(std::shared_ptr<Player> &player, std::shared_pt
|
||||
player->setPlayingState(Player::State::ROLLING);
|
||||
sendPlayerToTheBack(player);
|
||||
if (allPlayersAreNotPlaying()) {
|
||||
Stage::power_can_be_added = false; // No se puede subir poder de fase si no hay nadie jugando
|
||||
// Stage::power_can_be_added = false; // No se puede subir poder de fase si no hay nadie jugando
|
||||
stage_manager_->disablePowerCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -961,6 +1022,8 @@ void Game::updateGameStates() {
|
||||
|
||||
// Actualiza el fondo
|
||||
void Game::updateBackground() {
|
||||
/* static const auto total_power_to_complete_game = stage_manager_->getTotalPowerNeededToCompleteGame();
|
||||
|
||||
// Si el juego está completado, se reduce la velocidad de las nubes
|
||||
if (state_ == State::COMPLETED) {
|
||||
Stage::total_power = (Stage::total_power > 200) ? (Stage::total_power - 25) : 200;
|
||||
@@ -969,7 +1032,7 @@ void Game::updateBackground() {
|
||||
// Calcula la velocidad en función de los globos explotados y el total de globos a explotar para acabar el juego
|
||||
constexpr float CLOUDS_INITIAL_SPEED = 0.05F;
|
||||
constexpr float CLOUDS_FINAL_SPEED = 2.00F - CLOUDS_INITIAL_SPEED;
|
||||
const float CLOUDS_SPEED = (-CLOUDS_INITIAL_SPEED) + (-CLOUDS_FINAL_SPEED * (static_cast<float>(Stage::total_power) / total_power_to_complete_game_));
|
||||
const float CLOUDS_SPEED = (-CLOUDS_INITIAL_SPEED) + (-CLOUDS_FINAL_SPEED * (static_cast<float>(Stage::total_power) / total_power_to_complete_game));
|
||||
background_->setCloudsSpeed(CLOUDS_SPEED);
|
||||
|
||||
// Calcula la transición de los diferentes fondos
|
||||
@@ -982,7 +1045,7 @@ void Game::updateBackground() {
|
||||
// Calcula la posición del sol
|
||||
constexpr float SUN_FINAL_POWER = NUM * 2;
|
||||
background_->setSunProgression(Stage::total_power / SUN_FINAL_POWER);
|
||||
background_->setMoonProgression(Stage::total_power / static_cast<float>(total_power_to_complete_game_));
|
||||
background_->setMoonProgression(Stage::total_power / static_cast<float>(total_power_to_complete_game)); */
|
||||
|
||||
// Actualiza el objeto
|
||||
background_->update();
|
||||
@@ -1166,12 +1229,11 @@ void Game::updateScoreboard() {
|
||||
}
|
||||
|
||||
// Resto de marcador
|
||||
scoreboard_->setStage(Stage::number + 1);
|
||||
scoreboard_->setPower((float)Stage::power / (float)Stage::get(Stage::number).power_to_complete);
|
||||
scoreboard_->setStage(stage_manager_->getCurrentStageIndex() + 1);
|
||||
scoreboard_->setPower(stage_manager_->getCurrentStageProgressFraction());
|
||||
scoreboard_->setHiScore(hi_score_.score);
|
||||
scoreboard_->setHiScoreName(hi_score_.name);
|
||||
|
||||
// Lógica del marcador
|
||||
scoreboard_->update();
|
||||
}
|
||||
|
||||
@@ -1488,13 +1550,14 @@ void Game::initDemo(Player::Id player_id) {
|
||||
constexpr auto NUM_DEMOS = 3;
|
||||
const auto DEMO = rand() % NUM_DEMOS;
|
||||
constexpr std::array<int, NUM_DEMOS> STAGES = {0, 3, 5};
|
||||
Stage::number = STAGES[DEMO];
|
||||
// Stage::number = STAGES[DEMO];
|
||||
stage_manager_->jumpToStage(STAGES.at(DEMO));
|
||||
}
|
||||
|
||||
// Actualiza el numero de globos explotados según la fase del modo demostración
|
||||
for (int i = 0; i < Stage::number; ++i) {
|
||||
/* for (int i = 0; i < Stage::number; ++i) {
|
||||
Stage::total_power += Stage::get(i).power_to_complete;
|
||||
}
|
||||
} */
|
||||
|
||||
// Activa o no al otro jugador
|
||||
if (rand() % 3 != 0) {
|
||||
@@ -1529,14 +1592,6 @@ void Game::initDemo(Player::Id player_id) {
|
||||
demo_.counter = 0;
|
||||
}
|
||||
|
||||
// Calcula el poder total necesario para completar el juego
|
||||
void Game::setTotalPower() {
|
||||
total_power_to_complete_game_ = 0;
|
||||
for (const auto &stage : Stage::stages) {
|
||||
total_power_to_complete_game_ += stage.power_to_complete;
|
||||
}
|
||||
}
|
||||
|
||||
// Inicializa el marcador
|
||||
void Game::initScoreboard() {
|
||||
scoreboard_->setPos(param.scoreboard.rect);
|
||||
@@ -1596,6 +1651,7 @@ void Game::initPlayers(Player::Id player_id) {
|
||||
config_player1.animations = player_animations_;
|
||||
config_player1.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player1.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER1) - 1);
|
||||
config_player1.stage_info = stage_manager_.get();
|
||||
|
||||
auto player1 = std::make_unique<Player>(config_player1);
|
||||
player1->setScoreBoardPanel(Scoreboard::Id::LEFT);
|
||||
@@ -1616,6 +1672,7 @@ void Game::initPlayers(Player::Id player_id) {
|
||||
config_player2.animations = player_animations_;
|
||||
config_player2.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player2.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER2) - 1);
|
||||
config_player2.stage_info = stage_manager_.get();
|
||||
|
||||
auto player2 = std::make_unique<Player>(config_player2);
|
||||
player2->setScoreBoardPanel(Scoreboard::Id::RIGHT);
|
||||
@@ -1755,7 +1812,8 @@ void Game::updateGameStateShowingGetReadyMessage() {
|
||||
void Game::updateGameStatePlaying() {
|
||||
#ifdef _DEBUG
|
||||
if (auto_pop_balloons_) {
|
||||
Stage::addPower(5);
|
||||
// Stage::addPower(5);
|
||||
stage_manager_->addPower(5);
|
||||
}
|
||||
#endif
|
||||
updatePlayers();
|
||||
@@ -1787,7 +1845,7 @@ void Game::cleanVectors() {
|
||||
freePathSprites();
|
||||
}
|
||||
|
||||
// Gestiona el nivel de amenaza
|
||||
/* // Gestiona el nivel de amenaza
|
||||
void Game::updateMenace() {
|
||||
if (state_ == State::PLAYING) {
|
||||
const auto STAGE = Stage::get(Stage::number);
|
||||
@@ -1803,6 +1861,30 @@ void Game::updateMenace() {
|
||||
evaluateAndSetMenace(); // Recalcula el nivel de amenaza con el nuevo globo
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
// Gestiona el nivel de amenaza
|
||||
void Game::updateMenace() {
|
||||
if (state_ != State::PLAYING) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_stage = stage_manager_->getCurrentStage();
|
||||
if (!current_stage.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &stage = current_stage.value();
|
||||
const double fraction = stage_manager_->getCurrentStageProgressFraction();
|
||||
const int difference = stage.getMaxMenace() - stage.getMinMenace();
|
||||
|
||||
// Aumenta el nivel de amenaza en función del progreso de la fase
|
||||
menace_threshold_ = stage.getMinMenace() + (difference * fraction);
|
||||
|
||||
if (menace_current_ < menace_threshold_) {
|
||||
balloon_manager_->deployRandomFormation(stage_manager_->getCurrentStageIndex());
|
||||
evaluateAndSetMenace();
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula y establece el valor de amenaza en funcion de los globos activos
|
||||
@@ -1816,7 +1898,8 @@ void Game::checkAndUpdateBalloonSpeed() {
|
||||
return;
|
||||
}
|
||||
|
||||
const float PERCENT = static_cast<float>(Stage::power) / Stage::get(Stage::number).power_to_complete;
|
||||
// const float PERCENT = static_cast<float>(Stage::power) / Stage::get(Stage::number).power_to_complete;
|
||||
const float PERCENT = stage_manager_->getCurrentStageProgressPercentage();
|
||||
constexpr std::array<float, 4> THRESHOLDS = {0.2F, 0.4F, 0.6F, 0.8F};
|
||||
|
||||
for (size_t i = 0; i < std::size(THRESHOLDS); ++i) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "player.h" // Para Player
|
||||
#include "smart_sprite.h" // Para SmartSprite
|
||||
#include "utils.h" // Para Demo
|
||||
#include "stage.h" // Para StageManager
|
||||
|
||||
class Background;
|
||||
class Balloon;
|
||||
@@ -119,6 +120,7 @@ class Game {
|
||||
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<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
|
||||
@@ -141,7 +143,6 @@ class Game {
|
||||
int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más globos
|
||||
int game_over_counter_ = GAME_OVER_COUNTER; // Contador para el estado de fin de partida
|
||||
int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
|
||||
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
|
||||
int menace_current_ = 0; // Nivel de amenaza actual
|
||||
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
||||
State state_ = State::FADE_IN; // Estado
|
||||
|
||||
237
source/stage.cpp
237
source/stage.cpp
@@ -1,43 +1,210 @@
|
||||
#include "stage.h"
|
||||
|
||||
#include <algorithm> // Para min
|
||||
#include <vector> // Para vector
|
||||
#include <algorithm>
|
||||
|
||||
namespace Stage {
|
||||
// ===== 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) {}
|
||||
|
||||
std::vector<Stage> stages; // Variable con los datos de cada pantalla
|
||||
int power = 0; // Poder acumulado en la fase
|
||||
int total_power = 0; // Poder total necesario para completar el juego
|
||||
int number = 0; // Fase actual
|
||||
bool power_can_be_added = true; // Habilita la recolecta de poder
|
||||
|
||||
// Devuelve una fase
|
||||
auto get(int index) -> Stage { return stages.at(std::min(9, index)); }
|
||||
|
||||
// Inicializa las variables del namespace Stage
|
||||
void init() {
|
||||
stages.clear();
|
||||
stages.emplace_back(200, 7 + (4 * 1), 7 + (4 * 3));
|
||||
stages.emplace_back(300, 7 + (4 * 2), 7 + (4 * 4));
|
||||
stages.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5));
|
||||
stages.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5));
|
||||
stages.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6));
|
||||
stages.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6));
|
||||
stages.emplace_back(650, 7 + (4 * 5), 7 + (4 * 7));
|
||||
stages.emplace_back(750, 7 + (4 * 5), 7 + (4 * 7));
|
||||
stages.emplace_back(850, 7 + (4 * 6), 7 + (4 * 8));
|
||||
stages.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10));
|
||||
|
||||
power = 0;
|
||||
total_power = 0;
|
||||
number = 0;
|
||||
// ===== IMPLEMENTACIÓN DE StageManager =====
|
||||
StageManager::StageManager()
|
||||
: current_power_(0), total_power_(0), current_stage_index_(0), power_collection_state_(PowerCollectionState::ENABLED) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
// Añade poder
|
||||
void addPower(int amount) {
|
||||
if (power_can_be_added) {
|
||||
power += amount;
|
||||
total_power += amount;
|
||||
void StageManager::initialize() {
|
||||
stages_.clear();
|
||||
createDefaultStages();
|
||||
reset();
|
||||
}
|
||||
|
||||
void StageManager::reset() {
|
||||
current_power_ = 0;
|
||||
total_power_ = 0;
|
||||
current_stage_index_ = 0;
|
||||
power_collection_state_ = PowerCollectionState::ENABLED;
|
||||
updateStageStatuses();
|
||||
}
|
||||
|
||||
void StageManager::createDefaultStages() {
|
||||
// Crear las 10 fases como en tu código original
|
||||
stages_.emplace_back(200, 7 + (4 * 1), 7 + (4 * 3), "Tutorial");
|
||||
stages_.emplace_back(300, 7 + (4 * 2), 7 + (4 * 4), "Primeros pasos");
|
||||
stages_.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5), "Intensificación");
|
||||
stages_.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5), "Persistencia");
|
||||
stages_.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6), "Desafío medio");
|
||||
stages_.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6), "Resistencia");
|
||||
stages_.emplace_back(650, 7 + (4 * 5), 7 + (4 * 7), "Aproximación final");
|
||||
stages_.emplace_back(750, 7 + (4 * 5), 7 + (4 * 7), "Penúltimo obstáculo");
|
||||
stages_.emplace_back(850, 7 + (4 * 6), 7 + (4 * 8), "Clímax");
|
||||
stages_.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10), "Maestría");
|
||||
}
|
||||
|
||||
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
|
||||
updateStageStatuses();
|
||||
return true;
|
||||
}
|
||||
} // namespace Stage
|
||||
|
||||
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
|
||||
total_power_ = accumulated_power; // Poder total como si hubiéramos completado las anteriores
|
||||
|
||||
updateStageStatuses();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StageManager::subtractPower(int amount) {
|
||||
if (amount <= 0 || current_power_ < amount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current_power_ -= amount;
|
||||
updateStageStatuses();
|
||||
return true;
|
||||
}
|
||||
|
||||
void StageManager::enablePowerCollection() {
|
||||
power_collection_state_ = PowerCollectionState::ENABLED;
|
||||
}
|
||||
|
||||
void StageManager::disablePowerCollection() {
|
||||
power_collection_state_ = PowerCollectionState::DISABLED;
|
||||
}
|
||||
|
||||
std::optional<StageData> StageManager::getCurrentStage() const {
|
||||
return getStage(current_stage_index_);
|
||||
}
|
||||
|
||||
std::optional<StageData> StageManager::getStage(size_t index) const {
|
||||
if (!validateStageIndex(index)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return stages_[index];
|
||||
}
|
||||
|
||||
bool StageManager::isCurrentStageCompleted() const {
|
||||
auto current_stage = getCurrentStage();
|
||||
if (!current_stage.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return current_power_ >= current_stage->getPowerToComplete();
|
||||
}
|
||||
|
||||
bool StageManager::isGameCompleted() const {
|
||||
return current_stage_index_ >= stages_.size() - 1 && isCurrentStageCompleted();
|
||||
}
|
||||
|
||||
double StageManager::getProgressPercentage() const {
|
||||
if (stages_.empty()) return 0.0;
|
||||
|
||||
int total_power_needed = getTotalPowerNeededToCompleteGame();
|
||||
if (total_power_needed == 0) return 100.0;
|
||||
|
||||
return (static_cast<double>(total_power_) / total_power_needed) * 100.0;
|
||||
}
|
||||
|
||||
double StageManager::getCurrentStageProgressPercentage() const {
|
||||
return getCurrentStageProgressFraction() * 100.0;
|
||||
}
|
||||
|
||||
double StageManager::getCurrentStageProgressFraction() const {
|
||||
auto current_stage = getCurrentStage();
|
||||
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);
|
||||
}
|
||||
|
||||
int StageManager::getPowerNeededForCurrentStage() const {
|
||||
auto current_stage = getCurrentStage();
|
||||
if (!current_stage.has_value()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::max(0, current_stage->getPowerToComplete() - current_power_);
|
||||
}
|
||||
|
||||
int StageManager::getTotalPowerNeededToCompleteGame() const {
|
||||
int total_power_needed = 0;
|
||||
for (const auto& stage : stages_) {
|
||||
total_power_needed += stage.getPowerToComplete();
|
||||
}
|
||||
return total_power_needed;
|
||||
}
|
||||
|
||||
// ===== IMPLEMENTACIÓN DE IStageInfo (lo que ven Player y Balloon) =====
|
||||
bool StageManager::canCollectPower() const {
|
||||
return power_collection_state_ == PowerCollectionState::ENABLED;
|
||||
}
|
||||
|
||||
void StageManager::addPower(int amount) {
|
||||
if (amount <= 0 || !canCollectPower()) {
|
||||
return;
|
||||
}
|
||||
|
||||
current_power_ += amount;
|
||||
total_power_ += amount;
|
||||
|
||||
// Verificar si se completó la fase actual
|
||||
if (isCurrentStageCompleted()) {
|
||||
auto current_stage = getCurrentStage();
|
||||
if (current_stage.has_value()) {
|
||||
stages_[current_stage_index_].setStatus(StageStatus::COMPLETED);
|
||||
}
|
||||
}
|
||||
|
||||
updateStageStatuses();
|
||||
}
|
||||
|
||||
int StageManager::getCurrentMenaceLevel() const {
|
||||
auto current_stage = getCurrentStage();
|
||||
if (!current_stage.has_value()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return current_stage->getMinMenace();
|
||||
}
|
||||
|
||||
// ===== MÉTODOS PRIVADOS =====
|
||||
bool StageManager::validateStageIndex(size_t index) const {
|
||||
return index < stages_.size();
|
||||
}
|
||||
|
||||
void StageManager::updateStageStatuses() {
|
||||
for (size_t i = 0; i < stages_.size(); ++i) {
|
||||
if (i < current_stage_index_) {
|
||||
stages_[i].setStatus(StageStatus::COMPLETED);
|
||||
} else if (i == current_stage_index_) {
|
||||
stages_[i].setStatus(StageStatus::IN_PROGRESS);
|
||||
} else {
|
||||
stages_[i].setStatus(StageStatus::LOCKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
source/stage.h
115
source/stage.h
@@ -1,33 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector> // Para vector
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
Namespace Stage: gestiona los datos y operaciones de las fases del juego.
|
||||
Permite consultar y modificar el poder necesario, la amenaza y el estado de cada fase.
|
||||
*/
|
||||
#include "stage_interface.h"
|
||||
|
||||
namespace Stage {
|
||||
// --- Estructura con los datos de una fase ---
|
||||
struct Stage {
|
||||
int power_to_complete; // Cantidad de poder que se necesita para completar la fase
|
||||
int min_menace; // Umbral mínimo de amenaza de la fase
|
||||
int max_menace; // Umbral máximo de amenaza de la fase
|
||||
|
||||
// Constructor
|
||||
Stage(int power_to_complete, int min_menace, int max_menace)
|
||||
: power_to_complete(power_to_complete), min_menace(min_menace), max_menace(max_menace) {}
|
||||
enum class PowerCollectionState {
|
||||
ENABLED,
|
||||
DISABLED
|
||||
};
|
||||
|
||||
// --- Variables globales del estado de las fases ---
|
||||
extern std::vector<Stage> stages; // Vector con los datos de cada pantalla
|
||||
extern int power; // Poder acumulado en la fase actual
|
||||
extern int total_power; // Poder total necesario para completar el juego
|
||||
extern int number; // Índice de la fase actual
|
||||
extern bool power_can_be_added; // Indica si se puede añadir poder a la fase
|
||||
enum class StageStatus {
|
||||
LOCKED,
|
||||
IN_PROGRESS,
|
||||
COMPLETED
|
||||
};
|
||||
|
||||
// --- Funciones principales ---
|
||||
auto get(int index) -> Stage; // Devuelve una fase por índice
|
||||
void init(); // Inicializa las variables del namespace Stage
|
||||
void addPower(int amount); // Añade poder a la fase actual
|
||||
} // namespace Stage
|
||||
class StageData {
|
||||
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 = "");
|
||||
|
||||
// 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; }
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
// 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;
|
||||
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();
|
||||
};
|
||||
14
source/stage_interface.h
Normal file
14
source/stage_interface.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
// Interfaz simple para lo que necesitan Player y Balloon
|
||||
class IStageInfo {
|
||||
public:
|
||||
virtual ~IStageInfo() = default;
|
||||
|
||||
// Lo que necesita Player para recolectar poder
|
||||
virtual bool canCollectPower() const = 0;
|
||||
virtual void addPower(int amount) = 0;
|
||||
|
||||
// Lo que necesitan Player y Balloon para ajustar comportamiento
|
||||
virtual int getCurrentMenaceLevel() const = 0;
|
||||
};
|
||||
Reference in New Issue
Block a user