Files
coffee-crisis/source/game/game.h
T

545 lines
23 KiB
C++

#pragma once
#include <SDL3/SDL.h>
#include <cstdint> // for uint8_t
#include <string> // for string, basic_string
#include <vector> // for vector
#include "game/entities/bullet.h" // for Bullet::Kind (signatura de createBullet)
#include "game/entities/item.h" // for Item::Id (signatura de dropItem/createItem)
#include "utils/utils.h" // for DemoKeys, Color
class Balloon;
class Fade;
class Menu;
class MovingSprite;
class Player;
class SmartSprite;
class Sprite;
class Text;
class Texture;
struct JA_Music_t;
struct JA_Sound_t;
// 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 SHAKE_COUNTER = 10;
constexpr int HELP_COUNTER = 1000;
constexpr int GAME_COMPLETED_START_FADE = 500;
constexpr int GAME_COMPLETED_END = 700;
// Formaciones enemigas
constexpr int NUMBER_OF_ENEMY_FORMATIONS = 100;
constexpr int MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION = 50;
// 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;
// Clase Game
class Game {
private:
struct EnemyInit {
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float vel_x; // Velocidad inicial en el eje X
Uint8 kind; // Tipo de enemigo
Uint16 creation_counter; // Temporizador para la creación del enemigo
};
struct EnemyFormation // Contiene la información de una formación enemiga
{
Uint8 number_of_enemies; // Cantidad de enemigos que forman la formación
EnemyInit init[MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
};
struct EnemyPool {
EnemyFormation *set[10]; // Conjunto de formaciones enemigas
};
struct Stage // Contiene todas las variables relacionadas con una fase
{
EnemyPool *enemy_pool; // El conjunto de formaciones enemigas de la fase
Uint16 current_power; // Cantidad actual de poder
Uint16 power_to_complete; // Cantidad de poder que se necesita para completar la fase
Uint8 max_menace; // Umbral máximo de amenaza de la fase
Uint8 min_menace; // Umbral mínimo de amenaza de la fase
Uint8 number; // Numero de fase
};
struct Effect {
bool flash; // Indica si se ha de pintar la pantalla de blanco
bool shake; // Indica si se ha de agitar la pantalla
Uint8 shake_counter; // Contador para medir el tiempo que dura el efecto
};
// Estado para el efecto de agitación intensa (muerte del jugador)
struct DeathShake {
bool active; // Indica si el efecto está activo
Uint8 step; // Paso actual del efecto (0-7)
Uint32 last_step_ticks; // Ticks del último paso
};
// Fases de la secuencia de muerte del jugador
enum class DeathPhase : std::uint8_t {
NONE,
SHAKING,
WAITING,
DONE
};
// Estado de la secuencia de muerte del jugador
struct DeathSequence {
DeathPhase phase; // Fase actual
Uint32 phase_start_ticks; // Ticks del inicio de la fase actual
Player *player; // Jugador que está muriendo
};
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_paco_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
Uint16 counter; // Contador para el modo demo
DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo
DemoKeys data_file[TOTAL_DEMO_DATA]; // Datos del fichero con los movimientos para la demo
};
// Objetos y punteros
SDL_Renderer *renderer_; // El renderizador de la ventana
Section *section_; // Seccion actual dentro del juego
std::vector<Player *> players_; // Vector con los jugadores
std::vector<Balloon *> balloons_; // Vector con los globos
std::vector<Bullet *> bullets_; // Vector con las balas
std::vector<Item *> items_; // Vector con los items
std::vector<SmartSprite *> smart_sprites_; // Vector con los smartsprites
Texture *bullet_texture_; // Textura para las balas
std::vector<Texture *> item_textures_; // Vector con las texturas de los items
std::vector<Texture *> balloon_textures_; // Vector con las texturas de los globos
std::vector<Texture *> player1_textures_; // Vector con las texturas del jugador
std::vector<Texture *> player2_textures_; // Vector con las texturas del jugador
std::vector<std::vector<Texture *>> player_textures_; // Vector con todas las texturas de los jugadores;
Texture *game_buildings_texture_; // Textura con los edificios de fondo
Texture *game_clouds_texture_; // Textura con las nubes de fondo
Texture *game_grass_texture_; // Textura con la hierba del suelo
Texture *game_power_meter_texture_; // Textura con el marcador de poder de la fase
Texture *game_sky_colors_texture_; // Textura con los diferentes colores de fondo del juego
Texture *game_text_texture_; // Textura para los sprites con textos
Texture *game_over_texture_; // Textura para la pantalla de game over
Texture *game_over_end_texture_; // Textura para la pantalla de game over de acabar el juego
std::vector<std::vector<std::string> *> item_animations_; // Vector con las animaciones de los items
std::vector<std::vector<std::string> *> player_animations_; // Vector con las animaciones del jugador
std::vector<std::vector<std::string> *> balloon_animations_; // Vector con las animaciones de los globos
Text *text_; // Fuente para los textos del juego
Text *text_big_; // Fuente de texto grande
Text *text_scoreboard_; // Fuente para el marcador del juego
Text *text_nokia2_; // Otra fuente de texto para mensajes
Text *text_nokia_big2_; // Y la versión en grande
Menu *game_over_menu_; // Menú de la pantalla de game over
Menu *pause_menu_; // Menú de la pantalla de pausa
Fade *fade_; // Objeto para renderizar fades
SDL_Event *event_handler_; // Manejador de eventos
MovingSprite *clouds1_a_; // Sprite para las nubes superiores
MovingSprite *clouds1_b_; // Sprite para las nubes superiores
MovingSprite *clouds2_a_; // Sprite para las nubes inferiores
MovingSprite *clouds2_b_; // Sprite para las nubes inferiores
SmartSprite *n1000_sprite_; // Sprite con el texto 1.000
SmartSprite *n2500_sprite_; // Sprite con el texto 2.500
SmartSprite *n5000_sprite_; // Sprite con el texto 5.000
Sprite *buildings_sprite_; // Sprite con los edificios de fondo
Sprite *sky_colors_sprite_; // Sprite con los graficos del degradado de color de fondo
Sprite *grass_sprite_; // Sprite para la hierba
Sprite *power_meter_sprite_; // Sprite para el medidor de poder de la fase
Sprite *game_over_sprite_; // Sprite para dibujar los graficos del game over
Sprite *game_over_end_sprite_; // Sprite para dibujar los graficos del game over de acabar el juego
JA_Sound_t *balloon_sound_; // Sonido para la explosión del globo
JA_Sound_t *bullet_sound_; // Sonido para los disparos
JA_Sound_t *player_collision_sound_; // Sonido para la colisión del jugador con un enemigo
JA_Sound_t *hi_score_sound_; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound_t *item_drop_sound_; // Sonido para cuando se genera un item
JA_Sound_t *item_pick_up_sound_; // Sonido para cuando se recoge un item
JA_Sound_t *coffee_out_sound_; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound_t *stage_change_sound_; // Sonido para cuando se cambia de fase
JA_Sound_t *bubble1_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble2_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble3_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble4_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *clock_sound_; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound_t *power_ball_sound_; // Sonido para cuando se explota una Power Ball
JA_Sound_t *coffee_machine_sound_; // Sonido para cuando la máquina de café toca el suelo
JA_Music_t *game_music_; // Musica de fondo
// Variables
int num_players_; // Numero de jugadores
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint8 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
Uint32 hi_score_; // Puntuación máxima
bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima
std::string hi_score_name_; // Nombre del jugador que ostenta la máxima puntuación
Stage stage_[10]; // Variable con los datos de cada pantalla
Uint8 current_stage_; // Indica la fase actual
Uint8 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
Uint16 death_counter_; // Contador para la animación de muerte del jugador
Uint8 menace_current_; // Nivel de amenaza actual
Uint8 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 numero de globos
bool time_stopped_; // Indica si el tiempo está detenido
Uint16 time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido
Uint32 counter_; // Contador para el juego
Uint32 score_data_file_[TOTAL_SCORE_DATA]; // Datos del fichero de puntos
SDL_Rect sky_colors_rect_[4]; // Vector con las coordenadas de los 4 colores de cielo
Uint16 balloons_popped_; // Lleva la cuenta de los globos explotados
Uint8 last_enemy_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
int enemy_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float enemy_speed_; // Velocidad a la que se mueven los enemigos
float default_enemy_speed_; // Velocidad base de los enemigos, sin incrementar
Effect effect_; // Variable para gestionar los efectos visuales
DeathShake death_shake_; // Variable para gestionar el efecto de agitación intensa
DeathSequence death_sequence_; // Variable para gestionar la secuencia de muerte
Helper helper_; // Variable para gestionar las ayudas
bool power_ball_enabled_; // Indica si hay una powerball ya activa
Uint8 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
Uint8 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
Uint8 player_one_control_; // Variable para almacenar el valor de las opciones
EnemyFormation enemy_formation_[NUMBER_OF_ENEMY_FORMATIONS]; // Vector con todas las formaciones enemigas
EnemyPool enemy_pool_[10]; // Variable con los diferentes conjuntos de formaciones enemigas
Uint8 last_stage_reached_; // Contiene el numero 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
int clouds_speed_{0}; // Velocidad a la que se desplazan las nubes
int pause_counter_; // Contador para salir del menu de pausa y volver al juego
bool leaving_pause_menu_; // Indica si esta saliendo del menu de pausa para volver al juego
bool pause_initialized_; // Indica si la pausa ha sido inicializada
bool game_over_initialized_; // Indica si el game over ha sido inicializado
int game_over_post_fade_; // Opción a realizar cuando termina el fundido del game over
#ifdef PAUSE
bool pause;
#endif
// Actualiza el juego
void update();
// Dibuja el juego
void render();
// Inicializa las variables necesarias para la sección 'Game'
void init();
// Carga los recursos necesarios para la sección 'Game'
void loadMedia();
// Carga el fichero de puntos
auto loadScoreFile() -> bool;
// Carga el fichero de datos para la demo
auto loadDemoFile() -> bool;
// Guarda el fichero de puntos
auto saveScoreFile() -> bool;
// Guarda el fichero de datos para la demo
auto saveDemoFile() -> bool;
// Inicializa las formaciones enemigas
void initEnemyFormations();
// Inicializa los conjuntos de formaciones
void initEnemyPools();
// Inicializa las fases del juego
void initGameStages();
// Crea una formación de enemigos
void deployEnemyFormation();
// Aumenta el poder de la fase
void increaseStageCurrentPower(Uint8 power);
// Establece el valor de la variable
void setHiScore(Uint32 score);
// Actualiza el valor de HiScore en caso necesario
void updateHiScore();
// Transforma un valor numérico en una cadena de 6 cifras
static auto updateScoreText(Uint32 num) -> std::string;
// Pinta el marcador en pantalla usando un objeto texto
void renderScoreBoard();
// Actualiza las variables del jugador
void updatePlayers();
// Dibuja a los jugadores
void renderPlayers();
// Actualiza las variables de la fase
void updateStage();
// Actualiza el estado de muerte
void updateDeath();
// Renderiza el fade final cuando se acaba la partida
void renderDeathFade(int counter);
// Actualiza los globos
void updateBalloons();
// Pinta en pantalla todos los globos activos
void renderBalloons();
// Crea un globo nuevo en el vector de globos
auto createBalloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer) -> Uint8;
// Crea una PowerBall
void createPowerBall();
// Establece la velocidad de los globos
void setBalloonSpeed(float speed);
// Incrementa la velocidad de los globos
void incBalloonSpeed();
// 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(Balloon *balloon);
// Explosiona un globo. Lo destruye
void destroyBalloon(Balloon *balloon);
// Destruye todos los globos
void destroyAllBalloons();
// Detiene todos los globos
void stopAllBalloons(Uint16 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
auto checkPlayerBalloonCollision(Player *player) -> bool;
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(Player *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, Bullet::Kind 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
auto dropItem() -> Item::Id;
// Crea un objeto item
void createItem(Item::Id kind, float x, float y);
// Vacia el vector de items
void freeItems();
// Crea un objeto SmartSprite
void createItemScoreSprite(int x, int y, const SmartSprite *sprite);
// Vacia el vector de smartsprites
void freeSmartSprites();
// Dibuja el efecto de flash
void renderFlashEffect();
// Actualiza el efecto de agitar la pantalla
void updateShakeEffect();
// Crea un SmartSprite para arrojar el item café al recibir un impacto
void throwCoffee(int x, int y);
// Actualiza los SmartSprites
void updateSmartSprites();
// Pinta los SmartSprites activos
void renderSmartSprites();
// Acciones a realizar cuando el jugador muere
void killPlayer(Player *player);
// Calcula y establece el valor de amenaza en funcion de los globos activos
void evaluateAndSetMenace();
// Obtiene el valor de la variable
[[nodiscard]] auto getMenace() const -> Uint8;
// Establece el valor de la variable
void setTimeStopped(bool value);
// Obtiene el valor de la variable
[[nodiscard]] auto isTimeStopped() const -> bool;
// Establece el valor de la variable
void setTimeStoppedCounter(Uint16 value);
// Incrementa el valor de la variable
void incTimeStoppedCounter(Uint16 value);
// Actualiza la variable EnemyDeployCounter
void updateEnemyDeployCounter();
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter();
// Gestiona el nivel de amenaza
void updateMenace();
// Actualiza el fondo
void updateBackground();
// Dibuja el fondo
void renderBackground();
// Gestiona la entrada durante el juego
void checkGameInput();
// 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();
// Inicia el efecto de agitación intensa de la pantalla
void shakeScreen();
// Actualiza el efecto de agitación intensa
void updateDeathShake();
// Indica si el efecto de agitación intensa está activo
[[nodiscard]] auto isDeathShaking() const -> bool;
// Actualiza la secuencia de muerte del jugador
void updateDeathSequence();
// Actualiza las variables del menu de pausa del juego
void updatePausedGame();
// Dibuja el menu de pausa del juego
void renderPausedGame();
// Inicializa el estado de pausa del juego
void enterPausedGame();
// Actualiza los elementos de la pantalla de game over
void updateGameOverScreen();
// Dibuja los elementos de la pantalla de game over
void renderGameOverScreen();
// Inicializa el estado de game over
void enterGameOverScreen();
// Indica si se puede crear una powerball
auto canPowerBallBeCreated() -> bool;
// Calcula el poder actual de los globos en pantalla
auto calculateScreenPower() -> int;
// 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 muerto
auto allPlayersAreDead() -> bool;
// Elimina todos los objetos contenidos en vectores
void deleteAllVectorObjects();
// Establece la máxima puntuación desde fichero o desde las puntuaciones online
void setHiScore();
public:
// Constructor
Game(int num_players, int current_stage, SDL_Renderer *renderer, bool demo, Section *section);
// Destructor
~Game();
Game(const Game &) = delete;
auto operator=(const Game &) -> Game & = delete;
// Bucle para el juego
void run();
// Ejecuta un frame del juego
void iterate();
// Indica si el juego ha terminado
[[nodiscard]] auto hasFinished() const -> bool;
// Procesa un evento
void handleEvent(const SDL_Event *event);
};