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";
vy_ = 0;
handleDeathByFalling();
jump_sound_ctrl_.reset();
fall_sound_ctrl_.reset();
resetSoundControllersOnLanding();
current_slope_ = nullptr;
break;
case State::ON_SLOPE:
//std::cout << "ON_SLOPE\n";
vy_ = 0;
handleDeathByFalling();
jump_sound_ctrl_.reset();
fall_sound_ctrl_.reset();
resetSoundControllersOnLanding();
updateCurrentSlope();
break;
case State::JUMPING:
@@ -208,24 +206,7 @@ void Player::moveOnGround(float delta_time) {
if (vx_ == 0.0F) { return; }
// Movimiento horizontal y colision con muros
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 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;
}
}
applyHorizontalMovement(delta_time);
// 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;
@@ -263,24 +244,7 @@ void Player::moveOnSlope(float delta_time) {
const bool IS_LEFT_SLOPE = isLeftSlope();
// Movimiento horizontal con colisión lateral
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 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;
}
}
applyHorizontalMovement(delta_time);
// Seleccionar el pie apropiado según el tipo de rampa
// Left slopes (forma \) colisionan con el pie izquierdo
@@ -340,23 +304,7 @@ void Player::moveOnSlope(float delta_time) {
// Movimiento físico del estado JUMPING
void Player::moveJumping(float delta_time) {
// Movimiento horizontal
if (vx_ != 0.0F) {
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;
}
}
applyHorizontalMovement(delta_time);
// Movimiento vertical
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
const SDL_FRect PROJECTION = getProjection(Direction::DOWN, DISPLACEMENT_Y);
// 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); // Aterrizó en superficie plana o conveyor belt
}
// Comprueba la colisión con las rampas
else {
// JUMPING colisiona con rampas solo si vx_ == 0
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;
}
// JUMPING colisiona con rampas solo si vx_ == 0
if (vx_ == 0.0F) {
handleLandingFromAir(DISPLACEMENT_Y, PROJECTION);
} else {
// Comprueba la colisión con las superficies y las cintas transportadoras (sin rampas)
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);
} else {
// Esta saltando con movimiento horizontal y no hay colisión con los muros
// Calcula la nueva posición (atraviesa rampas)
@@ -421,26 +357,8 @@ void Player::moveFalling(float delta_time) {
const float DISPLACEMENT = vy_ * delta_time;
const SDL_FRect PROJECTION = getProjection(Direction::DOWN, DISPLACEMENT);
// 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); // 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 aterrizaje en superficies y rampas
handleLandingFromAir(DISPLACEMENT, PROJECTION);
}
// 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
auto Player::getProjection(Direction direction, float displacement) -> SDL_FRect {
switch (direction) {

View File

@@ -181,8 +181,11 @@ class Player {
void applyGravity(float delta_time); // Aplica gravedad al jugador
// --- Funciones de movimiento y colisión ---
void move(float delta_time); // Orquesta el movimiento del jugador
auto getProjection(Direction direction, float displacement) -> SDL_FRect; // Devuelve el rectangulo de proyeccion
void move(float delta_time); // Orquesta el movimiento del jugador
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 ---
auto isOnFloor() -> bool; // Comprueba si el jugador tiene suelo debajo de los pies