ajustant el jugador
This commit is contained in:
@@ -76,11 +76,8 @@ void Player::move(float delta_time) {
|
||||
case State::ON_SLOPE:
|
||||
moveOnSlope(delta_time);
|
||||
break;
|
||||
case State::JUMPING:
|
||||
moveJumping(delta_time);
|
||||
break;
|
||||
case State::FALLING:
|
||||
moveFalling(delta_time);
|
||||
case State::ON_AIR:
|
||||
moveOnAir(delta_time);
|
||||
break;
|
||||
}
|
||||
syncSpriteAndCollider(); // Actualiza la posición del sprite y las colisiones
|
||||
@@ -95,11 +92,8 @@ void Player::move(float delta_time) {
|
||||
case State::ON_SLOPE:
|
||||
Debug::get()->set("P.STATE", "ON_SLOPE");
|
||||
break;
|
||||
case State::JUMPING:
|
||||
Debug::get()->set("P.STATE", "JUMPING");
|
||||
break;
|
||||
case State::FALLING:
|
||||
Debug::get()->set("P.STATE", "FALLING");
|
||||
case State::ON_AIR:
|
||||
Debug::get()->set("P.STATE", "ON_AIR");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -117,7 +111,8 @@ void Player::handleConveyorBelts() {
|
||||
|
||||
void Player::handleShouldFall() {
|
||||
if (!isOnFloor() and (state_ == State::ON_GROUND || state_ == State::ON_SLOPE)) {
|
||||
transitionToState(State::FALLING);
|
||||
vy_ = 0.0F;
|
||||
transitionToState(State::ON_AIR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,37 +123,24 @@ void Player::transitionToState(State state) {
|
||||
switch (state) {
|
||||
case State::ON_GROUND:
|
||||
vy_ = 0;
|
||||
handleDeathByFalling();
|
||||
resetSoundControllersOnLanding();
|
||||
if (previous_state_ == State::ON_AIR) {
|
||||
Audio::get()->playSound(land_sound_, Audio::Group::GAME);
|
||||
}
|
||||
current_slope_ = nullptr;
|
||||
break;
|
||||
case State::ON_SLOPE:
|
||||
vy_ = 0;
|
||||
handleDeathByFalling();
|
||||
resetSoundControllersOnLanding();
|
||||
if (previous_state_ == State::ON_AIR) {
|
||||
Audio::get()->playSound(land_sound_, Audio::Group::GAME);
|
||||
}
|
||||
updateCurrentSlope();
|
||||
if (current_slope_ == nullptr) {
|
||||
// Los pies no coinciden con ninguna rampa: tratar como suelo plano
|
||||
state_ = State::ON_GROUND;
|
||||
}
|
||||
break;
|
||||
case State::JUMPING:
|
||||
// Puede saltar desde ON_GROUND o ON_SLOPE
|
||||
if (previous_state_ == State::ON_GROUND || previous_state_ == State::ON_SLOPE) {
|
||||
vy_ = -MAX_VY;
|
||||
last_grounded_position_ = y_;
|
||||
updateVelocity();
|
||||
jump_sound_ctrl_.start();
|
||||
current_slope_ = nullptr;
|
||||
}
|
||||
break;
|
||||
case State::FALLING:
|
||||
fall_start_position_ = static_cast<int>(y_);
|
||||
case State::ON_AIR:
|
||||
last_grounded_position_ = static_cast<int>(y_);
|
||||
vy_ = MAX_VY;
|
||||
vx_ = 0.0F;
|
||||
jump_sound_ctrl_.reset();
|
||||
fall_sound_ctrl_.start(y_);
|
||||
current_slope_ = nullptr;
|
||||
break;
|
||||
}
|
||||
@@ -172,48 +154,48 @@ void Player::updateState(float delta_time) {
|
||||
case State::ON_SLOPE:
|
||||
updateOnSlope(delta_time);
|
||||
break;
|
||||
case State::JUMPING:
|
||||
updateJumping(delta_time);
|
||||
break;
|
||||
case State::FALLING:
|
||||
updateFalling(delta_time);
|
||||
case State::ON_AIR:
|
||||
updateOnAir(delta_time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Inicia un salto desde ON_GROUND/ON_SLOPE: velocidad inicial hacia arriba + sonido + transición
|
||||
void Player::startJump() {
|
||||
vy_ = JUMP_VELOCITY;
|
||||
last_grounded_position_ = y_;
|
||||
Audio::get()->playSound(jump_sound_, Audio::Group::GAME);
|
||||
transitionToState(State::ON_AIR);
|
||||
}
|
||||
|
||||
// Actualización lógica del estado ON_GROUND
|
||||
void Player::updateOnGround(float delta_time) {
|
||||
(void)delta_time; // No usado en este método, pero se mantiene por consistencia
|
||||
handleConveyorBelts(); // Gestiona las cintas transportadoras
|
||||
handleShouldFall(); // Verifica si debe caer (no tiene suelo)
|
||||
|
||||
// Verifica si el jugador quiere saltar
|
||||
if (wanna_jump_) { transitionToState(State::JUMPING); }
|
||||
// El salto tiene prioridad sobre la caída por falta de suelo
|
||||
if (wanna_jump_) {
|
||||
startJump();
|
||||
return;
|
||||
}
|
||||
handleShouldFall(); // Verifica si debe caer (no tiene suelo)
|
||||
}
|
||||
|
||||
// Actualización lógica del estado ON_SLOPE
|
||||
void Player::updateOnSlope(float delta_time) {
|
||||
(void)delta_time; // No usado en este método, pero se mantiene por consistencia
|
||||
|
||||
if (wanna_jump_) {
|
||||
startJump();
|
||||
return;
|
||||
}
|
||||
handleShouldFall();
|
||||
// NOTA: No llamamos handleShouldFall() aquí porque moveOnSlope() ya maneja
|
||||
// todas las condiciones de salida de la rampa (out of bounds, transición a superficie plana)
|
||||
|
||||
// Verifica si el jugador quiere saltar
|
||||
if (wanna_jump_) { transitionToState(State::JUMPING); }
|
||||
}
|
||||
|
||||
// Actualización lógica del estado JUMPING
|
||||
void Player::updateJumping(float delta_time) {
|
||||
auto_movement_ = false; // Desactiva el movimiento automático durante el salto
|
||||
playJumpSound(delta_time); // Reproduce los sonidos de salto
|
||||
handleJumpEnd(); // Verifica si el salto ha terminado (alcanzó la altura inicial)
|
||||
}
|
||||
|
||||
// Actualización lógica del estado FALLING
|
||||
void Player::updateFalling(float delta_time) {
|
||||
auto_movement_ = false; // Desactiva el movimiento automático durante la caída
|
||||
playFallSound(delta_time); // Reproduce los sonidos de caída
|
||||
// Actualización lógica del estado ON_AIR
|
||||
void Player::updateOnAir(float delta_time) {
|
||||
(void)delta_time;
|
||||
auto_movement_ = false; // Desactiva el movimiento automático en el aire
|
||||
}
|
||||
|
||||
// Movimiento físico del estado ON_GROUND
|
||||
@@ -256,7 +238,8 @@ void Player::moveOnSlope(float delta_time) {
|
||||
// Verificar rampa válida antes de comprobar velocidad: si no hay rampa siempre caer,
|
||||
// independientemente de si hay o no input (evita bloqueo con vx_=0 y slope null)
|
||||
if (current_slope_ == nullptr) {
|
||||
transitionToState(State::FALLING);
|
||||
vy_ = 0.0F;
|
||||
transitionToState(State::ON_AIR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -320,7 +303,8 @@ void Player::moveOnSlope(float delta_time) {
|
||||
transitionToState(State::ON_GROUND);
|
||||
} else {
|
||||
// Sin soporte: empezar a caer
|
||||
transitionToState(State::FALLING);
|
||||
vy_ = 0.0F;
|
||||
transitionToState(State::ON_AIR);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -332,69 +316,39 @@ void Player::moveOnSlope(float delta_time) {
|
||||
}*/
|
||||
}
|
||||
|
||||
// Movimiento físico del estado JUMPING
|
||||
void Player::moveJumping(float delta_time) {
|
||||
// Movimiento horizontal
|
||||
// Movimiento físico del estado ON_AIR
|
||||
// El jugador puede moverse horizontalmente en el aire y la gravedad siempre actúa.
|
||||
void Player::moveOnAir(float delta_time) {
|
||||
// Movimiento horizontal libre según wanna_go_ (permite girar en el aire)
|
||||
updateVelocity();
|
||||
applyHorizontalMovement(delta_time);
|
||||
|
||||
// Movimiento vertical
|
||||
// Gravedad
|
||||
applyGravity(delta_time);
|
||||
|
||||
const float DISPLACEMENT_Y = vy_ * delta_time;
|
||||
// Movimiento vertical hacia arriba
|
||||
|
||||
// Subiendo: comprobar techo
|
||||
if (vy_ < 0.0F) {
|
||||
const SDL_FRect PROJECTION = getProjection(Direction::UP, DISPLACEMENT_Y);
|
||||
|
||||
// Comprueba la colisión
|
||||
const int POS = room_->checkBottomSurfaces(PROJECTION);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == Collision::NONE) {
|
||||
// Si no hay colisión
|
||||
y_ += DISPLACEMENT_Y;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona -> FALLING
|
||||
// Choque con techo: se pega por debajo y empieza a caer
|
||||
y_ = POS + 1;
|
||||
transitionToState(State::FALLING);
|
||||
vy_ = 0.0F;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Movimiento vertical hacia abajo
|
||||
else if (vy_ > 0.0F) {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
|
||||
// Bajando: comprobar aterrizaje en superficies y rampas
|
||||
if (vy_ > 0.0F) {
|
||||
const SDL_FRect PROJECTION = getProjection(Direction::DOWN, 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)
|
||||
// Extendemos 1px hacia arriba para detectar suelos traversados ligeramente al
|
||||
// entrar horizontalmente (consecuencia del margen h=HEIGHT-1 en la proyección horizontal)
|
||||
const SDL_FRect ADJ = {.x = PROJECTION.x, .y = PROJECTION.y - 1.0F, .w = PROJECTION.w, .h = PROJECTION.h + 1.0F};
|
||||
const float POS = std::max(room_->checkTopSurfaces(ADJ), room_->checkAutoSurfaces(ADJ));
|
||||
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)
|
||||
y_ += DISPLACEMENT_Y;
|
||||
}
|
||||
}
|
||||
handleLandingFromAir(DISPLACEMENT_Y, PROJECTION);
|
||||
}
|
||||
}
|
||||
|
||||
// Movimiento físico del estado FALLING
|
||||
void Player::moveFalling(float delta_time) {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
const float DISPLACEMENT = vy_ * delta_time;
|
||||
const SDL_FRect PROJECTION = getProjection(Direction::DOWN, DISPLACEMENT);
|
||||
|
||||
// Comprueba aterrizaje en superficies y rampas
|
||||
handleLandingFromAir(DISPLACEMENT, PROJECTION);
|
||||
}
|
||||
|
||||
// Comprueba si está situado en alguno de los cuatro bordes de la habitación
|
||||
auto Player::handleBorders() -> Room::Border {
|
||||
if (x_ < PlayArea::LEFT) {
|
||||
@@ -410,10 +364,8 @@ auto Player::handleBorders() -> Room::Border {
|
||||
}
|
||||
|
||||
if (y_ + HEIGHT > PlayArea::BOTTOM) {
|
||||
// Si llega en estado terminal, muere y no cruza
|
||||
const bool SHOULD_DIE = static_cast<int>(y_) - last_grounded_position_ > MAX_FALLING_HEIGHT;
|
||||
if (SHOULD_DIE) { markAsDead(); }
|
||||
return is_alive_ ? Room::Border::BOTTOM : Room::Border::NONE;
|
||||
// Restricción de muerte por altura de caída desactivada
|
||||
return Room::Border::BOTTOM;
|
||||
}
|
||||
|
||||
return Room::Border::NONE;
|
||||
@@ -454,9 +406,8 @@ void Player::switchBorders() {
|
||||
|
||||
// Aplica gravedad al jugador
|
||||
void Player::applyGravity(float delta_time) {
|
||||
// La gravedad solo se aplica cuando el jugador esta saltando
|
||||
// Nunca mientras cae o esta de pie
|
||||
if (state_ == State::JUMPING) {
|
||||
// La gravedad solo se aplica cuando el jugador esta en el aire
|
||||
if (state_ == State::ON_AIR) {
|
||||
vy_ += GRAVITY_FORCE * delta_time;
|
||||
vy_ = std::min(vy_, MAX_VY);
|
||||
}
|
||||
@@ -464,37 +415,13 @@ void Player::applyGravity(float delta_time) {
|
||||
|
||||
// Establece la animación del jugador
|
||||
void Player::animate(float delta_time) { // NOLINT(readability-make-member-function-const)
|
||||
if (vx_ != 0) {
|
||||
if (state_ == State::ON_AIR) {
|
||||
sprite_->setCurrentAnimation("jump");
|
||||
} else if (vx_ != 0) {
|
||||
sprite_->setCurrentAnimation("default");
|
||||
sprite_->update(delta_time);
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si ha finalizado el salto al alcanzar la altura de inicio
|
||||
void Player::handleJumpEnd() {
|
||||
// Si el jugador vuelve EXACTAMENTE a la altura inicial, debe CONTINUAR en JUMPING
|
||||
// Solo cuando la SUPERA (desciende más allá) cambia a FALLING
|
||||
if (state_ == State::JUMPING && vy_ > 0.0F && static_cast<int>(y_) > last_grounded_position_) {
|
||||
transitionToState(State::FALLING);
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula y reproduce el sonido de salto basado en tiempo transcurrido
|
||||
void Player::playJumpSound(float delta_time) { // NOLINT(readability-convert-member-functions-to-static)
|
||||
size_t sound_index;
|
||||
if (jump_sound_ctrl_.shouldPlay(delta_time, sound_index)) {
|
||||
if (sound_index < jumping_sound_.size()) {
|
||||
Audio::get()->playSound(jumping_sound_[sound_index], Audio::Group::GAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula y reproduce el sonido de caída basado en distancia vertical recorrida
|
||||
void Player::playFallSound(float delta_time) { // NOLINT(readability-convert-member-functions-to-static)
|
||||
size_t sound_index;
|
||||
if (fall_sound_ctrl_.shouldPlay(delta_time, y_, sound_index)) {
|
||||
if (sound_index < falling_sound_.size()) {
|
||||
Audio::get()->playSound(falling_sound_[sound_index], Audio::Group::GAME);
|
||||
}
|
||||
} else {
|
||||
sprite_->setCurrentAnimation("stand");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,98 +592,10 @@ void Player::updateFeet() {
|
||||
.y = y_ + HEIGHT};
|
||||
}
|
||||
|
||||
// Inicializa los sonidos de salto y caida
|
||||
// Inicializa los sonidos de salto y aterrizaje
|
||||
void Player::initSounds() { // NOLINT(readability-convert-member-functions-to-static)
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
std::string sound_file = "jump" + std::to_string(i + 1) + ".wav";
|
||||
jumping_sound_[i] = Resource::Cache::get()->getSound(sound_file);
|
||||
|
||||
if (i >= 10) { // i+1 >= 11
|
||||
falling_sound_[i - 10] = Resource::Cache::get()->getSound(sound_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implementación de JumpSoundController::start
|
||||
void Player::JumpSoundController::start() {
|
||||
current_index = 0;
|
||||
elapsed_time = 0.0F;
|
||||
active = true;
|
||||
}
|
||||
|
||||
// Implementación de JumpSoundController::reset
|
||||
void Player::JumpSoundController::reset() {
|
||||
active = false;
|
||||
current_index = 0;
|
||||
elapsed_time = 0.0F;
|
||||
}
|
||||
|
||||
// Implementación de JumpSoundController::shouldPlay
|
||||
auto Player::JumpSoundController::shouldPlay(float delta_time, size_t& out_index) -> bool {
|
||||
if (!active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Acumula el tiempo transcurrido durante el salto
|
||||
elapsed_time += delta_time;
|
||||
|
||||
// Calcula qué sonido debería estar sonando según el tiempo
|
||||
size_t target_index = FIRST_SOUND + static_cast<size_t>((elapsed_time / SECONDS_PER_SOUND));
|
||||
target_index = std::min(target_index, LAST_SOUND);
|
||||
|
||||
// Reproduce si hemos avanzado a un nuevo sonido
|
||||
if (target_index > current_index) {
|
||||
current_index = target_index;
|
||||
out_index = current_index;
|
||||
return true; // NOLINT(readability-simplify-boolean-expr)
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implementación de FallSoundController::start
|
||||
void Player::FallSoundController::start(float start_y) {
|
||||
current_index = 0;
|
||||
distance_traveled = 0.0F;
|
||||
last_y = start_y;
|
||||
active = true;
|
||||
}
|
||||
|
||||
// Implementación de FallSoundController::reset
|
||||
void Player::FallSoundController::reset() {
|
||||
active = false;
|
||||
current_index = 0;
|
||||
distance_traveled = 0.0F;
|
||||
}
|
||||
|
||||
// Implementación de FallSoundController::shouldPlay
|
||||
auto Player::FallSoundController::shouldPlay(float delta_time, float current_y, size_t& out_index) -> bool {
|
||||
(void)delta_time; // No usado actualmente, pero recibido por consistencia
|
||||
|
||||
if (!active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Acumula la distancia recorrida (solo hacia abajo)
|
||||
if (current_y > last_y) {
|
||||
distance_traveled += (current_y - last_y);
|
||||
}
|
||||
last_y = current_y;
|
||||
|
||||
// Calcula qué sonido debería estar sonando según el intervalo
|
||||
size_t target_index = FIRST_SOUND + static_cast<size_t>((distance_traveled / PIXELS_PER_SOUND));
|
||||
|
||||
// El sonido a reproducir se limita a LAST_SOUND (13), pero el índice interno sigue creciendo
|
||||
size_t sound_to_play = std::min(target_index, LAST_SOUND);
|
||||
|
||||
// Reproduce si hemos avanzado a un nuevo índice (permite repetición de sonido 13)
|
||||
if (target_index > current_index) {
|
||||
current_index = target_index; // Guardamos el índice real (puede ser > LAST_SOUND)
|
||||
out_index = sound_to_play; // Pero reproducimos LAST_SOUND cuando corresponde
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
jump_sound_ = Resource::Cache::get()->getSound("jump.wav");
|
||||
land_sound_ = Resource::Cache::get()->getSound("land.wav");
|
||||
}
|
||||
|
||||
// Aplica los valores de spawn al jugador
|
||||
@@ -810,14 +649,6 @@ void Player::placeSprite() {
|
||||
sprite_->setPos(x_, y_);
|
||||
}
|
||||
|
||||
// Gestiona la muerta al ccaer desde muy alto
|
||||
void Player::handleDeathByFalling() {
|
||||
const int FALL_DISTANCE = static_cast<int>(y_) - last_grounded_position_;
|
||||
if (previous_state_ == State::FALLING && FALL_DISTANCE > MAX_FALLING_HEIGHT) {
|
||||
markAsDead(); // Muere si cae más de 32 píxeles
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula la velocidad en x
|
||||
void Player::updateVelocity() {
|
||||
if (auto_movement_) {
|
||||
@@ -900,12 +731,6 @@ auto Player::handleLandingFromAir(float displacement, const SDL_FRect& projectio
|
||||
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 { // NOLINT(readability-convert-member-functions-to-static)
|
||||
switch (direction) {
|
||||
|
||||
Reference in New Issue
Block a user