#pragma once #include // Para SDL_Renderer, SDL_Texture #include // Para Uint32, Uint8 #include // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN #include // Para shared_ptr, unique_ptr #include // Para string #include // Para vector #include "manage_hiscore_table.h" // Para HiScoreEntry #include "options.h" // Para Options, OptionsGame, options #include "player.h" // Para Player #include "utils.h" // Para Demo class Asset; // lines 13-13 class Background; // lines 14-14 class BalloonManager; class Tabe; class Bullet; // lines 15-15 class Fade; // lines 16-16 class Input; // lines 17-17 class Item; // lines 18-18 class PathSprite; // lines 19-19 class Scoreboard; // lines 20-20 class Screen; // lines 21-21 class SmartSprite; // lines 22-22 class Texture; // lines 23-23 enum class BulletType : Uint8; // lines 24-24 enum class ItemType; // lines 25-25 struct Path; // lines 26-26 // 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; /* Esta clase gestiona un estado del programa. Se encarga de toda la parte en la que se está jugando. Tiene: - Cacheadas todas las texturas y animaciones que usaran los diferentes objetos. Mediante el método loadMedia() almacena en vectores todos los recursos - Tiene vectores con objetos: jugadores, enemigos, balas, explosiones, objetos y otros (sprites con los puntos al coger objetos) - Se encarga de comprobar las colisiones entre los diferentes objetos, los marca como deshabilitados si es el caso y luego revisa los vectores para eliminar los objetos deshabilitados Utiliza: - Un objeto para dibujar el fondo animado - Un objeto para dibujar el marcador La clase comprueba el nivel de amenaza que hay en pantalla contando el número de enemigos y su peligrosidad y actua en consecuencia: - Generando items - Generando nuevas oleadas enemigas Mientras haya un jugador activo siempre puede unirse un segundo jugador. Cada vez que un jugador muere aparece una cuenta atras para permitirle continuar. Si la cuenta atras de ambos jugadores llega a cero, el juego termina. Cuando ambos jugadores han finalizado, se permite introducir nombre para la tabla de records adjuntando la máxima puntuación obtenida en la partida, solo en caso de que hayan conseguido superar la puntuación mínima. */ // Clase Game class Game { private: // Enum enum class GameState { FADE_IN, ENTERING_PLAYER, SHOWING_GET_READY_MESSAGE, PLAYING, COMPLETED, GAME_OVER, }; // Contadores 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; // Porcentaje de aparición de los objetos 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; // Indica si se necesitan cafes bool need_coffee_machine; // Indica si se necesita PowerUp bool need_power_ball; // 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 // Constructor con valores predeterminados Helper() : need_coffee(false), need_coffee_machine(false), need_power_ball(false), 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 Asset *asset_; // Objeto que gestiona todos los ficheros de recursos 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 smartsprites std::shared_ptr bullet_texture_; // Textura para las balas 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 HiScoreEntry hi_score_ = HiScoreEntry( options.game.hi_score_table[0].name, options.game.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 GameDifficulty difficulty_ = options.game.difficulty; // Dificultad del juego Helper helper_; // Variable para gestionar las ayudas Uint32 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) 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 #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 // Actualiza el juego void update(); // Dibuja el juego void render(); // Comprueba los eventos que hay en cola void checkEvents(); // Asigna texturas y animaciones void setResources(); // Actualiza el valor de HiScore en caso necesario void updateHiScore(); // Actualiza las variables del jugador void updatePlayers(); // Dibuja a los jugadores void renderPlayers(); // Comprueba si hay cambio de fase y actualiza las variables void updateStage(); // Actualiza el estado de fin de la partida void updateGameStateGameOver(); // Destruye todos los items void destroyAllItems(); // Comprueba la colisión entre el jugador y los globos activos bool checkPlayerBalloonCollision(std::shared_ptr &player); // Comprueba la colisión entre el jugador y los items void checkPlayerItemCollision(std::shared_ptr &player); // Comprueba y procesa la colisión de las balas void checkBulletCollision(); // Mueve las balas activas void updateBullets(); // Pinta las balas activas void renderBullets(); // Crea un objeto bala void createBullet(int x, int y, BulletType kind, bool powered_up, int owner); // Vacia el vector de balas void freeBullets(); // Actualiza los items void updateItems(); // Pinta los items activos void renderItems(); // Devuelve un item en función del azar ItemType dropItem(); // Crea un objeto item void createItem(ItemType type, float x, float y); // Vacia el vector de items void freeItems(); // Crea un objeto PathSprite void createItemText(int x, std::shared_ptr texture); // Crea un objeto PathSprite void createMessage(const std::vector &paths, std::shared_ptr texture); // Vacia el vector de smartsprites void freeSmartSprites(); // Vacia el vector de pathsprites void freePathSprites(); // Crea un SpriteSmart para arrojar el item café al recibir un impacto void throwCoffee(int x, int y); // Actualiza los SpriteSmarts void updateSmartSprites(); // Pinta los SpriteSmarts activos void renderSmartSprites(); // Actualiza los PathSprites void updatePathSprites(); // Pinta los PathSprites activos void renderPathSprites(); // Acciones a realizar cuando el jugador muere void killPlayer(std::shared_ptr &player); // Actualiza y comprueba el valor de la variable void updateTimeStopped(); // Actualiza el fondo void updateBackground(); // Inicializa las variables que contienen puntos de ruta para mover objetos void initPaths(); // Habilita el efecto del item de detener el tiempo void enableTimeStopItem(); // Deshabilita el efecto del item de detener el tiempo void disableTimeStopItem(); // Actualiza las variables de ayuda void updateHelper(); // Comprueba si todos los jugadores han terminado de jugar bool allPlayersAreWaitingOrGameOver(); // Comprueba si todos los jugadores han terminado de jugar bool allPlayersAreGameOver(); // Comprueba si todos los jugadores han terminado de jugar bool allPlayersAreNotPlaying(); // Actualiza el marcador void updateScoreboard(); // Dibuja los elementos de la zona de juego en su textura void fillCanvas(); // Pausa el juego void pause(bool value); // Añade una puntuación a la tabla de records void addScoreToScoreBoard(const std::shared_ptr &player); // Saca del estado de GAME OVER al jugador si el otro está activo void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Comprueba el estado de juego de los jugadores void checkPlayersStatusPlaying(); // Obtiene un jugador a partir de su "id" std::shared_ptr getPlayer(int id); // Obtiene un controlador a partir del "id" del jugador int getController(int playerId); // Gestiona la entrada durante el juego void checkInput(); // Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego. void checkPauseInput(); // Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos. void handleDemoMode(); // Procesa las entradas para un jugador específico durante el modo demo. void handleDemoPlayerInput(const std::shared_ptr &player, int index); // Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos. void handleFireInput(const std::shared_ptr &player, BulletType bulletType); // Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo). void handlePlayersInput(); // Maneja las entradas de movimiento y disparo para un jugador en modo normal. void handleNormalPlayerInput(const std::shared_ptr &player); // Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado. void handleFireInputs(const std::shared_ptr &player, bool autofire, int controllerIndex); // Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio. void handlePlayerContinue(const std::shared_ptr &player); // Procesa las entradas para la introducción del nombre del jugador. void handleNameInput(const std::shared_ptr &player); // Inicializa las variables para el modo DEMO void initDemo(int player_id); // Calcula el poder total necesario para completar el juego void setTotalPower(); // Inicializa el marcador void initScoreboard(); // Inicializa las opciones relacionadas con la dificultad void initDifficultyVars(); // Inicializa los jugadores void initPlayers(int player_id); // Pausa la música void pauseMusic(); // Reanuda la música void resumeMusic(); // Hace sonar la música void playMusic(); // Detiene la música void stopMusic(); // Actualiza las variables durante el modo demo void updateDemo(); #ifdef RECORDING // Actualiza las variables durante el modo de grabación void updateRecording(); #endif // Actualiza las variables durante dicho estado void updateGameStateFadeIn(); // Actualiza las variables durante dicho estado void updateGameStateEnteringPlayer(); // Actualiza las variables durante dicho estado void updateGameStateShowingGetReadyMessage(); // Actualiza las variables durante el transcurso normal del juego void updateGameStatePlaying(); // Gestiona eventos para el estado del final del juego void updateGameStateCompleted(); // Comprueba el estado del juego void checkState(); // Vacía los vectores de elementos deshabilitados void cleanVectors(); // Gestiona el nivel de amenaza void updateMenace(); // Calcula y establece el valor de amenaza en funcion de los globos activos void evaluateAndSetMenace(); // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase void checkAndUpdateBalloonSpeed(); // Cambia el estado del juego void setState(GameState state); public: // Constructor Game(int playerID, int current_stage, bool demo); // Destructor ~Game(); // Bucle para el juego void run(); };