#pragma once #include // for SDL_Renderer, SDL_Texture #include // for Uint32 #include // for shared_ptr, unique_ptr #include // for string #include // for vector #include "balloon.h" // for Balloon #include "player.h" // for Player #include "utils.h" // for DemoKeys, Color, HiScoreEntry class Asset; class Background; class BalloonFormations; class Bullet; class Explosions; class Fade; class Input; class Item; class Scoreboard; class Screen; class SmartSprite; class Text; class Texture; enum class BulletType; // lines 26-26 struct JA_Music_t; // lines 27-27 struct JA_Sound_t; // lines 28-28 enum class ItemType; // 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; constexpr int TOTAL_DEMO_DATA = 2000; // Contadores constexpr int STAGE_COUNTER = 200; constexpr int HELP_COUNTER = 1000; constexpr int GAME_COMPLETED_START_FADE = 500; constexpr int GAME_COMPLETED_END = 700; constexpr int GAME_OVER_COUNTER = 350; // Porcentaje de aparición de los objetos constexpr int ITEM_POINTS_1_DISK_ODDS = 10; constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6; constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3; constexpr int ITEM_CLOCK_ODDS = 5; constexpr int ITEM_COFFEE_ODDS = 5; constexpr int ITEM_POWER_BALL_ODDS = 0; constexpr int ITEM_COFFEE_MACHINE_ODDS = 4; // Valores para las variables asociadas a los objetos constexpr int TIME_STOPPED_COUNTER = 300; /* 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: 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 }; struct Demo { bool enabled; // Indica si está activo el modo demo bool recording; // Indica si está activado el modo para grabar la demo int counter; // Contador para el modo demo DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo DemoKeys data_file[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo }; // 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 std::unique_ptr explosions_; // Objeto para dibujar explosiones std::unique_ptr balloon_formations_; // Objeto para gestionar las oleadas enemigas SDL_Texture *canvas_; // Textura para dibujar la zona de juego std::vector> players_; // Vector con los jugadores std::vector> balloons_; // Vector con los globos std::vector> bullets_; // Vector con las balas std::vector> items_; // Vector con los items std::vector> smart_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> balloon_textures_; // Vector con las texturas de los globos std::vector> explosions_textures_; // Vector con las texturas de las explosiones 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::vector> balloon_animations_; // Vector con las animaciones de los globos std::vector> explosions_animations_; // Vector con las animaciones de las explosiones std::unique_ptr text_; // Fuente para los textos del juego std::unique_ptr text_big_; // Fuente de texto grande std::unique_ptr text_nokia2_; // Otra fuente de texto para mensajes std::unique_ptr text_nokia2_big_; // Y la versión en grande std::unique_ptr fade_; // Objeto para renderizar fades // Variables Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima HiScoreEntry hi_score_; // Máxima puntuación y nombre de quien la ostenta int current_stage_; // Indica la fase actual int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage float stage_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto float get_ready_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto int game_over_counter_; // Contador para el estado de fin de partida int menace_current_; // Nivel de amenaza actual int menace_threshold_; // 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 bool time_stopped_; // Indica si el tiempo está detenido int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido int counter_; // Contador para el juego int balloons_popped_; // Lleva la cuenta de los globos explotados int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir; int balloon_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero float balloon_speed_; // Velocidad a la que se mueven los enemigos float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar Helper helper_; // Variable para gestionar las ayudas bool power_ball_enabled_; // Indica si hay una powerball ya activa int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos GameDifficulty difficulty_; // Dificultad del juego float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad Color difficulty_color_; // Color asociado a la dificultad int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado Demo demo_; // Variable con todas las variables relacionadas con el modo demo int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases bool paused_; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade) int current_power_; // Poder actual almacenado para completar la fase #ifdef DEBUG bool auto_pop_balloons_; // Si es true, incrementa automaticamente los globos explotados #endif // Actualiza el juego void update(); // Dibuja el juego void render(); // Comprueba los eventos que hay en cola void checkEvents(); // Inicializa las variables necesarias para la sección 'Game' void init(int player_id); // Carga los recursos necesarios para la sección 'Game' void loadMedia(); // Libera los recursos previamente cargados void unloadMedia(); // Carga el fichero de datos para la demo bool loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA]); #ifdef RECORDING // Guarda el fichero de datos para la demo bool saveDemoFile(const std::string &file_path); #endif // Crea una formación de enemigos void deployBalloonFormation(); // Aumenta el poder de la fase void increaseStageCurrentPower(int power); // 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 updateGameOver(); // Actualiza los globos void updateBalloons(); // Pinta en pantalla todos los globos activos void renderBalloons(); // Crea un globo nuevo en el vector de globos std::shared_ptr createBalloon(float x, int y, int kind, float velx, float speed, int stopped_counter); // Crea una PowerBall void createPowerBall(); // Establece la velocidad de los globos void setBalloonSpeed(float speed); // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase void updateBalloonSpeed(); // Explosiona un globo. Lo destruye y crea otros dos si es el caso void popBalloon(std::shared_ptr balloon); // Explosiona un globo. Lo destruye void destroyBalloon(std::shared_ptr &balloon); // Destruye todos los globos void destroyAllBalloons(); // Detiene todos los globos void stopAllBalloons(int time); // Pone en marcha todos los globos void startAllBalloons(); // Vacia el vector de globos void freeBalloons(); // 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 la colisión entre las balas y los globos void checkBulletBalloonCollision(); // Mueve las balas activas void moveBullets(); // 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 SpriteSmart void createItemScoreSprite(int x, int y, std::shared_ptr texture); // Vacia el vector de smartsprites void freeSpriteSmarts(); // Crea un SpriteSmart para arrojar el item café al recibir un impacto void throwCoffee(int x, int y); // Actualiza los SpriteSmarts void updateSpriteSmarts(); // Pinta los SpriteSmarts activos void renderSpriteSmarts(); // Acciones a realizar cuando el jugador muere void killPlayer(std::shared_ptr &player); // Calcula y establece el valor de amenaza en funcion de los globos activos void evaluateAndSetMenace(); // Obtiene el valor de la variable int getMenace() const; // Establece el valor de la variable void setTimeStopped(bool value); // Obtiene el valor de la variable bool isTimeStopped() const; // Establece el valor de la variable void setTimeStoppedCounter(int value); // Incrementa el valor de la variable void incTimeStoppedCounter(int value); // Actualiza la variable EnemyDeployCounter void updateBalloonDeployCounter(); // Actualiza y comprueba el valor de la variable void updateTimeStoppedCounter(); // Gestiona el nivel de amenaza void updateMenace(); // Actualiza el fondo void updateBackground(); // Pinta diferentes mensajes en la pantalla void renderMessages(); // Habilita el efecto del item de detener el tiempo void enableTimeStopItem(); // Deshabilita el efecto del item de detener el tiempo void disableTimeStopItem(); // Indica si se puede crear una powerball bool canPowerBallBeCreated(); // Calcula el poder actual de los globos en pantalla int calculateScreenPower(); // Inicializa las variables que contienen puntos de ruta para mover objetos void initPaths(); // Actualiza el tramo final de juego, una vez completado void updateGameCompleted(); // 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(); // Elimina todos los objetos contenidos en vectores void deleteAllVectorObjects(); // Recarga las texturas void reloadTextures(); // 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); // Comprueba si la música ha de estar sonando void checkMusicStatus(); // Añade una puntuación a la tabla de records void addScoreToScoreBoard(const std::string &name, int score); // 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. // Incluye movimientos (izquierda, derecha, sin movimiento) y disparos automáticos. 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); public: // Constructor Game(int playerID, int current_stage, bool demo); // Destructor ~Game(); // Bucle para el juego void run(); };