Files
coffee_crisis_arcade_edition/source/game.h
2024-10-26 08:11:30 +02:00

463 lines
17 KiB
C++

#pragma once
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // para Uint32
#include <memory> // para shared_ptr, unique_ptr
#include <string> // para string
#include <vector> // para vector
#include "balloon.h" // para Balloon
#include "player.h" // para Player
#include "utils.h" // para DemoKeys, Color, HiScoreEntry
#include "options.h" // para options
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;
/*
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:
// Constantes
// Contadores
static constexpr int STAGE_COUNTER_ = 200;
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_ = 300;
// 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> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Explosions> explosions_; // Objeto para dibujar explosiones
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para gestionar las oleadas enemigas
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::shared_ptr<Balloon>> balloons_; // Vector con los globos
std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
std::shared_ptr<Texture> bullet_texture_; // Textura para las balas
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores;
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
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
std::vector<std::vector<std::string>> explosions_animations_; // Vector con las animaciones de las explosiones
std::unique_ptr<Text> text_; // Fuente para los textos del juego
std::unique_ptr<Text> text_big_; // Fuente de texto grande
std::unique_ptr<Text> text_nokia2_; // Otra fuente de texto para mensajes
std::unique_ptr<Text> text_nokia2_big_; // Y la versión en grande
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// 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
int current_stage_; // Indica la fase actual
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
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 game_completed_ = false; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
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 power_ball_enabled_ = false; // Indica si hay una powerball ya activa
bool time_stopped_ = false; // Indica si el tiempo está detenido
float balloon_speed_; // Velocidad a la que se mueven los enemigos
float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
float get_ready_bitmap_path_[STAGE_COUNTER_]; // Vector con los puntos X por donde se desplaza el texto
int stage_bitmap_path_[STAGE_COUNTER_]; // Vector con los puntos Y por donde se desplaza el texto
int balloon_deploy_counter_ = 0; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
int balloons_popped_ = 0; // Lleva la cuenta de los globos explotados
int counter_ = 0; // Contador para el juego
int current_power_ = 0; // Poder actual almacenado para completar la fase
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 last_balloon_deploy_ = 0; // Guarda cual ha sido la última formación desplegada para no repetir;
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
int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
int stage_bitmap_counter_ = STAGE_COUNTER_; // Contador para el tiempo visible del texto de Stage
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
#ifdef DEBUG
bool auto_pop_balloons_ = false; // 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();
// Asigna texturas y animaciones
void setResources();
// 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<Balloon> 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> balloon);
// Explosiona un globo. Lo destruye
void destroyBalloon(std::shared_ptr<Balloon> &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> &player);
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(std::shared_ptr<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, 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> 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> &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();
// 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<Player> 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> &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> &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> &player);
// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
void handleFireInputs(const std::shared_ptr<Player> &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> &player);
// Procesa las entradas para la introducción del nombre del jugador.
void handleNameInput(const std::shared_ptr<Player> &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);
public:
// Constructor
Game(int playerID, int current_stage, bool demo);
// Destructor
~Game();
// Bucle para el juego
void run();
};