diff --git a/source/player.cpp b/source/player.cpp index c534875..42d6260 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -33,8 +33,6 @@ Player::Player(int id, float x, int y, bool demo, SDL_FRect &play_area, std::vec // Inicializa variables pos_x_ = default_pos_x_; - invulnerable_ = false; - invulnerable_counter_ = 0; init(); } @@ -44,6 +42,8 @@ void Player::init() { pos_y_ = default_pos_y_; walking_state_ = State::WALKING_STOP; firing_state_ = State::FIRING_NONE; + invulnerable_ = false; + invulnerable_counter_ = 0; power_up_ = false; power_up_counter_ = POWERUP_COUNTER; extra_hit_ = false; @@ -66,7 +66,7 @@ void Player::init() { shiftSprite(); // Selecciona un frame para pintar - player_sprite_->setCurrentAnimation("stand"); + //player_sprite_->setCurrentAnimation("stand"); } // Actua en consecuencia de la entrada recibida @@ -209,6 +209,8 @@ void Player::handleRollingGroundCollision() { return; } + // const float VEL_Y = player_sprite_->getVelY(); + // if (VEL_Y >= 0.0F && VEL_Y < 2.0F) { if (player_sprite_->getVelY() < 2.0F) { handleRollingStop(); } else { @@ -218,7 +220,6 @@ void Player::handleRollingGroundCollision() { void Player::handleRollingStop() { const auto NEXT_PLAYER_STATUS = isEligibleForHighScore() ? State::ENTERING_NAME : State::CONTINUE; - const auto NEXT_STATE = demo_ ? State::LYING_ON_THE_FLOOR_FOREVER : NEXT_PLAYER_STATUS; setPlayingState(NEXT_STATE); @@ -291,7 +292,7 @@ void Player::handlePlayer1Entering() { pos_x_ += vel_x_; if (pos_x_ > default_pos_x_) { pos_x_ = default_pos_x_; - setPlayingState(State::RESPAWNING); + setPlayingState(State::PLAYING); } } @@ -300,7 +301,7 @@ void Player::handlePlayer2Entering() { pos_x_ += vel_x_; if (pos_x_ < default_pos_x_) { pos_x_ = default_pos_x_; - setPlayingState(State::RESPAWNING); + setPlayingState(State::PLAYING); } } @@ -588,14 +589,14 @@ void Player::setPlayingState(State state) { switch (playing_state_) { case State::RESPAWNING: { - setInvulnerable(true); - addCredit(); playSound("voice_thankyou.wav"); setPlayingState(State::PLAYING); + setInvulnerable(true); + break; } case State::PLAYING: { init(); - playing_state_ = State::PLAYING; + setInvulnerable(true); setScoreboardMode(Scoreboard::Mode::SCORE); Stage::power_can_be_added = true; break; @@ -604,8 +605,8 @@ void Player::setPlayingState(State state) { // Inicializa el contador de continuar continue_ticks_ = SDL_GetTicks(); continue_counter_ = 9; - setScoreboardMode(Scoreboard::Mode::CONTINUE); playSound("continue_clock.wav"); + setScoreboardMode(Scoreboard::Mode::CONTINUE); break; } case State::WAITING: { @@ -640,11 +641,12 @@ void Player::setPlayingState(State state) { break; } case State::ROLLING: { - // Activa la animación de rodar + // Activa la animación de rodar dando botes player_sprite_->setCurrentAnimation("rolling"); player_sprite_->setAnimationSpeed(4); - player_sprite_->setAccelY(0.2F); - player_sprite_->setVelY(-6.6F); + player_sprite_->setVelY(-6.6F); // Velocidad inicial + player_sprite_->setAccelY(0.2F); // Gravedad + player_sprite_->setPosY(pos_y_ - 2); // Para "sacarlo" del suelo, ya que está hundido un pixel para ocultar el outline de los pies (rand() % 2 == 0) ? player_sprite_->setVelX(3.3F) : player_sprite_->setVelX(-3.3F); break; } @@ -660,7 +662,7 @@ void Player::setPlayingState(State state) { break; } case State::CONTINUE_TIME_OUT: { - // Activa la animación de morir + // Activa la animación de sacar al jugador de la zona de juego player_sprite_->setAccelY(0.2F); player_sprite_->setVelY(-4.0F); player_sprite_->setVelX(0.0F); @@ -692,6 +694,7 @@ void Player::setPlayingState(State state) { break; } case State::ENTERING_SCREEN: { + init(); step_counter_ = 0; setScoreboardMode(Scoreboard::Mode::SCORE); switch (id_) { diff --git a/source/player.h b/source/player.h index 2bd00bb..18b44fb 100644 --- a/source/player.h +++ b/source/player.h @@ -20,6 +20,10 @@ enum class Mode; // --- Clase Player --- class Player { public: + // --- Constantes --- + static constexpr int WIDTH = 32; // Anchura + static constexpr int HEIGHT = 32; // Altura + // --- Estados posibles del jugador --- enum class State { // Estados de movimiento @@ -50,7 +54,7 @@ class Player { WAITING, // Esperando para entrar a jugar ENTERING_NAME, // Introduciendo nombre para la tabla de puntuaciones SHOWING_NAME, // Mostrando el nombre introducido - ROLLING, // El jugador está muriendo (animación de muerte) + ROLLING, // El jugador está dando vueltas y rebotando LYING_ON_THE_FLOOR_FOREVER, // El jugador está inconsciente para siempre en el suelo (demo) GAME_OVER, // Fin de la partida, no puede jugar CELEBRATING, // Celebrando victoria (pose de victoria) @@ -164,8 +168,6 @@ class Player { // --- 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 = 32; // Anchura - static constexpr int HEIGHT = 32; // Altura static constexpr float BASE_SPEED = 1.5F; // Velocidad base del jugador static constexpr int COOLING_DURATION = 50; static constexpr int COOLING_COMPLETE = 0; @@ -214,7 +216,7 @@ class Player { 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 número de veces que ha continuado + int credits_used_ = 0; // Indica el número de veces que ha continuado std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones int waiting_counter_ = 0; // Contador para el estado de espera diff --git a/source/sections/game.cpp b/source/sections/game.cpp index dc13cc4..285f561 100644 --- a/source/sections/game.cpp +++ b/source/sections/game.cpp @@ -1348,18 +1348,17 @@ void Game::handleFireInput(const std::shared_ptr &player, BulletType bul } } -// Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo). +// Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo) void Game::handlePlayersInput() { for (const auto &player : players_) { if (player->isPlaying()) { - // Maneja el input de los jugadores en modo normal. - handleNormalPlayerInput(player); - } else if (player->isContinue() || player->isWaiting()) { - // Gestiona la continuación del jugador. - handlePlayerContinue(player); + handleNormalPlayerInput(player); // Maneja el input de los jugadores en modo normal + } else if (player->isContinue()) { + handlePlayerContinueInput(player); // Gestiona la continuación del jugador + } else if (player->isWaiting()) { + handlePlayerWaitingInput(player); // Gestiona la (re)entrada del jugador } else if (player->isEnteringName() || player->isEnteringNameGameCompleted() || player->isShowingName()) { - // Gestiona la introducción del nombre del jugador. - handleNameInput(player); + handleNameInput(player); // Gestiona la introducción del nombre del jugador } } } @@ -1367,7 +1366,6 @@ void Game::handlePlayersInput() { // Maneja las entradas de movimiento y disparo para un jugador en modo normal. void Game::handleNormalPlayerInput(const std::shared_ptr &player) { const auto &controller = Options::controllers.at(player->getController()); - const bool AUTOFIRE = player->isPowerUp() || Options::settings.autofire; if (input_->checkInput(InputAction::LEFT, INPUT_ALLOW_REPEAT, controller.type, controller.index)) { player->setInput(InputAction::LEFT); @@ -1386,22 +1384,24 @@ void Game::handleNormalPlayerInput(const std::shared_ptr &player) { #endif } + const bool AUTOFIRE = player->isPowerUp() || Options::settings.autofire; handleFireInputs(player, AUTOFIRE, player->getController()); // Verifica y maneja todas las posibles entradas de disparo. } // Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado. void Game::handleFireInputs(const std::shared_ptr &player, bool autofire, int controller_index) { - if (input_->checkInput(InputAction::FIRE_CENTER, autofire, Options::controllers[controller_index].type, Options::controllers[controller_index].index)) { + const auto CONTROLLER = Options::controllers.at(player->getController()); + if (input_->checkInput(InputAction::FIRE_CENTER, autofire, CONTROLLER.type, CONTROLLER.index)) { handleFireInput(player, BulletType::UP); #ifdef RECORDING demo_.keys.fire = 1; #endif - } else if (input_->checkInput(InputAction::FIRE_LEFT, autofire, Options::controllers[controller_index].type, Options::controllers[controller_index].index)) { + } else if (input_->checkInput(InputAction::FIRE_LEFT, autofire, CONTROLLER.type, CONTROLLER.index)) { handleFireInput(player, BulletType::LEFT); #ifdef RECORDING demo_.keys.fire_left = 1; #endif - } else if (input_->checkInput(InputAction::FIRE_RIGHT, autofire, Options::controllers[controller_index].type, Options::controllers[controller_index].index)) { + } else if (input_->checkInput(InputAction::FIRE_RIGHT, autofire, CONTROLLER.type, CONTROLLER.index)) { handleFireInput(player, BulletType::RIGHT); #ifdef RECORDING demo_.keys.fire_right = 1; @@ -1410,31 +1410,38 @@ void Game::handleFireInputs(const std::shared_ptr &player, bool autofire } // Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio. -void Game::handlePlayerContinue(const std::shared_ptr &player) { - const auto CONTROLLER_INDEX = player->getController(); - if (input_->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index)) { - if (player->isContinue()) { - player->setPlayingState(Player::State::RESPAWNING); - } else if (player->isWaiting()) { - player->setPlayingState(Player::State::ENTERING_SCREEN); - } +void Game::handlePlayerContinueInput(const std::shared_ptr &player) { + const auto CONTROLLER = Options::controllers.at(player->getController()); + if (input_->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { + player->setPlayingState(Player::State::RESPAWNING); + player->addCredit(); sendPlayerToTheFront(player); } // Disminuye el contador de continuación si se presiona cualquier botón de disparo. - if (input_->checkInput(InputAction::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index) || - input_->checkInput(InputAction::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index) || - input_->checkInput(InputAction::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index)) { + if (input_->checkInput(InputAction::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index) || + input_->checkInput(InputAction::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index) || + input_->checkInput(InputAction::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { if (player->getContinueCounter() < param.scoreboard.skip_countdown_value) { player->decContinueCounter(); } } } +// Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio. +void Game::handlePlayerWaitingInput(const std::shared_ptr &player) { + const auto CONTROLLER = Options::controllers.at(player->getController()); + if (input_->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { + player->setPlayingState(Player::State::ENTERING_SCREEN); + player->addCredit(); + sendPlayerToTheFront(player); + } +} + // Procesa las entradas para la introducción del nombre del jugador. void Game::handleNameInput(const std::shared_ptr &player) { - const auto CONTROLLER_INDEX = player->getController(); - if (input_->checkInput(InputAction::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index)) { + const auto CONTROLLER = Options::controllers.at(player->getController()); + if (input_->checkInput(InputAction::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { if (player->isShowingName()) { player->setPlayingState(Player::State::CONTINUE); } else if (player->getEnterNamePositionOverflow()) { @@ -1444,18 +1451,18 @@ void Game::handleNameInput(const std::shared_ptr &player) { } else { player->setInput(InputAction::RIGHT); } - } else if (input_->checkInput(InputAction::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index) || - input_->checkInput(InputAction::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index)) { + } else if (input_->checkInput(InputAction::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index) || + input_->checkInput(InputAction::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { if (player->isShowingName()) { player->setPlayingState(Player::State::CONTINUE); } else { player->setInput(InputAction::LEFT); } - } else if (input_->checkInput(InputAction::UP, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index)) { + } else if (input_->checkInput(InputAction::UP, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { player->setInput(InputAction::UP); - } else if (input_->checkInput(InputAction::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index)) { + } else if (input_->checkInput(InputAction::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { player->setInput(InputAction::DOWN); - } else if (input_->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, Options::controllers[CONTROLLER_INDEX].type, Options::controllers[CONTROLLER_INDEX].index)) { + } else if (input_->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) { if (player->isShowingName()) { player->setPlayingState(Player::State::CONTINUE); } else { @@ -1580,19 +1587,17 @@ void Game::initDifficultyVars() { // Inicializa los jugadores void Game::initPlayers(int player_id) { - constexpr int PLAYER_HEIGHT = 32; - constexpr int PLAYER_WIDTH = 32; - const int Y = param.game.play_area.rect.h - PLAYER_HEIGHT + 1; + const int Y = param.game.play_area.rect.h - Player::HEIGHT + 1; // Se hunde un pixel para esconder el outline de los pies // Crea al jugador uno y lo pone en modo espera - players_.emplace_back(std::make_unique(1, param.game.play_area.first_quarter_x - (PLAYER_WIDTH / 2), Y, demo_.enabled, param.game.play_area.rect, player_textures_[0], player_animations_)); + players_.emplace_back(std::make_unique(1, param.game.play_area.first_quarter_x - (Player::WIDTH / 2), Y, demo_.enabled, param.game.play_area.rect, player_textures_.at(0), player_animations_)); players_.back()->setScoreBoardPanel(Scoreboard::Id::LEFT); players_.back()->setName(Lang::getText("[SCOREBOARD] 1")); players_.back()->setController(getController(players_.back()->getId())); players_.back()->setPlayingState(Player::State::WAITING); // Crea al jugador dos y lo pone en modo espera - players_.emplace_back(std::make_unique(2, param.game.play_area.third_quarter_x - (PLAYER_WIDTH / 2), Y, demo_.enabled, param.game.play_area.rect, player_textures_[1], player_animations_)); + players_.emplace_back(std::make_unique(2, param.game.play_area.third_quarter_x - (Player::WIDTH / 2), Y, demo_.enabled, param.game.play_area.rect, player_textures_.at(1), player_animations_)); players_.back()->setScoreBoardPanel(Scoreboard::Id::RIGHT); players_.back()->setName(Lang::getText("[SCOREBOARD] 2")); players_.back()->setController(getController(players_.back()->getId())); diff --git a/source/sections/game.h b/source/sections/game.h index 8cdd6ef..f8ebb5f 100644 --- a/source/sections/game.h +++ b/source/sections/game.h @@ -202,7 +202,8 @@ class Game { void handleNormalPlayerInput(const std::shared_ptr &player); // Procesa entrada de un jugador específico void handleFireInput(const std::shared_ptr &player, BulletType bullet_type); // Gestiona disparo de jugador void handleFireInputs(const std::shared_ptr &player, bool autofire, int controller_index); // Procesa disparos automáticos - void handlePlayerContinue(const std::shared_ptr &player); // Permite continuar al jugador + void handlePlayerContinueInput(const std::shared_ptr &player); // Permite continuar al jugador + void handlePlayerWaitingInput(const std::shared_ptr &player); // Permite (re)entrar al jugador void handleNameInput(const std::shared_ptr &player); // Gestiona entrada de nombre del jugador // --- Entrada en modo demo --- @@ -294,8 +295,8 @@ class Game { // --- Utilidades y servicios --- void checkServiceMenu(); // Verifica si el menú de servicio está activo - void renderHit(); // Dibuja el golpe que recibe el jugador al impactarle un globo - void putHitOnScreen(SDL_FPoint position); // Coloca el Hit en pantalla obligando a hacer un renderizado + void renderHit(); // Dibuja el golpe que recibe el jugador al impactarle un globo + void putHitOnScreen(SDL_FPoint position); // Coloca el Hit en pantalla obligando a hacer un renderizado void sendPlayerToTheBack(const std::shared_ptr &player); // Mueve el jugador para pintarlo al fondo de la lista de jugadores void sendPlayerToTheFront(const std::shared_ptr &player); // Mueve el jugador para pintarlo el primero de la lista de jugadores