diff --git a/source/game/defaults.hpp b/source/game/defaults.hpp index 05160fd..ce70aa0 100644 --- a/source/game/defaults.hpp +++ b/source/game/defaults.hpp @@ -46,7 +46,7 @@ constexpr int BORDER_HEIGHT = 24; // Alto del borde por defecto // AUDIO // ============================================================================= constexpr int AUDIO_VOLUME = 100; // Volumen por defecto -constexpr bool AUDIO_ENABLED = true; // Audio por defecto +constexpr bool AUDIO_ENABLED = false; // Audio por defecto // MUSIC constexpr int MUSIC_VOLUME = 80; // Volumen por defecto de la musica diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index 1cbcbff..9cc41b1 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -3,12 +3,12 @@ #include // Para max, min #include // Para ceil, abs -#include // Para std::ranges::any_of +#include +#include // Para std::ranges::any_of #include "core/input/input.hpp" // Para Input, InputAction #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/resources/resource.hpp" // Para Resource -#include "core/system/debug.hpp" // Para Debug #include "external/jail_audio.h" // Para JA_PlaySound #include "game/gameplay/room.hpp" // Para Room, TileType #include "game/options.hpp" // Para Cheat, Options, options @@ -18,52 +18,37 @@ Player::Player(const Data& player) : room_(player.room) { // Inicializa algunas variables - initSprite(/*player.texture_path, */player.animations_path); + initSprite(player.animations_path); setColor(); applySpawnValues(player.spawn_data); placeSprite(); initSounds(); previous_state_ = state_; - last_position_ = getRect(); - collider_box_ = getRect(); - collider_points_.resize(collider_points_.size() + 8, {0, 0}); - under_feet_.resize(under_feet_.size() + 2, {0, 0}); - feet_.resize(feet_.size() + 2, {0, 0}); - -#ifdef _DEBUG - debug_rect_x_ = {.x = 0, .y = 0, .w = 0, .h = 0}; - debug_rect_y_ = {.x = 0, .y = 0, .w = 0, .h = 0}; - debug_color_ = static_cast(PaletteColor::GREEN); - debug_point_ = {.x = 0, .y = 0}; -#endif } // Pinta el jugador en pantalla void Player::render() { sprite_->render(1, color_); - -#ifdef _DEBUG - renderDebugInfo(); -#endif } // Actualiza las variables del objeto void Player::update(float delta_time) { if (!is_paused_) { - checkInput(delta_time); // Comprueba las entradas y modifica variables - move(delta_time); // Recalcula la posición del jugador - animate(delta_time); // Establece la animación del jugador - checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación - checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio - checkKillingTiles(); // Comprueba que el jugador no toque ningun tile de los que matan} + checkInput(); // Comprueba las entradas y establece las velocidades y el flip + move(delta_time); // Recalcula la posición del jugador + animate(delta_time); // Establece la animación del jugador + updateState(delta_time); // Comprueba el estado del jugador + checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación + checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio + checkKillingTiles(); // Comprueba que el jugador no toque ningun tile de los que matan} + + setColor(); } } -// Comprueba las entradas y modifica variables -void Player::checkInput(float delta_time) { - (void)delta_time; // No usado en este método, pero mantenido para consistencia - +// Comprueba las entradas y establece las velocidades y el flip +void Player::checkInput() { // Solo comprueba las entradas de dirección cuando está sobre una superficie if (state_ != State::STANDING) { return; @@ -74,42 +59,36 @@ void Player::checkInput(float delta_time) { if (Input::get()->checkInput(InputAction::LEFT)) { vx_ = -HORIZONTAL_VELOCITY; sprite_->setFlip(SDL_FLIP_HORIZONTAL); + left_or_right_is_pressed_ = true; } else if (Input::get()->checkInput(InputAction::RIGHT)) { vx_ = HORIZONTAL_VELOCITY; sprite_->setFlip(SDL_FLIP_NONE); + left_or_right_is_pressed_ = true; } else { // No se pulsa ninguna dirección vx_ = 0.0F; - if (isOnAutoSurface()) { - // Si deja de moverse sobre una superficie se engancha - auto_movement_ = true; - } + left_or_right_is_pressed_ = false; } - } else { // El movimiento lo proporciona la superficie + } else { + // El movimiento lo proporciona la superficie vx_ = HORIZONTAL_VELOCITY * room_->getAutoSurfaceDirection(); - - if (vx_ > 0.0F) { - sprite_->setFlip(SDL_FLIP_NONE); - } else { - sprite_->setFlip(SDL_FLIP_HORIZONTAL); - } + sprite_->setFlip(vx_ > 0.0F ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL); } if (Input::get()->checkInput(InputAction::JUMP)) { - // Solo puede saltar si ademas de estar (state == s_standing) - // Esta sobre el suelo, rampa o suelo que se mueve - // Esto es para evitar el salto desde el vacio al cambiar de pantalla verticalmente - // Ya que se coloca el estado s_standing al cambiar de pantalla + /* + Solo puede saltar si ademas de estar (State::STANDING) + Esta sobre el suelo, rampa o suelo que se mueve + Esto es para evitar el salto desde el vacio al cambiar de pantalla verticalmente + Ya que se coloca el estado State::STANDING al cambiar de pantalla + */ if (isOnFloor() || isOnAutoSurface()) { setState(State::JUMPING); - vy_ = JUMP_VELOCITY; - jump_init_pos_ = y_; - jumping_time_ = 0.0F; } } } @@ -142,37 +121,42 @@ void Player::checkBorders() { } // Comprueba el estado del jugador -void Player::checkState(float delta_time) { +void Player::updateState(float delta_time) { // Actualiza las variables en función del estado - if (state_ == State::FALLING) { - vx_ = 0.0F; - vy_ = MAX_VY; - falling_time_ += delta_time; - playFallSound(); - } - - else if (state_ == State::STANDING) { - // Calcula la distancia de caída en pixels (velocidad * tiempo) - const float FALLING_DISTANCE = MAX_VY * falling_time_; - if (previous_state_ == State::FALLING && FALLING_DISTANCE > MAX_FALLING_HEIGHT) { // Si cae de muy alto, el jugador muere - is_alive_ = false; + switch (state_) { + case State::STANDING: { + // Calcula la distancia de caída en pixels (velocidad * tiempo) + const int FALLING_DISTANCE = static_cast(y_) - last_grounded_position_; + if (previous_state_ == State::FALLING && FALLING_DISTANCE > MAX_FALLING_HEIGHT) { + // Si cae de muy alto, el jugador muere + is_alive_ = false; + } + vy_ = 0.0F; + jumping_time_ = 0.0F; + last_grounded_position_ = static_cast(y_); + auto_movement_ = !isOnFloor() && isOnAutoSurface(); + if (!isOnFloor() && !isOnAutoSurface() && !isOnDownSlope()) { + setState(State::FALLING); + } + break; } - vy_ = 0.0F; - jumping_time_ = 0.0F; - falling_time_ = 0.0F; - if (!isOnFloor() && !isOnAutoSurface() && !isOnDownSlope()) { - setState(State::FALLING); + + case State::FALLING: { vx_ = 0.0F; vy_ = MAX_VY; - falling_time_ += delta_time; playFallSound(); + break; } - } - else if (state_ == State::JUMPING) { - falling_time_ = 0.0F; - jumping_time_ += delta_time; - playJumpSound(); + case State::JUMPING: { + last_grounded_position_ = static_cast(y_); + jumping_time_ += delta_time; + playJumpSound(); + break; + } + + default: + break; } } @@ -203,7 +187,6 @@ void Player::switchBorders() { is_on_border_ = false; placeSprite(); - collider_box_ = getRect(); } // Aplica gravedad al jugador @@ -220,15 +203,11 @@ void Player::applyGravity(float delta_time) { void Player::moveHorizontalLeft(float delta_time) { // Crea el rectangulo de proyección en el eje X para ver si colisiona const float DISPLACEMENT = vx_ * delta_time; - SDL_FRect proj; - proj.x = static_cast(x_ + DISPLACEMENT); - proj.y = static_cast(y_); - proj.h = HEIGHT; - proj.w = static_cast(std::ceil(std::fabs(DISPLACEMENT))); // Para evitar que tenga un ancho de 0 pixels - -#ifdef _DEBUG - debug_rect_x_ = proj; -#endif + SDL_FRect proj = { + .x = x_ + DISPLACEMENT, + .y = y_, + .w = std::ceil(std::fabs(DISPLACEMENT)), // Para evitar que tenga un ancho de 0 pixels + .h = HEIGHT}; // Comprueba la colisión con las superficies const int POS = room_->checkRightSurfaces(&proj); @@ -240,20 +219,25 @@ void Player::moveHorizontalLeft(float delta_time) { } else { // Si hay colisión lo mueve hasta donde no colisiona x_ = POS + 1; + std::cout << "LEFT\n"; } - // Si ha tocado alguna rampa mientras camina (sin saltar), asciende - if (state_ != State::JUMPING) { - const LineVertical LEFT_SIDE = {.x = static_cast(x_), .y1 = static_cast(y_) + static_cast(HEIGHT) - 2, .y2 = static_cast(y_) + static_cast(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo - const int LY = room_->checkLeftSlopes(&LEFT_SIDE); - if (LY > -1) { - y_ = LY - HEIGHT; + // Si ha tocado alguna rampa mientras camina (sin saltar) + if (state_ == State::STANDING) { + // Si está bajando la rampa, recoloca al jugador + if (isOnDownSlope() && state_ == State::STANDING) { + y_ += 1; + std::cout << "RAMP DOWN LEFT\n"; + } + // Asciende + else { + const LineVertical LEFT_SIDE = {.x = static_cast(x_), .y1 = static_cast(y_) + static_cast(HEIGHT) - 2, .y2 = static_cast(y_) + static_cast(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo + const int LY = room_->checkLeftSlopes(&LEFT_SIDE); + if (LY > -1) { + y_ = LY - HEIGHT; + std::cout << "RAMP UP LEFT\n"; + } } - } - - // Si está bajando la rampa, recoloca al jugador - if (isOnDownSlope() && state_ != State::JUMPING) { - y_ += 1; } } @@ -261,15 +245,11 @@ void Player::moveHorizontalLeft(float delta_time) { void Player::moveHorizontalRight(float delta_time) { // Crea el rectangulo de proyección en el eje X para ver si colisiona const float DISPLACEMENT = vx_ * delta_time; - SDL_FRect proj; - proj.x = x_ + WIDTH; - proj.y = y_; - proj.h = HEIGHT; - proj.w = std::ceil(DISPLACEMENT); // Para evitar que tenga un ancho de 0 pixels - -#ifdef _DEBUG - debug_rect_x_ = proj; -#endif + SDL_FRect proj = { + .x = x_ + WIDTH, + .y = y_, + .w = std::ceil(DISPLACEMENT), // Para evitar que tenga un ancho de 0 pixels + .h = HEIGHT}; // Comprueba la colisión const int POS = room_->checkLeftSurfaces(&proj); @@ -281,20 +261,25 @@ void Player::moveHorizontalRight(float delta_time) { } else { // Si hay colisión lo mueve hasta donde no colisiona x_ = POS - WIDTH; + std::cout << "RIGHT\n"; } - // Si ha tocado alguna rampa mientras camina (sin saltar), asciende - if (state_ != State::JUMPING) { - const LineVertical RIGHT_SIDE = {.x = static_cast(x_) + static_cast(WIDTH) - 1, .y1 = static_cast(y_) + static_cast(HEIGHT) - 2, .y2 = static_cast(y_) + static_cast(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo - const int RY = room_->checkRightSlopes(&RIGHT_SIDE); - if (RY > -1) { - y_ = RY - HEIGHT; + // Si ha tocado alguna rampa mientras camina (sin saltar) + if (state_ == State::STANDING) { + // Si está bajando la rampa, recoloca al jugador + if (isOnDownSlope() && state_ == State::STANDING) { + y_ += 1; + std::cout << "RAMP DOWN RIGHT\n"; + } + // Asciende + else { + const LineVertical RIGHT_SIDE = {.x = static_cast(x_) + static_cast(WIDTH) - 1, .y1 = static_cast(y_) + static_cast(HEIGHT) - 2, .y2 = static_cast(y_) + static_cast(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo + const int RY = room_->checkRightSlopes(&RIGHT_SIDE); + if (RY > -1) { + y_ = RY - HEIGHT; + std::cout << "RAMP UP RIGHT\n"; + } } - } - - // Si está bajando la rampa, recoloca al jugador - if (isOnDownSlope() && state_ != State::JUMPING) { - y_ += 1; } } @@ -302,15 +287,12 @@ void Player::moveHorizontalRight(float delta_time) { void Player::moveVerticalUp(float delta_time) { // Crea el rectangulo de proyección en el eje Y para ver si colisiona const float DISPLACEMENT = vy_ * delta_time; - SDL_FRect proj; - proj.x = static_cast(x_); - proj.y = static_cast(y_ + DISPLACEMENT); - proj.h = static_cast(std::ceil(std::fabs(DISPLACEMENT))); // Para evitar que tenga una altura de 0 pixels - proj.w = WIDTH; - -#ifdef _DEBUG - debug_rect_y_ = proj; -#endif + SDL_FRect proj = { + .x = x_, + .y = y_ + DISPLACEMENT, + .w = WIDTH, + .h = std::ceil(std::fabs(DISPLACEMENT)) // Para evitar que tenga una altura de 0 pixels + }; // Comprueba la colisión const int POS = room_->checkBottomSurfaces(&proj); @@ -322,6 +304,7 @@ void Player::moveVerticalUp(float delta_time) { } else { // Si hay colisión lo mueve hasta donde no colisiona y entra en caída y_ = POS + 1; + std::cout << "TOP\n"; setState(State::FALLING); } } @@ -330,48 +313,39 @@ void Player::moveVerticalUp(float delta_time) { void Player::moveVerticalDown(float delta_time) { // Crea el rectangulo de proyección en el eje Y para ver si colisiona const float DISPLACEMENT = vy_ * delta_time; - SDL_FRect proj; - proj.x = x_; - proj.y = y_ + HEIGHT; - proj.h = std::ceil(DISPLACEMENT); // Para evitar que tenga una altura de 0 pixels - proj.w = WIDTH; - -#ifdef _DEBUG - debug_rect_y_ = proj; -#endif + SDL_FRect proj = { + .x = x_, + .y = y_ + HEIGHT, + .w = WIDTH, + .h = std::ceil(DISPLACEMENT) // Para evitar que tenga una altura de 0 pixels + }; // Comprueba la colisión con las superficies normales y las automáticas const float POS = std::max(room_->checkTopSurfaces(&proj), room_->checkAutoSurfaces(&proj)); if (POS > -1) { // Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie y_ = POS - HEIGHT; + std::cout << "BOTTOM\n"; setState(State::STANDING); - - // Deja de estar enganchado a la superficie automatica - auto_movement_ = false; } else { // Si no hay colisión con los muros, comprueba la colisión con las rampas if (state_ != State::JUMPING) { // Las rampas no se miran si se está saltando - auto rect = toSDLRect(proj); + auto frect = getRect(); + auto rect = toSDLRect(frect); const LineVertical LEFT_SIDE = {.x = rect.x, .y1 = rect.y, .y2 = rect.y + rect.h - 1}; const LineVertical RIGHT_SIDE = {.x = rect.x + rect.w - 1, .y1 = rect.y, .y2 = rect.y + rect.h - 1}; + std::cout << RIGHT_SIDE.x << " " << RIGHT_SIDE.y1 << " " << RIGHT_SIDE.y2 << "\n"; const float POINT = std::max(room_->checkRightSlopes(&RIGHT_SIDE), room_->checkLeftSlopes(&LEFT_SIDE)); if (POINT > -1) { // No está saltando y hay colisión con una rampa // Calcula la nueva posición y_ = POINT - HEIGHT; + std::cout << "BOTTOM SLOPE\n"; setState(State::STANDING); -#ifdef _DEBUG - debug_color_ = static_cast(PaletteColor::YELLOW); - debug_point_ = {.x = x_ + (WIDTH / 2), .y = POINT}; -#endif } else { // No está saltando y no hay colisón con una rampa // Calcula la nueva posición y_ += DISPLACEMENT; -#ifdef _DEBUG - debug_color_ = static_cast(PaletteColor::RED); -#endif } } else { // Esta saltando y no hay colisión con los muros @@ -383,13 +357,7 @@ void Player::moveVerticalDown(float delta_time) { // Recalcula la posición del jugador y su animación void Player::move(float delta_time) { - last_position_ = {.x = x_, .y = y_}; // Guarda la posicion actual antes de modificarla - applyGravity(delta_time); // Aplica gravedad al jugador - checkState(delta_time); // Comprueba el estado del jugador - -#ifdef _DEBUG - debug_color_ = static_cast(PaletteColor::GREEN); -#endif + applyGravity(delta_time); // Aplica gravedad al jugador // Movimiento horizontal if (vx_ < 0.0F) { @@ -398,17 +366,6 @@ void Player::move(float delta_time) { moveHorizontalRight(delta_time); } - // Si ha salido del suelo, el jugador cae - if (state_ == State::STANDING && !isOnFloor()) { - setState(State::FALLING); - auto_movement_ = false; - } - - // Si ha salido de una superficie automatica, detiene el movimiento automatico - if (state_ == State::STANDING && isOnFloor() && !isOnAutoSurface()) { - auto_movement_ = false; - } - // Movimiento vertical if (vy_ < 0.0F) { moveVerticalUp(delta_time); @@ -416,13 +373,7 @@ void Player::move(float delta_time) { moveVerticalDown(delta_time); } - placeSprite(); // Coloca el sprite en la nueva posición - collider_box_ = getRect(); // Actualiza el rectangulo de colisión - -#ifdef _DEBUG - Debug::get()->add("RECT_X: " + std::to_string(debug_rect_x_.x) + "," + std::to_string(debug_rect_x_.y) + "," + std::to_string(debug_rect_x_.w) + "," + std::to_string(debug_rect_x_.h)); - Debug::get()->add("RECT_Y: " + std::to_string(debug_rect_y_.x) + "," + std::to_string(debug_rect_y_.y) + "," + std::to_string(debug_rect_y_.w) + "," + std::to_string(debug_rect_y_.h)); -#endif + placeSprite(); // Coloca el sprite en la nueva posición } // Establece la animación del jugador @@ -434,15 +385,9 @@ void Player::animate(float delta_time) { // Comprueba si ha finalizado el salto al alcanzar la altura de inicio void Player::checkJumpEnd() { - if (state_ == State::JUMPING) { - if (vy_ > 0) { - if (y_ >= jump_init_pos_) { - // Si alcanza la altura de salto inicial, pasa al estado de caída - setState(State::FALLING); - vy_ = MAX_VY; - jumping_time_ = 0.0F; - } - } + if (state_ == State::JUMPING && vy_ > 0.0F && static_cast(y_) >= jump_init_pos_) { + // Si alcanza la altura de salto inicial, pasa al estado de caída + setState(State::FALLING); } } @@ -454,14 +399,14 @@ void Player::playJumpSound() { // Solo reproduce el sonido cuando cambia de índice if (SOUND_INDEX != PREVIOUS_INDEX && SOUND_INDEX < static_cast(jumping_sound_.size())) { JA_PlaySound(jumping_sound_[SOUND_INDEX]); -#ifdef _DEBUG - Debug::get()->add("JUMP: " + std::to_string(SOUND_INDEX)); -#endif } } // Calcula y reproduce el sonido de caer void Player::playFallSound() { + return; + + /* const int SOUND_INDEX = static_cast(falling_time_ / SOUND_INTERVAL); const int PREVIOUS_INDEX = static_cast((falling_time_ - SOUND_INTERVAL) / SOUND_INTERVAL); @@ -473,6 +418,7 @@ void Player::playFallSound() { Debug::get()->add("FALL: " + std::to_string(CLAMPED_INDEX)); #endif } + */ } // Comprueba si el jugador tiene suelo debajo de los pies @@ -490,23 +436,9 @@ auto Player::isOnFloor() -> bool { } // Comprueba las rampas - on_slope_l = room_->checkLeftSlopes(under_feet_.data()); + on_slope_l = room_->checkLeftSlopes(&under_feet_[0]); on_slope_r = room_->checkRightSlopes(&under_feet_[1]); -#ifdef _DEBUG - if (on_floor) { - Debug::get()->add("ON_FLOOR"); - } - - if (on_slope_l) { - Debug::get()->add("ON_SLOPE_L: " + std::to_string(under_feet_[0].x) + "," + std::to_string(under_feet_[0].y)); - } - - if (on_slope_r) { - Debug::get()->add("ON_SLOPE_R: " + std::to_string(under_feet_[1].x) + "," + std::to_string(under_feet_[1].y)); - } -#endif - return on_floor || on_slope_l || on_slope_r; } @@ -521,12 +453,6 @@ auto Player::isOnAutoSurface() -> bool { on_auto_surface |= room_->checkAutoSurfaces(&f); } -#ifdef _DEBUG - if (on_auto_surface) { - Debug::get()->add("ON_AUTO_SURFACE"); - } -#endif - return on_auto_surface; } @@ -538,27 +464,20 @@ auto Player::isOnDownSlope() -> bool { // Cuando el jugador baja una escalera, se queda volando // Hay que mirar otro pixel más por debajo - under_feet_[0].y += 1; - under_feet_[1].y += 1; + SDL_FPoint foot0 = under_feet_[0]; + SDL_FPoint foot1 = under_feet_[1]; + foot0.y += 1.0f; + foot1.y += 1.0f; // Comprueba las rampas - on_slope |= room_->checkLeftSlopes(under_feet_.data()); - on_slope |= room_->checkRightSlopes(&under_feet_[1]); - -#ifdef _DEBUG - if (on_slope) { - Debug::get()->add("ON_DOWN_SLOPE"); - } -#endif + on_slope |= room_->checkLeftSlopes(&foot0); + on_slope |= room_->checkRightSlopes(&foot1); return on_slope; } // Comprueba que el jugador no toque ningun tile de los que matan auto Player::checkKillingTiles() -> bool { - // Actualiza los puntos de colisión - updateColliderPoints(); - // Comprueba si hay contacto con algún tile que mata if (std::ranges::any_of(collider_points_, [this](const auto& c) { return room_->getTile(c) == Room::Tile::KILL; @@ -572,6 +491,7 @@ auto Player::checkKillingTiles() -> bool { // Establece el color del jugador void Player::setColor() { + /* if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { color_ = static_cast(PaletteColor::CYAN); } else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) { @@ -579,6 +499,24 @@ void Player::setColor() { } else { color_ = static_cast(PaletteColor::WHITE); } + */ + + switch (state_) { + case State::STANDING: + color_ = static_cast(PaletteColor::YELLOW); + break; + + case State::JUMPING: + color_ = static_cast(PaletteColor::GREEN); + break; + + case State::FALLING: + color_ = static_cast(PaletteColor::RED); + break; + + default: + break; + } } // Actualiza los puntos de colisión @@ -610,8 +548,39 @@ void Player::setState(State value) { previous_state_ = state_; state_ = value; + switch (state_) { + case State::STANDING: + vy_ = 0.0F; + last_grounded_position_ = static_cast(y_); + std::cout << "SET STANDING\n"; + break; + + case State::JUMPING: + last_grounded_position_ = static_cast(y_); + vy_ = JUMP_VELOCITY; + jump_init_pos_ = y_; + jumping_time_ = 0.0F; + std::cout << "SET JUMPING\n"; + break; + + case State::FALLING: + vx_ = 0.0F; + vy_ = MAX_VY; + playFallSound(); + if (previous_state_ == State::STANDING) { + last_grounded_position_ = static_cast(y_); + } + auto_movement_ = false; + jumping_time_ = 0.0F; + std::cout << "SET FALLING\n"; + break; + + default: + break; + } + // Llama a checkState con delta_time 0 porque esto es un cambio de estado inmediato - checkState(0.0F); + updateState(0.0F); } // Inicializa los sonidos de salto y caida @@ -641,40 +610,18 @@ void Player::applySpawnValues(const SpawnData& spawn) { } // Inicializa el sprite del jugador -void Player::initSprite(/*const std::string& surface_path, */const std::string& animations_path) { - //auto surface = Resource::get()->getSurface(surface_path); +void Player::initSprite(const std::string& animations_path) { auto animations = Resource::get()->getAnimations(animations_path); - sprite_ = std::make_shared(/*surface, */animations); + sprite_ = std::make_unique(animations); sprite_->setWidth(WIDTH); sprite_->setHeight(HEIGHT); sprite_->setCurrentAnimation("walk"); } -#ifdef _DEBUG -// Pinta la información de debug del jugador -void Player::renderDebugInfo() { - if (Debug::get()->getEnabled()) { - auto surface = Screen::get()->getRendererSurface(); - - // Pinta los underfeet - surface->putPixel(under_feet_[0].x, under_feet_[0].y, static_cast(PaletteColor::BRIGHT_MAGENTA)); - surface->putPixel(under_feet_[1].x, under_feet_[1].y, static_cast(PaletteColor::BRIGHT_MAGENTA)); - - // Pinta rectangulo del jugador - SDL_FRect rect = getRect(); - surface->drawRectBorder(&rect, static_cast(PaletteColor::BRIGHT_CYAN)); - - // Pinta el rectangulo de movimiento - if (vx_ != 0.0F) { - surface->fillRect(&debug_rect_x_, static_cast(PaletteColor::BRIGHT_RED)); - } - if (vy_ != 0.0F) { - surface->fillRect(&debug_rect_y_, static_cast(PaletteColor::BRIGHT_RED)); - } - - // Pinta el punto de debug - surface->putPixel(debug_point_.x, debug_point_.y, rand() % 16); - } -} -#endif // _DEBUG \ No newline at end of file +// Coloca el sprite en la posición del jugador +void Player::placeSprite() { + sprite_->setPos(x_, y_); // Recoloca el sprite + collider_box_ = getRect(); // Actualiza el rectangulo de colisión + updateColliderPoints(); // Actualiza los puntos de colisión +} \ No newline at end of file diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index 558bb29..2b1c3e3 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -2,6 +2,7 @@ #include +#include // Para array #include // Para shared_ptr, __shared_ptr_access #include // Para string #include @@ -47,7 +48,6 @@ class Player { struct Data { SpawnData spawn_data; - //std::string texture_path{}; std::string animations_path; std::shared_ptr room = nullptr; @@ -57,7 +57,6 @@ class Player { // Constructor con parámetros Data(SpawnData spawn_data, const std::string& texture_path, std::string animations_path, std::shared_ptr room) : spawn_data(spawn_data), - // texture_path(std::move(texture_path)), animations_path(std::move(animations_path)), room(std::move(room)) {} }; @@ -97,66 +96,55 @@ class Player { // --- --- Objetos y punteros --- --- std::shared_ptr room_; // Objeto encargado de gestionar cada habitación del juego - std::shared_ptr sprite_; // Sprite del jugador + std::unique_ptr sprite_; // Sprite del jugador // --- Variables --- - float x_; // Posición del jugador en el eje X - float y_; // Posición del jugador en el eje Y - float vx_; // Velocidad/desplazamiento del jugador en el eje X - float vy_; // Velocidad/desplazamiento del jugador en el eje Y - Uint8 color_; // Color del jugador - SDL_FRect collider_box_; // Caja de colisión con los enemigos u objetos - std::vector collider_points_; // Puntos de colisión con el mapa - std::vector under_feet_; // Contiene los puntos que hay bajo cada pie del jugador - std::vector feet_; // Contiene los puntos que hay en el pie del jugador - State state_; // Estado en el que se encuentra el jugador. Util apara saber si está saltando o cayendo - State previous_state_; // Estado previo en el que se encontraba el jugador - bool is_on_border_ = false; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla - bool is_alive_ = true; // Indica si el jugador esta vivo o no - bool is_paused_ = false; // Indica si el jugador esta en modo pausa - bool auto_movement_ = false; // Indica si esta siendo arrastrado por una superficie automatica - Room::Border border_ = Room::Border::TOP; // Indica en cual de los cuatro bordes se encuentra - SDL_FRect last_position_; // Contiene la ultima posición del jugador, por si hay que deshacer algun movimiento - int jump_init_pos_; // Valor del eje Y en el que se inicia el salto - std::vector jumping_sound_; // Vecor con todos los sonidos del salto - std::vector falling_sound_; // Vecor con todos los sonidos de la caída - float jumping_time_ = 0.0F; // Tiempo acumulado de salto en segundos - float falling_time_ = 0.0F; // Tiempo acumulado de caída en segundos + float x_ = 0.0F; // Posición del jugador en el eje X + float y_ = 0.0F; // Posición del jugador en el eje Y + float vx_ = 0.0F; // Velocidad/desplazamiento del jugador en el eje X + float vy_ = 0.0F; // Velocidad/desplazamiento del jugador en el eje Y + Uint8 color_ = 0; // Color del jugador + SDL_FRect collider_box_; // Caja de colisión con los enemigos u objetos + std::array collider_points_{}; // Puntos de colisión con el mapa + std::array under_feet_{}; // Contiene los puntos que hay bajo cada pie del jugador + std::array feet_{}; // Contiene los puntos que hay en el pie del jugador + State state_ = State::STANDING; // Estado en el que se encuentra el jugador. Util apara saber si está saltando o cayendo + State previous_state_ = State::STANDING; // Estado previo en el que se encontraba el jugador + bool is_on_border_ = false; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla + bool is_alive_ = true; // Indica si el jugador esta vivo o no + bool is_paused_ = false; // Indica si el jugador esta en modo pausa + bool auto_movement_ = false; // Indica si esta siendo arrastrado por una superficie automatica + Room::Border border_ = Room::Border::TOP; // Indica en cual de los cuatro bordes se encuentra + int jump_init_pos_ = 0; // Valor del eje Y en el que se inicia el salto + std::vector jumping_sound_; // Vecor con todos los sonidos del salto + std::vector falling_sound_; // Vecor con todos los sonidos de la caída + float jumping_time_ = 0.0F; // Tiempo acumulado de salto en segundos + int last_grounded_position_ = 0; // Ultima posición en Y en la que se estaba en contacto con el suelo + bool left_or_right_is_pressed_ = false; // Indica si se está pulsando una de las dos direcciones. Sirve para las conveyor belts // --- Funciones --- - void checkInput(float delta_time); // Comprueba las entradas y modifica variables - void checkBorders(); // Comprueba si se halla en alguno de los cuatro bordes - void checkState(float delta_time); // Comprueba el estado del jugador - void applyGravity(float delta_time); // Aplica gravedad al jugador - void move(float delta_time); // Recalcula la posición del jugador y su animación - void moveHorizontalLeft(float delta_time); // Maneja el movimiento horizontal hacia la izquierda - void moveHorizontalRight(float delta_time); // Maneja el movimiento horizontal hacia la derecha - void moveVerticalUp(float delta_time); // Maneja el movimiento vertical hacia arriba - void moveVerticalDown(float delta_time); // Maneja el movimiento vertical hacia abajo - void animate(float delta_time); // Establece la animación del jugador - void checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio - void playJumpSound(); // Calcula y reproduce el sonido de salto - void playFallSound(); // Calcula y reproduce el sonido de caer - auto isOnFloor() -> bool; // Comprueba si el jugador tiene suelo debajo de los pies - auto isOnAutoSurface() -> bool; // Comprueba si el jugador esta sobre una superficie automática - auto isOnDownSlope() -> bool; // Comprueba si el jugador está sobre una rampa hacia abajo - auto checkKillingTiles() -> bool; // Comprueba que el jugador no toque ningun tile de los que matan - void updateColliderPoints(); // Actualiza los puntos de colisión - void updateFeet(); // Actualiza los puntos de los pies - void setState(State value); // Cambia el estado del jugador - void initSounds(); // Inicializa los sonidos de salto y caida - void placeSprite() { sprite_->setPos(x_, y_); } // Coloca el sprite en la posición del jugador - void applySpawnValues(const SpawnData& spawn); // Aplica los valores de spawn al jugador - void initSprite(/*const std::string& surface_path, */const std::string& animations_path); // Inicializa el sprite del jugador - -#ifdef _DEBUG - // --- Variables --- - SDL_FRect debug_rect_x_; // Rectangulo de desplazamiento para el modo debug - SDL_FRect debug_rect_y_; // Rectangulo de desplazamiento para el modo debug - Uint8 debug_color_; // Color del recuadro de debug del jugador - SDL_FPoint debug_point_; // Punto para debug - - // --- Funciones --- - void renderDebugInfo(); // Pinta la información de debug del jugador -#endif + void checkInput(); // Comprueba las entradas y modifica variables + void checkBorders(); // Comprueba si se halla en alguno de los cuatro bordes + void updateState(float delta_time); // Comprueba el estado del jugador + void applyGravity(float delta_time); // Aplica gravedad al jugador + void move(float delta_time); // Recalcula la posición del jugador y su animación + void moveHorizontalLeft(float delta_time); // Maneja el movimiento horizontal hacia la izquierda + void moveHorizontalRight(float delta_time); // Maneja el movimiento horizontal hacia la derecha + void moveVerticalUp(float delta_time); // Maneja el movimiento vertical hacia arriba + void moveVerticalDown(float delta_time); // Maneja el movimiento vertical hacia abajo + void animate(float delta_time); // Establece la animación del jugador + void checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio + void playJumpSound(); // Calcula y reproduce el sonido de salto + void playFallSound(); // Calcula y reproduce el sonido de caer + auto isOnFloor() -> bool; // Comprueba si el jugador tiene suelo debajo de los pies + auto isOnAutoSurface() -> bool; // Comprueba si el jugador esta sobre una superficie automática + auto isOnDownSlope() -> bool; // Comprueba si el jugador está sobre una rampa hacia abajo + auto checkKillingTiles() -> bool; // Comprueba que el jugador no toque ningun tile de los que matan + void updateColliderPoints(); // Actualiza los puntos de colisión + void updateFeet(); // Actualiza los puntos de los pies + void setState(State value); // Cambia el estado del jugador + void initSounds(); // Inicializa los sonidos de salto y caida + void placeSprite(); // Coloca el sprite en la posición del jugador + void applySpawnValues(const SpawnData& spawn); // Aplica los valores de spawn al jugador + void initSprite(const std::string& animations_path); // Inicializa el sprite del jugador }; \ No newline at end of file diff --git a/source/game/scene_manager.hpp b/source/game/scene_manager.hpp index a479a24..140a7ef 100644 --- a/source/game/scene_manager.hpp +++ b/source/game/scene_manager.hpp @@ -37,7 +37,7 @@ enum class Options { inline Scene current = Scene::LOGO; // Escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual #else -inline Scene current = Scene::GAME_OVER; // Escena actual +inline Scene current = Scene::GAME; // Escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual #endif diff --git a/source/utils/utils.hpp b/source/utils/utils.hpp index 15eb2b8..1daccf0 100644 --- a/source/utils/utils.hpp +++ b/source/utils/utils.hpp @@ -155,17 +155,17 @@ void playMusic(const std::string& music_path); void fillTextureWithColor(SDL_Renderer* renderer, SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b, Uint8 a); inline auto toSDLRect(const SDL_FRect& frect) -> SDL_Rect { - SDL_Rect rect; - rect.x = static_cast(frect.x); - rect.y = static_cast(frect.y); - rect.w = static_cast(frect.w); - rect.h = static_cast(frect.h); + SDL_Rect rect = { + .x = static_cast(frect.x), + .y = static_cast(frect.y), + .w = static_cast(frect.w), + .h = static_cast(frect.h)}; return rect; } inline auto toSDLPoint(const SDL_FPoint& fpoint) -> SDL_Point { - SDL_Point point; - point.x = static_cast(fpoint.x); - point.y = static_cast(fpoint.y); + SDL_Point point = { + .x = static_cast(fpoint.x), + .y = static_cast(fpoint.y)}; return point; } \ No newline at end of file