#pragma once #include // Para SDL_Event, SDL_Renderer, SDL_Texture, Uint64 #include // Para shared_ptr, unique_ptr #include // Para string #include // Para vector #include "difficulty.h" // Para Difficulty #include "item.h" // Para Item, ItemType #include "manage_hiscore_table.h" // Para HiScoreEntry #include "options.h" // Para SettingsOptions, settings, DifficultyCode (ptr only) #include "path_sprite.h" // Para PathSprite, Path #include "player.h" // Para Player #include "smart_sprite.h" // Para SmartSprite #include "utils.h" // Para Demo class Background; class Balloon; class BalloonManager; class Bullet; class Fade; class Input; class Scoreboard; class Screen; class Tabe; class Texture; enum class BulletType : Uint8; // Modo demo constexpr bool GAME_MODE_DEMO_OFF = false; constexpr bool GAME_MODE_DEMO_ON = true; // Cantidad de elementos a escribir en los ficheros de datos constexpr int TOTAL_SCORE_DATA = 3; // Clase Game class Game { public: // Constructor Game(int player_id, int current_stage, bool demo); // Destructor ~Game(); // Bucle principal del juego void run(); private: // --- Tipos internos --- enum class GameState { FADE_IN, ENTERING_PLAYER, SHOWING_GET_READY_MESSAGE, PLAYING, COMPLETED, GAME_OVER, }; // --- Constantes internas --- static constexpr int HELP_COUNTER = 1000; static constexpr int GAME_COMPLETED_START_FADE = 500; static constexpr int GAME_COMPLETED_END = 700; static constexpr int GAME_OVER_COUNTER = 350; static constexpr int TIME_STOPPED_COUNTER = 360; static constexpr int ITEM_POINTS_1_DISK_ODDS = 10; static constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6; static constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3; static constexpr int ITEM_CLOCK_ODDS = 5; static constexpr int ITEM_COFFEE_ODDS = 5; static constexpr int ITEM_POWER_BALL_ODDS = 0; static constexpr int ITEM_COFFEE_MACHINE_ODDS = 4; // --- Estructuras --- struct Helper { bool need_coffee{false}; // Indica si se necesitan cafes bool need_coffee_machine{false}; // Indica si se necesita PowerUp bool need_power_ball{false}; // Indica si se necesita una PowerBall int counter; // Contador para no dar ayudas consecutivas int item_disk_odds; // Probabilidad de aparición del objeto int item_gavina_odds; // Probabilidad de aparición del objeto int item_pacmar_odds; // Probabilidad de aparición del objeto int item_clock_odds; // Probabilidad de aparición del objeto int item_coffee_odds; // Probabilidad de aparición del objeto int item_coffee_machine_odds; // Probabilidad de aparición del objeto Helper() : counter(HELP_COUNTER), item_disk_odds(ITEM_POINTS_1_DISK_ODDS), item_gavina_odds(ITEM_POINTS_2_GAVINA_ODDS), item_pacmar_odds(ITEM_POINTS_3_PACMAR_ODDS), item_clock_odds(ITEM_CLOCK_ODDS), item_coffee_odds(ITEM_COFFEE_ODDS), item_coffee_machine_odds(ITEM_COFFEE_MACHINE_ODDS) {} }; // --- Objetos y punteros --- SDL_Renderer *renderer_; // El renderizador de la ventana Screen *screen_; // Objeto encargado de dibujar en pantalla Input *input_; // Manejador de entrada Scoreboard *scoreboard_; // Objeto para dibujar el marcador std::unique_ptr background_; // Objeto para dibujar el fondo del juego SDL_Texture *canvas_; // Textura para dibujar la zona de juego std::vector> players_; // Vector con los jugadores std::vector> bullets_; // Vector con las balas std::vector> items_; // Vector con los items std::vector> smart_sprites_; // Vector con los smartsprites std::vector> path_sprites_; // Vector con los pathsprites std::vector> item_textures_; // Vector con las texturas de los items std::vector>> player_textures_; // Vector con todas las texturas de los jugadores std::vector> game_text_textures_; // Vector con las texturas para los sprites con textos std::vector> item_animations_; // Vector con las animaciones de los items std::vector> player_animations_; // Vector con las animaciones del jugador std::unique_ptr fade_in_; // Objeto para renderizar fades std::unique_ptr fade_out_; // Objeto para renderizar fades std::unique_ptr balloon_manager_; // Objeto para gestionar los globos std::unique_ptr tabe_; // Objeto para gestionar el Tabe Volaor std::vector paths_; // Vector con los recorridos precalculados almacenados // --- Variables de estado --- HiScoreEntry hi_score_ = HiScoreEntry( Options::settings.hi_score_table[0].name, Options::settings.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta Demo demo_; // Variable con todas las variables relacionadas con el modo demo Difficulty::Code difficulty_ = Options::settings.difficulty; // Dificultad del juego Helper helper_; // Variable para gestionar las ayudas Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima bool paused_ = false; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade) // bool paused_by_service_menu_ = false; float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad int counter_ = 0; // Contador para el juego int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos 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 GameState state_ = GameState::FADE_IN; // Estado std::vector> players_to_reorder_; #ifdef _DEBUG bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados // Comprueba los eventos en el modo DEBUG void checkDebugEvents(const SDL_Event &event); #endif // --- Métodos internos --- void update(); // Actualiza el juego void render(); // Dibuja el juego void checkEvents(); // Comprueba los eventos que hay en cola void setResources(); // Asigna texturas y animaciones void updateHiScore(); // Actualiza el valor de HiScore en caso necesario void updatePlayers(); // Actualiza las variables del jugador void renderPlayers(); // Dibuja a los jugadores void updateStage(); // Comprueba si hay cambio de fase y actualiza las variables void updateGameStateGameOver(); // Actualiza el estado de fin de la partida void destroyAllItems(); // Destruye todos los items auto checkPlayerBalloonCollision(std::shared_ptr &player) -> std::shared_ptr; // Comprueba la colisión entre el jugador y los globos activos void checkPlayerItemCollision(std::shared_ptr &player); // Comprueba la colisión entre el jugador y los items void checkBulletCollision(); // Comprueba y procesa la colisión de las balas void updateBullets(); // Mueve las balas activas void renderBullets(); // Pinta las balas activas void createBullet(int x, int y, BulletType kind, bool powered_up, int owner); // Crea un objeto bala void freeBullets(); // Vacia el vector de balas void updateItems(); // Actualiza los items void renderItems(); // Pinta los items activos auto dropItem() -> ItemType; // Devuelve un item en función del azar void createItem(ItemType type, float x, float y); // Crea un objeto item void freeItems(); // Vacia el vector de items void createItemText(int x, std::shared_ptr texture); // Crea un objeto PathSprite void createMessage(const std::vector &paths, std::shared_ptr texture); // Crea un objeto PathSprite void freeSmartSprites(); // Vacia el vector de smartsprites void freePathSprites(); // Vacia el vector de pathsprites void throwCoffee(int x, int y); // Crea un SpriteSmart para arrojar el item café al recibir un impacto void updateSmartSprites(); // Actualiza los SpriteSmarts void renderSmartSprites(); // Pinta los SpriteSmarts activos void updatePathSprites(); // Actualiza los PathSprites void renderPathSprites(); // Pinta los PathSprites activos void handlePlayerCollision(std::shared_ptr &player); // Acciones a realizar cuando el jugador colisiona con un globo void updateTimeStopped(); // Actualiza y comprueba el valor de la variable void updateBackground(); // Actualiza el fondo void initPaths(); // Inicializa las variables que contienen puntos de ruta para mover objetos void enableTimeStopItem(); // Habilita el efecto del item de detener el tiempo void disableTimeStopItem(); // Deshabilita el efecto del item de detener el tiempo void updateHelper(); // Actualiza las variables de ayuda auto allPlayersAreWaitingOrGameOver() -> bool; // Comprueba si todos los jugadores han terminado de jugar auto allPlayersAreGameOver() -> bool; // Comprueba si todos los jugadores han terminado de jugar auto allPlayersAreNotPlaying() -> bool; // Comprueba si todos los jugadores han terminado de jugar void updateScoreboard(); // Actualiza el marcador void fillCanvas(); // Dibuja los elementos de la zona de juego en su textura void pause(bool value); // Pausa el juego void addScoreToScoreBoard(const std::shared_ptr &player); // Añade una puntuación a la tabla de records void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Saca del estado de GAME OVER al jugador si el otro está activo void checkPlayersStatusPlaying(); // Comprueba el estado de juego de los jugadores auto getPlayer(int id) -> std::shared_ptr; // Obtiene un jugador a partir de su "id" static auto getController(int player_id) -> int; // Obtiene un controlador a partir del "id" del jugador void checkInput(); // Gestiona la entrada durante el juego void checkPauseInput(); // Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego. void demoHandleInput(); // Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos. void demoHandlePassInput(); // Gestiona las entradas de los jugadores en el modo demo para saltarse la demo. void demoHandlePlayerInput(const std::shared_ptr &player, int index); // Procesa las entradas para un jugador específico durante el modo demo. void handleFireInput(const std::shared_ptr &player, BulletType bullet_type); // Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos. void handlePlayersInput(); // Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo). void handleNormalPlayerInput(const std::shared_ptr &player); // Maneja las entradas de movimiento y disparo para un jugador en modo normal. void handleFireInputs(const std::shared_ptr &player, bool autofire, int controller_index); // Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado. void handlePlayerContinue(const std::shared_ptr &player); // Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio. void handleNameInput(const std::shared_ptr &player); // Procesa las entradas para la introducción del nombre del jugador. void initDemo(int player_id); // Inicializa las variables para el modo DEMO void setTotalPower(); // Calcula el poder total necesario para completar el juego void initScoreboard(); // Inicializa el marcador void initDifficultyVars(); // Inicializa las opciones relacionadas con la dificultad void initPlayers(int player_id); // Inicializa los jugadores static void playMusic(); // Hace sonar la música void stopMusic() const; // Detiene la música void playSound(const std::string &name) const; // Hace sonar un sonido void updateDemo(); // Actualiza las variables durante el modo demo void updateGameStateFadeIn(); // Actualiza las variables durante dicho estado void updateGameStateEnteringPlayer(); // Actualiza las variables durante dicho estado void updateGameStateShowingGetReadyMessage(); // Actualiza las variables durante dicho estado void updateGameStatePlaying(); // Actualiza las variables durante el transcurso normal del juego void updateGameStateCompleted(); // Gestiona eventos para el estado del final del juego void checkState(); // Comprueba el estado del juego void cleanVectors(); // Vacía los vectores de elementos deshabilitados void updateMenace(); // Gestiona el nivel de amenaza void evaluateAndSetMenace(); // Calcula y establece el valor de amenaza en funcion de los globos activos void checkAndUpdateBalloonSpeed(); // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase void setState(GameState state); // Cambia el estado del juego void movePlayersToFront(); // Organiza los jugadores para que los vivos se pinten sobre los muertos void checkServiceMenu(); // Comprueba si está activo el menu de servicio para poner el juego en pausa auto checkBulletTabeCollision(std::shared_ptr bullet) -> bool; void handleTabeHitEffects(); auto checkBulletBalloonCollision(std::shared_ptr bullet) -> bool; void processBalloonHit(std::shared_ptr bullet, std::shared_ptr balloon); void handleItemDrop(std::shared_ptr balloon, std::shared_ptr player); void handleBalloonDestruction(std::shared_ptr balloon, std::shared_ptr player); #ifdef RECORDING void updateRecording(); // Actualiza las variables durante el modo de grabación #endif };