Files
coffee_crisis_arcade_edition/source/game.h

434 lines
15 KiB
C++

#pragma once
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // 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> background_; // Objeto para dibujar el fondo del juego
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
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::vector<std::unique_ptr<PathSprite>> path_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::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::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
std::vector<Path> 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> &player);
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(std::shared_ptr<Player> &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> texture);
// Crea un objeto PathSprite
void createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture> 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> &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> &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<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.
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);
// 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();
};