Stage ja carrega desde fitxer la informació de les fases

This commit is contained in:
2025-08-14 11:14:54 +02:00
parent b2139d8e06
commit 4cc5102d70
8 changed files with 188 additions and 91 deletions

View File

@@ -16,6 +16,7 @@ DEMODATA|${PREFIX}/data/config/demo2.bin
DATA|${PREFIX}/data/config/gamecontrollerdb.txt DATA|${PREFIX}/data/config/gamecontrollerdb.txt
DATA|${PREFIX}/data/config/formations.txt DATA|${PREFIX}/data/config/formations.txt
DATA|${PREFIX}/data/config/pools.txt DATA|${PREFIX}/data/config/pools.txt
DATA|${PREFIX}/data/config/stages.txt
# Música # Música
MUSIC|${PREFIX}/data/music/intro.ogg MUSIC|${PREFIX}/data/music/intro.ogg

19
data/config/stages.txt Normal file
View File

@@ -0,0 +1,19 @@
# Archivo de configuración de fases
# Formato: power_to_complete,min_menace,max_menace,name
# Líneas que empiezan con # son comentarios y se ignoran
# Fases iniciales - Tutorial y aprendizaje
200, 11, 19, Tutorial
300, 15, 23, Primeros pasos
# Fases intermedias - Incremento de dificultad
600, 19, 27, Intensificación
600, 19, 27, Persistencia
600, 23, 31, Desafío medio
600, 23, 31, Resistencia
# Fases avanzadas - Desafío final
650, 27, 35, Aproximación final
750, 27, 35, Penúltimo obstáculo
850, 31, 39, Clímax
950, 35, 47, Maestría

View File

@@ -111,7 +111,7 @@ void BalloonManager::deployRandomFormation(int stage) {
} }
// Reinicia el contador para el próximo despliegue // Reinicia el contador para el próximo despliegue
balloon_deploy_counter_ = 300; balloon_deploy_counter_ = DEFAULT_BALLOON_DEPLOY_COUNTER;
} }
} }
} }

View File

@@ -81,6 +81,8 @@ class BalloonManager {
[[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); } [[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); }
private: private:
static const int DEFAULT_BALLOON_DEPLOY_COUNTER = 300;
Balloons balloons_; // Vector con los globos activos Balloons balloons_; // Vector con los globos activos
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas

View File

@@ -67,7 +67,7 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
// Otras variables // Otras variables
Section::name = Section::Name::GAME; Section::name = Section::Name::GAME;
Section::options = Section::Options::NONE; Section::options = Section::Options::NONE;
stage_manager_->initialize(); stage_manager_->initialize(Asset::get()->get("stages.txt"));
stage_manager_->setPowerChangeCallback([this](int amount) { background_->incrementProgress(amount); }); stage_manager_->setPowerChangeCallback([this](int amount) { background_->incrementProgress(amount); });
stage_manager_->jumpToStage(current_stage); stage_manager_->jumpToStage(current_stage);
@@ -1846,24 +1846,6 @@ void Game::cleanVectors() {
freePathSprites(); freePathSprites();
} }
/* // Gestiona el nivel de amenaza
void Game::updateMenace() {
if (state_ == State::PLAYING) {
const auto STAGE = Stage::get(Stage::number);
const float PERCENT = Stage::power / STAGE.power_to_complete;
const int DIFFERENCE = STAGE.max_menace - STAGE.min_menace;
// Aumenta el nivel de amenaza en función de la puntuación
menace_threshold_ = STAGE.min_menace + (DIFFERENCE * PERCENT);
// Si el nivel de amenza es inferior al umbral
if (menace_current_ < menace_threshold_) {
balloon_manager_->deployRandomFormation(Stage::number); // Crea una formación aleatoria de globos
evaluateAndSetMenace(); // Recalcula el nivel de amenaza con el nuevo globo
}
}
} */
// Gestiona el nivel de amenaza // Gestiona el nivel de amenaza
void Game::updateMenace() { void Game::updateMenace() {
if (state_ != State::PLAYING) { if (state_ != State::PLAYING) {

View File

@@ -1,12 +1,14 @@
#include "stage.h" #include "stage.h"
#include <algorithm> #include <algorithm>
#include <fstream>
#include <sstream>
// ===== IMPLEMENTACIÓN DE StageData ===== // Implementación de StageData
StageData::StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name) 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), : power_to_complete_(power_to_complete), min_menace_(min_menace),
max_menace_(max_menace), name_(name), status_(StageStatus::LOCKED) {} max_menace_(max_menace), name_(name), status_(StageStatus::LOCKED) {}
// ===== IMPLEMENTACIÓN DE StageManager ===== // Implementación de StageManager
StageManager::StageManager() StageManager::StageManager()
: current_power_(0), total_power_(0), current_stage_index_(0), : current_power_(0), total_power_(0), current_stage_index_(0),
power_collection_state_(PowerCollectionState::ENABLED), power_collection_state_(PowerCollectionState::ENABLED),
@@ -20,6 +22,17 @@ void StageManager::initialize() {
reset(); reset();
} }
void StageManager::initialize(const std::string& stages_file) {
stages_.clear();
// Intentar cargar desde archivo, si falla usar valores predeterminados
if (!loadStagesFromFile(stages_file)) {
createDefaultStages();
}
reset();
}
void StageManager::reset() { void StageManager::reset() {
current_power_ = 0; current_power_ = 0;
total_power_ = 0; total_power_ = 0;
@@ -29,7 +42,7 @@ void StageManager::reset() {
} }
void StageManager::createDefaultStages() { void StageManager::createDefaultStages() {
// Crear las 10 fases como en tu código original // Crear las 10 fases predeterminadas con dificultad progresiva
stages_.emplace_back(200, 7 + (4 * 1), 7 + (4 * 3), "Tutorial"); 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(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), "Intensificación");
@@ -42,6 +55,69 @@ void StageManager::createDefaultStages() {
stages_.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10), "Maestría"); stages_.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10), "Maestría");
} }
bool StageManager::loadStagesFromFile(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
return false; // No se pudo abrir el archivo
}
std::string line;
int line_number = 0;
while (std::getline(file, line)) {
line_number++;
// Ignorar líneas vacías y comentarios (líneas que empiezan con #)
if (line.empty() || line[0] == '#') {
continue;
}
// Parsear línea: power_to_complete,min_menace,max_menace,name
std::stringstream ss(line);
std::string token;
std::vector<std::string> tokens;
// Dividir por comas
while (std::getline(ss, token, ',')) {
// Eliminar espacios en blanco al inicio y final
token.erase(0, token.find_first_not_of(" \t"));
token.erase(token.find_last_not_of(" \t") + 1);
tokens.push_back(token);
}
// Verificar que tenemos exactamente 4 campos
if (tokens.size() != 4) {
// Error de formato, continuar con la siguiente línea
continue;
}
try {
// Convertir a enteros los primeros tres campos
int power_to_complete = std::stoi(tokens[0]);
int min_menace = std::stoi(tokens[1]);
int max_menace = std::stoi(tokens[2]);
std::string name = tokens[3];
// Validar valores
if (power_to_complete <= 0 || min_menace < 0 || max_menace < min_menace) {
continue; // Valores inválidos, saltar línea
}
// Crear y añadir la fase
stages_.emplace_back(power_to_complete, min_menace, max_menace, name);
} catch (const std::exception&) {
// Error de conversión, continuar con la siguiente línea
continue;
}
}
file.close();
// Verificar que se cargó al menos una fase
return !stages_.empty();
}
bool StageManager::advanceToNextStage() { bool StageManager::advanceToNextStage() {
if (!isCurrentStageCompleted() || current_stage_index_ >= stages_.size() - 1) { if (!isCurrentStageCompleted() || current_stage_index_ >= stages_.size() - 1) {
return false; return false;
@@ -58,7 +134,7 @@ bool StageManager::jumpToStage(size_t target_stage_index) {
return false; return false;
} }
// Calcular el poder total acumulado hasta la fase objetivo // Calcular el poder acumulado hasta la fase objetivo
int accumulated_power = 0; int accumulated_power = 0;
for (size_t i = 0; i < target_stage_index; ++i) { for (size_t i = 0; i < target_stage_index; ++i) {
accumulated_power += stages_[i].getPowerToComplete(); accumulated_power += stages_[i].getPowerToComplete();
@@ -66,8 +142,8 @@ bool StageManager::jumpToStage(size_t target_stage_index) {
// Actualizar estado // Actualizar estado
current_stage_index_ = target_stage_index; current_stage_index_ = target_stage_index;
current_power_ = 0; // Empezar la fase objetivo sin poder current_power_ = 0; // Comenzar la fase objetivo sin poder
total_power_ = accumulated_power; // Poder total como si hubiéramos completado las anteriores total_power_ = accumulated_power; // Poder total como si se hubieran completado las anteriores
updateStageStatuses(); updateStageStatuses();
return true; return true;
@@ -118,7 +194,7 @@ bool StageManager::isGameCompleted() const {
double StageManager::getProgressPercentage() const { double StageManager::getProgressPercentage() const {
if (stages_.empty()) return 0.0; if (stages_.empty()) return 0.0;
int total_power_needed = getTotalPowerNeededToCompleteGame(); // ⬅️ Usar el nuevo método int total_power_needed = getTotalPowerNeededToCompleteGame();
if (total_power_needed == 0) return 100.0; if (total_power_needed == 0) return 100.0;
return (static_cast<double>(total_power_) / total_power_needed) * 100.0; return (static_cast<double>(total_power_) / total_power_needed) * 100.0;
@@ -139,7 +215,7 @@ double StageManager::getCurrentStageProgressFraction() const {
return 1.0; return 1.0;
} }
// Retorna fracción entre 0.0 y 1.0 // Devuelve una fracción entre 0.0 y 1.0
double fraction = static_cast<double>(current_power_) / power_needed; double fraction = static_cast<double>(current_power_) / power_needed;
return std::min(fraction, 1.0); return std::min(fraction, 1.0);
} }
@@ -161,7 +237,7 @@ int StageManager::getTotalPowerNeededToCompleteGame() const {
return total_power_needed; return total_power_needed;
} }
// ===== IMPLEMENTACIÓN DE IStageInfo (lo que ven Player y Balloon) ===== // Implementación de la interfaz IStageInfo
bool StageManager::canCollectPower() const { bool StageManager::canCollectPower() const {
return power_collection_state_ == PowerCollectionState::ENABLED; return power_collection_state_ == PowerCollectionState::ENABLED;
} }
@@ -174,9 +250,10 @@ void StageManager::addPower(int amount) {
current_power_ += amount; current_power_ += amount;
total_power_ += amount; total_power_ += amount;
// Ejecutar callback si está registrado
if (power_change_callback_) { if (power_change_callback_) {
power_change_callback_(amount); power_change_callback_(amount);
} }
// Verificar si se completó la fase actual // Verificar si se completó la fase actual
if (isCurrentStageCompleted()) { if (isCurrentStageCompleted()) {
@@ -198,12 +275,22 @@ int StageManager::getCurrentMenaceLevel() const {
return current_stage->getMinMenace(); return current_stage->getMinMenace();
} }
// ===== MÉTODOS PRIVADOS ===== // Gestión de callbacks
void StageManager::setPowerChangeCallback(PowerChangeCallback callback) {
power_change_callback_ = callback;
}
void StageManager::removePowerChangeCallback() {
power_change_callback_ = nullptr;
}
// Métodos privados
bool StageManager::validateStageIndex(size_t index) const { bool StageManager::validateStageIndex(size_t index) const {
return index < stages_.size(); return index < stages_.size();
} }
void StageManager::updateStageStatuses() { void StageManager::updateStageStatuses() {
// Actualizar el estado de cada fase según su posición relativa a la actual
for (size_t i = 0; i < stages_.size(); ++i) { for (size_t i = 0; i < stages_.size(); ++i) {
if (i < current_stage_index_) { if (i < current_stage_index_) {
stages_[i].setStatus(StageStatus::COMPLETED); stages_[i].setStatus(StageStatus::COMPLETED);
@@ -214,11 +301,3 @@ void StageManager::updateStageStatuses() {
} }
} }
} }
void StageManager::setPowerChangeCallback(PowerChangeCallback callback) {
power_change_callback_ = callback;
}
void StageManager::removePowerChangeCallback() {
power_change_callback_ = nullptr;
}

View File

@@ -4,98 +4,108 @@
#include <vector> #include <vector>
#include <optional> #include <optional>
#include <string> #include <string>
#include <functional> // ⬅️ Para std::function #include <functional>
// --- Estados posibles para la recolección de poder ---
enum class PowerCollectionState { enum class PowerCollectionState {
ENABLED, ENABLED, // Recolección habilitada
DISABLED DISABLED // Recolección deshabilitada
}; };
// --- Estados posibles para una fase del juego ---
enum class StageStatus { enum class StageStatus {
LOCKED, LOCKED, // Fase bloqueada
IN_PROGRESS, IN_PROGRESS, // Fase en progreso
COMPLETED COMPLETED // Fase completada
}; };
// --- Representa los datos de una fase del juego ---
class StageData { class StageData {
private: private:
int power_to_complete_; int power_to_complete_; // Poder necesario para completar la fase
int min_menace_; int min_menace_; // Nivel mínimo de amenaza
int max_menace_; int max_menace_; // Nivel máximo de amenaza
std::string name_; std::string name_; // Nombre de la fase
StageStatus status_; StageStatus status_; // Estado actual de la fase
public: public:
// Constructor de una fase
StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name = ""); StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name = "");
// Getters // --- Getters ---
int getPowerToComplete() const { return power_to_complete_; } int getPowerToComplete() const { return power_to_complete_; }
int getMinMenace() const { return min_menace_; } int getMinMenace() const { return min_menace_; }
int getMaxMenace() const { return max_menace_; } int getMaxMenace() const { return max_menace_; }
const std::string& getName() const { return name_; } const std::string& getName() const { return name_; }
StageStatus getStatus() const { return status_; } StageStatus getStatus() const { return status_; }
// Setters // --- Setters ---
void setStatus(StageStatus status) { status_ = status; } void setStatus(StageStatus status) { status_ = status; }
// Utilidades // --- Utilidades ---
bool isCompleted() const { return status_ == StageStatus::COMPLETED; } bool isCompleted() const { return status_ == StageStatus::COMPLETED; }
}; };
class StageManager : public IStageInfo { // ⬅️ Hereda de la interfaz // --- Gestor principal del sistema de fases del juego ---
class StageManager : public IStageInfo {
private: private:
std::vector<StageData> stages_; std::vector<StageData> stages_; // Lista de todas las fases
int current_power_; int current_power_; // Poder actual en la fase activa
int total_power_; int total_power_; // Poder total acumulado en todo el juego
size_t current_stage_index_; size_t current_stage_index_; // Índice de la fase actual
PowerCollectionState power_collection_state_; PowerCollectionState power_collection_state_; // Estado de recolección de poder
public: public:
using PowerChangeCallback = std::function<void(int)>;
StageManager(); StageManager();
// Métodos principales para Game // --- Métodos principales del juego ---
void initialize(); void initialize(); // Inicializa el gestor de fases
void reset(); void initialize(const std::string& stages_file); // Inicializa con archivo personalizado
bool advanceToNextStage(); void reset(); // Reinicia el progreso del juego
bool advanceToNextStage(); // Avanza a la siguiente fase
// Gestión de poder // --- Gestión de poder ---
bool subtractPower(int amount); bool subtractPower(int amount); // Resta poder de la fase actual
void enablePowerCollection(); void enablePowerCollection(); // Habilita la recolección de poder
void disablePowerCollection(); void disablePowerCollection(); // Deshabilita la recolección de poder
// Navegación avanzada // --- Navegación ---
bool jumpToStage(size_t target_stage_index); bool jumpToStage(size_t target_stage_index); // Salta a una fase específica
// Consultas de estado // --- Consultas de estado ---
std::optional<StageData> getCurrentStage() const; std::optional<StageData> getCurrentStage() const; // Obtiene la fase actual
std::optional<StageData> getStage(size_t index) const; std::optional<StageData> getStage(size_t index) const; // Obtiene una fase específica
size_t getCurrentStageIndex() const { return current_stage_index_; } size_t getCurrentStageIndex() const { return current_stage_index_; }
int getCurrentPower() const { return current_power_; } int getCurrentPower() const { return current_power_; }
int getTotalPower() const { return total_power_; } int getTotalPower() const { return total_power_; }
int getTotalPowerNeededToCompleteGame() const; // ⬅️ Nuevo método int getTotalPowerNeededToCompleteGame() const; // Poder total necesario para completar el juego
size_t getTotalStages() const { return stages_.size(); } size_t getTotalStages() const { return stages_.size(); }
// Progreso // --- Seguimiento de progreso ---
bool isCurrentStageCompleted() const; bool isCurrentStageCompleted() const; // Verifica si la fase actual está completada
bool isGameCompleted() const; bool isGameCompleted() const; // Verifica si el juego está completado
double getProgressPercentage() const; // Progreso total del juego double getProgressPercentage() const; // Progreso total del juego (0-100%)
double getCurrentStageProgressPercentage() const; // Progreso de la fase actual (0-100%) double getCurrentStageProgressPercentage() const; // Progreso de la fase actual (0-100%)
double getCurrentStageProgressFraction() const; // Progreso de la fase actual (0.0-1.0) double getCurrentStageProgressFraction() const; // Progreso de la fase actual (0.0-1.0)
int getPowerNeededForCurrentStage() const; int getPowerNeededForCurrentStage() const; // Poder restante para completar la fase actual
// ===== IMPLEMENTACIÓN DE IStageInfo ===== // --- Gestión de callbacks ---
// (Esto es lo que ven Player y Balloon) void setPowerChangeCallback(PowerChangeCallback callback); // Establece callback para cambios de poder
void removePowerChangeCallback(); // Elimina callback de cambios de poder
// --- Implementación de la interfaz IStageInfo ---
bool canCollectPower() const override; bool canCollectPower() const override;
void addPower(int amount) override; void addPower(int amount) override;
int getCurrentMenaceLevel() const override; int getCurrentMenaceLevel() const override;
using PowerChangeCallback = std::function<void(int)>;
void setPowerChangeCallback(PowerChangeCallback callback);
void removePowerChangeCallback();
private: private:
PowerChangeCallback power_change_callback_; PowerChangeCallback power_change_callback_; // Callback para notificar cambios de poder
void createDefaultStages(); // --- Métodos privados ---
bool validateStageIndex(size_t index) const; void createDefaultStages(); // Crea las fases predeterminadas del juego
void updateStageStatuses(); bool loadStagesFromFile(const std::string& filename); // Carga fases desde archivo
bool validateStageIndex(size_t index) const; // Valida que un índice de fase sea válido
void updateStageStatuses(); // Actualiza los estados de todas las fases
}; };

View File

@@ -1,14 +1,18 @@
#pragma once #pragma once
// Interfaz simple para lo que necesitan Player y Balloon /**
* Interfaz para acceso a información de fases.
* Proporciona una API mínima para componentes que necesitan interactuar con datos de fases
* sin requerir acceso a toda la funcionalidad de StageManager.
*/
class IStageInfo { class IStageInfo {
public: public:
virtual ~IStageInfo() = default; virtual ~IStageInfo() = default;
// Lo que necesita Player para recolectar poder // Interfaz de recolección de poder
virtual bool canCollectPower() const = 0; virtual bool canCollectPower() const = 0;
virtual void addPower(int amount) = 0; virtual void addPower(int amount) = 0;
// Lo que necesitan Player y Balloon para ajustar comportamiento // Ajuste de comportamiento del gameplay
virtual int getCurrentMenaceLevel() const = 0; virtual int getCurrentMenaceLevel() const = 0;
}; };