classe Player refactoritzada per chanclot

This commit is contained in:
2025-11-19 19:56:35 +01:00
parent e73f573e9a
commit cbe71b5af4
2 changed files with 79 additions and 101 deletions

View File

@@ -113,16 +113,14 @@ void Player::transitionToState(State state) {
//std::cout << "ON_GROUND\n"; //std::cout << "ON_GROUND\n";
vy_ = 0; vy_ = 0;
handleDeathByFalling(); handleDeathByFalling();
jump_sound_ctrl_.reset(); resetSoundControllersOnLanding();
fall_sound_ctrl_.reset();
current_slope_ = nullptr; current_slope_ = nullptr;
break; break;
case State::ON_SLOPE: case State::ON_SLOPE:
//std::cout << "ON_SLOPE\n"; //std::cout << "ON_SLOPE\n";
vy_ = 0; vy_ = 0;
handleDeathByFalling(); handleDeathByFalling();
jump_sound_ctrl_.reset(); resetSoundControllersOnLanding();
fall_sound_ctrl_.reset();
updateCurrentSlope(); updateCurrentSlope();
break; break;
case State::JUMPING: case State::JUMPING:
@@ -208,24 +206,7 @@ void Player::moveOnGround(float delta_time) {
if (vx_ == 0.0F) { return; } if (vx_ == 0.0F) { return; }
// Movimiento horizontal y colision con muros // Movimiento horizontal y colision con muros
const float DISPLACEMENT = vx_ * delta_time; applyHorizontalMovement(delta_time);
if (vx_ < 0.0F) {
const SDL_FRect PROJECTION = getProjection(Direction::LEFT, DISPLACEMENT);
const int POS = room_->checkRightSurfaces(PROJECTION);
if (POS == Collision::NONE) {
x_ += DISPLACEMENT;
} else {
x_ = POS + 1;
}
} else if (vx_ > 0.0F) {
const SDL_FRect PROJECTION = getProjection(Direction::RIGHT, DISPLACEMENT);
const int POS = room_->checkLeftSurfaces(PROJECTION);
if (POS == Collision::NONE) {
x_ += DISPLACEMENT;
} else {
x_ = POS - WIDTH;
}
}
// Comprueba colision con rampas, corrige y cambia estado // Comprueba colision con rampas, corrige y cambia estado
const int SIDE_X = vx_ < 0.0F ? static_cast<int>(x_) : static_cast<int>(x_) + WIDTH - 1; const int SIDE_X = vx_ < 0.0F ? static_cast<int>(x_) : static_cast<int>(x_) + WIDTH - 1;
@@ -263,24 +244,7 @@ void Player::moveOnSlope(float delta_time) {
const bool IS_LEFT_SLOPE = isLeftSlope(); const bool IS_LEFT_SLOPE = isLeftSlope();
// Movimiento horizontal con colisión lateral // Movimiento horizontal con colisión lateral
const float DISPLACEMENT = vx_ * delta_time; applyHorizontalMovement(delta_time);
if (vx_ < 0.0F) {
const SDL_FRect PROJECTION = getProjection(Direction::LEFT, DISPLACEMENT);
const int POS = room_->checkRightSurfaces(PROJECTION);
if (POS == Collision::NONE) {
x_ += DISPLACEMENT;
} else {
x_ = POS + 1;
}
} else if (vx_ > 0.0F) {
const SDL_FRect PROJECTION = getProjection(Direction::RIGHT, DISPLACEMENT);
const int POS = room_->checkLeftSurfaces(PROJECTION);
if (POS == Collision::NONE) {
x_ += DISPLACEMENT;
} else {
x_ = POS - WIDTH;
}
}
// Seleccionar el pie apropiado según el tipo de rampa // Seleccionar el pie apropiado según el tipo de rampa
// Left slopes (forma \) colisionan con el pie izquierdo // Left slopes (forma \) colisionan con el pie izquierdo
@@ -340,23 +304,7 @@ void Player::moveOnSlope(float delta_time) {
// Movimiento físico del estado JUMPING // Movimiento físico del estado JUMPING
void Player::moveJumping(float delta_time) { void Player::moveJumping(float delta_time) {
// Movimiento horizontal // Movimiento horizontal
if (vx_ != 0.0F) { applyHorizontalMovement(delta_time);
const float DISPLACEMENT_X = vx_ * delta_time;
const Direction DIRECTION = vx_ > 0.0F ? Direction::RIGHT : Direction::LEFT;
const SDL_FRect PROJECTION = getProjection(DIRECTION, DISPLACEMENT_X);
// Comprueba la colisión con las superficies
const int POS = DIRECTION == Direction::LEFT ? room_->checkRightSurfaces(PROJECTION) : room_->checkLeftSurfaces(PROJECTION);
// Calcula la nueva posición
if (POS == Collision::NONE) {
// No hay colisión: mueve al jugador
x_ += DISPLACEMENT_X;
} else {
// Hay colisión: reposiciona al jugador en el punto de colisión
x_ = DIRECTION == Direction::LEFT ? POS + 1 : POS - WIDTH;
}
}
// Movimiento vertical // Movimiento vertical
applyGravity(delta_time); applyGravity(delta_time);
@@ -384,28 +332,16 @@ void Player::moveJumping(float delta_time) {
// Crea el rectangulo de proyección en el eje Y para ver si colisiona // Crea el rectangulo de proyección en el eje Y para ver si colisiona
const SDL_FRect PROJECTION = getProjection(Direction::DOWN, DISPLACEMENT_Y); const SDL_FRect PROJECTION = getProjection(Direction::DOWN, DISPLACEMENT_Y);
// Comprueba la colisión con las superficies y las cintas transportadoras // JUMPING colisiona con rampas solo si vx_ == 0
const float POS = std::max(room_->checkTopSurfaces(PROJECTION), room_->checkAutoSurfaces(PROJECTION)); if (vx_ == 0.0F) {
if (POS != Collision::NONE) { handleLandingFromAir(DISPLACEMENT_Y, PROJECTION);
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie } else {
y_ = POS - HEIGHT; // Comprueba la colisión con las superficies y las cintas transportadoras (sin rampas)
transitionToState(State::ON_GROUND); // Aterrizó en superficie plana o conveyor belt const float POS = std::max(room_->checkTopSurfaces(PROJECTION), room_->checkAutoSurfaces(PROJECTION));
} if (POS != Collision::NONE) {
// Comprueba la colisión con las rampas // Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
else { y_ = POS - HEIGHT;
// JUMPING colisiona con rampas solo si vx_ == 0 transitionToState(State::ON_GROUND);
if (vx_ == 0.0F) {
auto rect = toSDLRect(PROJECTION);
const LineVertical LEFT_SIDE = {.x = rect.x, .y1 = rect.y, .y2 = rect.y + rect.h};
const LineVertical RIGHT_SIDE = {.x = rect.x + rect.w - 1, .y1 = rect.y, .y2 = rect.y + rect.h};
const float POINT = std::max(room_->checkRightSlopes(RIGHT_SIDE), room_->checkLeftSlopes(LEFT_SIDE));
if (POINT != Collision::NONE) {
y_ = POINT - HEIGHT;
transitionToState(State::ON_SLOPE); // Aterrizó en rampa
} else {
// No hay colisón con una rampa
y_ += DISPLACEMENT_Y;
}
} else { } else {
// Esta saltando con movimiento horizontal y no hay colisión con los muros // Esta saltando con movimiento horizontal y no hay colisión con los muros
// Calcula la nueva posición (atraviesa rampas) // Calcula la nueva posición (atraviesa rampas)
@@ -421,26 +357,8 @@ void Player::moveFalling(float delta_time) {
const float DISPLACEMENT = vy_ * delta_time; const float DISPLACEMENT = vy_ * delta_time;
const SDL_FRect PROJECTION = getProjection(Direction::DOWN, DISPLACEMENT); const SDL_FRect PROJECTION = getProjection(Direction::DOWN, DISPLACEMENT);
// Comprueba la colisión con las superficies y las cintas transportadoras // Comprueba aterrizaje en superficies y rampas
const float POS = std::max(room_->checkTopSurfaces(PROJECTION), room_->checkAutoSurfaces(PROJECTION)); handleLandingFromAir(DISPLACEMENT, PROJECTION);
if (POS != Collision::NONE) {
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
y_ = POS - HEIGHT;
transitionToState(State::ON_GROUND); // Aterrizó en superficie plana o conveyor belt
}
// Comprueba la colisión con las rampas
else {
auto rect = toSDLRect(PROJECTION);
const LineVertical LEFT_SIDE = {.x = rect.x, .y1 = rect.y, .y2 = rect.y + rect.h};
const LineVertical RIGHT_SIDE = {.x = rect.x + rect.w - 1, .y1 = rect.y, .y2 = rect.y + rect.h};
const float POINT = std::max(room_->checkRightSlopes(RIGHT_SIDE), room_->checkLeftSlopes(LEFT_SIDE));
if (POINT != Collision::NONE) {
y_ = POINT - HEIGHT;
transitionToState(State::ON_SLOPE); // Aterrizó en rampa
} else {
y_ += DISPLACEMENT;
}
}
} }
// Comprueba si está situado en alguno de los cuatro bordes de la habitación // Comprueba si está situado en alguno de los cuatro bordes de la habitación
@@ -869,6 +787,63 @@ void Player::updateVelocity() {
} }
} }
// Aplica movimiento horizontal con colisión de muros
void Player::applyHorizontalMovement(float delta_time) {
if (vx_ == 0.0F) { return; }
const float DISPLACEMENT = vx_ * delta_time;
if (vx_ < 0.0F) {
const SDL_FRect PROJECTION = getProjection(Direction::LEFT, DISPLACEMENT);
const int POS = room_->checkRightSurfaces(PROJECTION);
if (POS == Collision::NONE) {
x_ += DISPLACEMENT;
} else {
x_ = POS + 1;
}
} else {
const SDL_FRect PROJECTION = getProjection(Direction::RIGHT, DISPLACEMENT);
const int POS = room_->checkLeftSurfaces(PROJECTION);
if (POS == Collision::NONE) {
x_ += DISPLACEMENT;
} else {
x_ = POS - WIDTH;
}
}
}
// Detecta aterrizaje en superficies y rampas
auto Player::handleLandingFromAir(float displacement, const SDL_FRect& projection) -> bool {
// Comprueba la colisión con las superficies y las cintas transportadoras
const float POS = std::max(room_->checkTopSurfaces(projection), room_->checkAutoSurfaces(projection));
if (POS != Collision::NONE) {
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
y_ = POS - HEIGHT;
transitionToState(State::ON_GROUND);
return true;
}
// Comprueba la colisión con las rampas
auto rect = toSDLRect(projection);
const LineVertical LEFT_SIDE = {.x = rect.x, .y1 = rect.y, .y2 = rect.y + rect.h};
const LineVertical RIGHT_SIDE = {.x = rect.x + rect.w - 1, .y1 = rect.y, .y2 = rect.y + rect.h};
const float POINT = std::max(room_->checkRightSlopes(RIGHT_SIDE), room_->checkLeftSlopes(LEFT_SIDE));
if (POINT != Collision::NONE) {
y_ = POINT - HEIGHT;
transitionToState(State::ON_SLOPE);
return true;
}
// No hay colisión
y_ += displacement;
return false;
}
// Resetea los controladores de sonido al aterrizar
void Player::resetSoundControllersOnLanding() {
jump_sound_ctrl_.reset();
fall_sound_ctrl_.reset();
}
// Devuelve el rectangulo de proyeccion // Devuelve el rectangulo de proyeccion
auto Player::getProjection(Direction direction, float displacement) -> SDL_FRect { auto Player::getProjection(Direction direction, float displacement) -> SDL_FRect {
switch (direction) { switch (direction) {

View File

@@ -181,8 +181,11 @@ class Player {
void applyGravity(float delta_time); // Aplica gravedad al jugador void applyGravity(float delta_time); // Aplica gravedad al jugador
// --- Funciones de movimiento y colisión --- // --- Funciones de movimiento y colisión ---
void move(float delta_time); // Orquesta el movimiento del jugador void move(float delta_time); // Orquesta el movimiento del jugador
auto getProjection(Direction direction, float displacement) -> SDL_FRect; // Devuelve el rectangulo de proyeccion auto getProjection(Direction direction, float displacement) -> SDL_FRect; // Devuelve el rectangulo de proyeccion
void applyHorizontalMovement(float delta_time); // Aplica movimiento horizontal con colisión de muros
auto handleLandingFromAir(float displacement, const SDL_FRect& projection) -> bool; // Detecta aterrizaje en superficies y rampas
void resetSoundControllersOnLanding(); // Resetea los controladores de sonido al aterrizar
// --- Funciones de detección de superficies --- // --- Funciones de detección de superficies ---
auto isOnFloor() -> bool; // Comprueba si el jugador tiene suelo debajo de los pies auto isOnFloor() -> bool; // Comprueba si el jugador tiene suelo debajo de los pies