#pragma once #include #include // Para SDL_FRect #include // Para Uint32 #include // Para unique_ptr, shared_ptr #include // Para string #include // Para vector #include "animated_sprite.h" // Para AnimatedSprite #include "enter_name.h" // Para EnterName #include "manage_hiscore_table.h" // Para HiScoreEntry #include "options.h" // Para Options, OptionsGame, options #include "utils.h" // Para Circle class Texture; // lines 13-13 enum class InputAction : int; // lines 14-14 enum class ScoreboardMode; // lines 15-15 // Estados del jugador enum class PlayerState { WALKING_LEFT, WALKING_RIGHT, WALKING_STOP, FIRING_UP, FIRING_LEFT, FIRING_RIGHT, FIRING_NONE, COOLING_UP, COOLING_LEFT, COOLING_RIGHT, PLAYING, // Está jugando CONTINUE, // Está con la cuenta atras para continuar WAITING, // No está jugando pero puede entrar a jugar ENTERING_NAME, // Introduciendo nombre SHOWING_NAME, // Mostrando el nombre introducido DYING, // El cadaver está volando por ahi DIED, // El cadaver ha desaparecido por el fondo GAME_OVER, // No está jugando y no puede entrar a jugar CELEBRATING, // Poniendo pose de victoria ENTERING_NAME_GAME_COMPLETED, // Poniendo nombre en el tramo final del juego LEAVING_SCREEN, // Moviendose fuera de la pantalla ENTERING_SCREEN, // Entando a la pantalla CREDITS, // Estado para los creditos del juego }; // Clase Player class Player { private: // Constantes static constexpr int POWERUP_COUNTER_ = 1500; // Duración del estado PowerUp static constexpr int INVULNERABLE_COUNTER_ = 200; // Duración del estado invulnerable static constexpr int WIDTH_ = 30; // Anchura static constexpr int HEIGHT_ = 30; // Altura static constexpr float BASE_SPEED_ = 1.5f; // Velocidad base del jugador // Objetos y punteros std::unique_ptr player_sprite_; // Sprite para dibujar el jugador std::unique_ptr power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope std::unique_ptr enter_name_; // Clase utilizada para introducir el nombre // Variables int id_; // Numero de identificación para el jugador. Player1 = 1, Player2 = 2 SDL_FRect play_area_; // Rectangulo con la zona de juego float pos_x_ = 0.0f; // Posicion en el eje X int pos_y_ = 0; // Posicion en el eje Y float default_pos_x_; // Posición inicial para el jugador int default_pos_y_; // Posición inicial para el jugador float vel_x_ = 0.0f; // Cantidad de pixeles a desplazarse en el eje X int vel_y_ = 0.0f; // Cantidad de pixeles a desplazarse en el eje Y int cool_down_ = 0; // Contador durante el cual no puede disparar int cooling_state_counter_ = 0; // Contador para la animación del estado cooling int score_ = 0; // Puntos del jugador float score_multiplier_ = 1.0f; // Multiplicador de puntos PlayerState walking_state_ = PlayerState::WALKING_STOP; // Estado del jugador al moverse PlayerState firing_state_ = PlayerState::FIRING_NONE; // Estado del jugador al disparar PlayerState playing_state_ = PlayerState::WAITING; // Estado del jugador en el juego bool invulnerable_ = true; // Indica si el jugador es invulnerable int invulnerable_counter_ = INVULNERABLE_COUNTER_; // Contador para la invulnerabilidad bool extra_hit_ = false; // Indica si el jugador tiene un toque extra int coffees_ = 0; // Indica cuantos cafes lleva acumulados bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp int power_up_counter_ = POWERUP_COUNTER_; // Temporizador para el modo PowerUp int power_up_desp_x_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador Circle collider_ = Circle(0, 0, 9); // Circulo de colisión del jugador int continue_counter_ = 10; // Contador para poder continuar Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo int scoreboard_panel_ = 0; // Panel del marcador asociado al jugador std::string name_; // Nombre del jugador int controller_index_ = 0; // Indice del array de mandos que utilizará para moverse bool demo_; // Para que el jugador sepa si está en el modo demostración int enter_name_counter_; // Contador para poner nombre Uint32 enter_name_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente bool game_completed_ = false; // Indica si ha completado el juego int credits_used_ = 1; // Indica el numero de veces que ha continuado std::string last_enter_name_; // Ultimo nombre introducido en la tabla de puntuaciones // Actualiza el circulo de colisión a la posición del jugador void shiftColliders(); // Recoloca el sprite void shiftSprite(); // Monitoriza el estado void updateInvulnerable(); // Actualiza el contador de continue void updateContinueCounter(); // Actualiza el contador de entrar nombre void updateEnterNameCounter(); // Actualiza el estado de SHOWING_NAME void updateShowingName(); // Decrementa el contador de entrar nombre void decEnterNameCounter(); // Actualiza el panel del marcador void updateScoreboard(); // Cambia el modo del marcador void setScoreboardMode(ScoreboardMode mode); // Hace sonar un ruido al azar void playRandomBubbleSound(); // Getters bool isRenderable() const { return !isWaiting() && !isGameOver(); } public: // Constructor Player(int id, float x, int y, bool demo, SDL_FRect &play_area, std::vector> texture, const std::vector> &animations); // Destructor ~Player() = default; // Iniciador void init(); // Actualiza al jugador a su posicion, animación y controla los contadores void update(); // Pinta el jugador en pantalla void render(); // Pone las texturas del jugador void setPlayerTextures(const std::vector> &texture); // Actua en consecuencia de la entrada recibida void setInput(InputAction input); // Procesa inputs para cuando está jugando void setInputPlaying(InputAction input); // Procesa inputs para cuando está introduciendo el nombre void setInputEnteringName(InputAction input); // Mueve el jugador a la posición y animación que le corresponde void move(); // Establece la animación correspondiente al estado void setAnimation(); // Actualiza el valor de la variable void updateCooldown(); // Incrementa la puntuación del jugador void addScore(int score); // Establece el estado del jugador en el juego void setPlayingState(PlayerState state); // Aumenta el valor de la variable hasta un máximo void incScoreMultiplier(); // Decrementa el valor de la variable hasta un mínimo void decScoreMultiplier(); // Establece el valor del estado void setInvulnerable(bool value); // Establece el valor de la variable a verdadero void setPowerUp(); // Actualiza el valor de la variable void updatePowerUp(); // Concede un toque extra al jugador void giveExtraHit(); // Quita el toque extra al jugador void removeExtraHit(); // Decrementa el contador de continuar void decContinueCounter(); // Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones int getRecordNamePos() const; // Comprobación de playing_state bool hasDied() const { return playing_state_ == PlayerState::DIED; } bool isCelebrating() const { return playing_state_ == PlayerState::CELEBRATING; } bool isContinue() const { return playing_state_ == PlayerState::CONTINUE; } bool isDying() const { return playing_state_ == PlayerState::DYING; } bool isEnteringName() const { return playing_state_ == PlayerState::ENTERING_NAME; } bool isShowingName() const { return playing_state_ == PlayerState::SHOWING_NAME; } bool isEnteringNameGameCompleted() const { return playing_state_ == PlayerState::ENTERING_NAME_GAME_COMPLETED; } bool isLeavingScreen() const { return playing_state_ == PlayerState::LEAVING_SCREEN; } bool isGameOver() const { return playing_state_ == PlayerState::GAME_OVER; } bool isPlaying() const { return playing_state_ == PlayerState::PLAYING; } bool isWaiting() const { return playing_state_ == PlayerState::WAITING; } // Getters bool canFire() const { return cool_down_ > 0 ? false : true; } bool hasExtraHit() const { return extra_hit_; } bool isCooling() const { return firing_state_ == PlayerState::COOLING_LEFT || firing_state_ == PlayerState::COOLING_UP || firing_state_ == PlayerState::COOLING_RIGHT; } bool IsEligibleForHighScore() const { return score_ > options.game.hi_score_table.back().score; } bool isInvulnerable() const { return invulnerable_; } bool isPowerUp() const { return power_up_; } Circle &getCollider() { return collider_; } float getScoreMultiplier() const { return score_multiplier_; } int getCoffees() const { return coffees_; } int getContinueCounter() const { return continue_counter_; } int getController() const { return controller_index_; } int getHeight() const { return HEIGHT_; } int getId() const { return id_; } int getInvulnerableCounter() const { return invulnerable_counter_; } int getPosX() const { return static_cast(pos_x_); } int getPosY() const { return pos_y_; } int getPowerUpCounter() const { return power_up_counter_; } std::string getRecordName() const { return enter_name_->getFinalName(); } int getScore() const { return score_; } int getScoreBoardPanel() const { return scoreboard_panel_; } int getWidth() const { return WIDTH_; } PlayerState getPlayingState() const { return playing_state_; } const std::string &getName() const { return name_; } bool get1CC() const { return game_completed_ && credits_used_ == 1; } bool getEnterNamePositionOverflow() const { return enter_name_->getPositionOverflow(); } // Setters void setController(int index) { controller_index_ = index; } void setFireCooldown(int time) { cool_down_ = time; } void setFiringState(PlayerState state) { firing_state_ = state; } void setInvulnerableCounter(int value) { invulnerable_counter_ = value; } void setName(const std::string &name) { name_ = name; } void setPowerUpCounter(int value) { power_up_counter_ = value; } void setScore(int score) { score_ = score; } void setScoreBoardPanel(int panel) { scoreboard_panel_ = panel; } void setScoreMultiplier(float value) { score_multiplier_ = value; } void setWalkingState(PlayerState state) { walking_state_ = state; } void addCredit() { ++credits_used_; } };