This commit is contained in:
2025-10-19 22:01:31 +02:00
parent 16306f2325
commit 2b4523d644
101 changed files with 2058 additions and 1564 deletions

View File

@@ -1,6 +1,6 @@
#include "player.hpp"
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_FlipMode
#include <SDL3/SDL.h> // Para SDL_FlipMode
#include <algorithm> // Para clamp, max, min
#include <cmath> // Para fmod
@@ -14,12 +14,8 @@
#include "manage_hiscore_table.hpp" // Para ManageHiScoreTable, HiScoreEntry
#include "param.hpp" // Para Param, ParamGame, param
#include "scoreboard.hpp" // Para Scoreboard
#include "stage.hpp" // Para power_can_be_added
#include "stage_interface.hpp" // Para IStageInfo
#include "texture.hpp" // Para Texture
#ifdef _DEBUG
#include <iostream>
#endif
// Constructor
Player::Player(const Config& config)
@@ -61,8 +57,8 @@ void Player::init() {
extra_hit_ = false;
coffees_ = 0;
continue_counter_ = 10;
name_entry_idle_time_accumulator_ = 0.0f;
name_entry_total_time_accumulator_ = 0.0f;
name_entry_idle_time_accumulator_ = 0.0F;
name_entry_total_time_accumulator_ = 0.0F;
shiftColliders();
vel_x_ = 0;
vel_y_ = 0;
@@ -146,37 +142,37 @@ void Player::setInputEnteringName(Input::Action action) {
default:
break;
}
name_entry_idle_time_accumulator_ = 0.0f;
name_entry_idle_time_accumulator_ = 0.0F;
}
// Sistema de movimiento
void Player::move(float deltaTime) {
void Player::move(float delta_time) {
switch (playing_state_) {
case State::PLAYING:
handlePlayingMovement(deltaTime);
handlePlayingMovement(delta_time);
break;
case State::ROLLING:
handleRollingMovement();
break;
case State::TITLE_ANIMATION:
handleTitleAnimation(deltaTime);
handleTitleAnimation(delta_time);
break;
case State::CONTINUE_TIME_OUT:
handleContinueTimeOut();
break;
case State::LEAVING_SCREEN:
updateStepCounter(deltaTime);
handleLeavingScreen(deltaTime);
updateStepCounter(delta_time);
handleLeavingScreen(delta_time);
break;
case State::ENTERING_SCREEN:
updateStepCounter(deltaTime);
handleEnteringScreen(deltaTime);
updateStepCounter(delta_time);
handleEnteringScreen(delta_time);
break;
case State::CREDITS:
handleCreditsMovement(deltaTime);
handleCreditsMovement(delta_time);
break;
case State::WAITING:
handleWaitingMovement(deltaTime);
handleWaitingMovement(delta_time);
break;
case State::RECOVER:
handleRecoverMovement();
@@ -187,9 +183,9 @@ void Player::move(float deltaTime) {
}
// Movimiento time-based durante el juego
void Player::handlePlayingMovement(float deltaTime) {
void Player::handlePlayingMovement(float delta_time) {
// Mueve el jugador a derecha o izquierda (time-based en segundos)
pos_x_ += vel_x_ * deltaTime;
pos_x_ += vel_x_ * delta_time;
// Si el jugador abandona el area de juego por los laterales, restaura su posición
const float MIN_X = play_area_.x - 5;
@@ -253,10 +249,10 @@ void Player::handleRollingBounce() {
playSound("jump.wav");
}
void Player::handleTitleAnimation(float deltaTime) {
void Player::handleTitleAnimation(float delta_time) {
setInputBasedOnPlayerId();
pos_x_ += (vel_x_ * 2.0F) * deltaTime;
pos_x_ += (vel_x_ * 2.0F) * delta_time;
const float MIN_X = -WIDTH;
const float MAX_X = play_area_.w;
pos_x_ = std::clamp(pos_x_, MIN_X, MAX_X);
@@ -275,11 +271,11 @@ void Player::handleContinueTimeOut() {
}
}
void Player::handleLeavingScreen(float deltaTime) {
void Player::handleLeavingScreen(float delta_time) {
// updateStepCounter se llama desde move() con deltaTime
setInputBasedOnPlayerId();
pos_x_ += vel_x_ * deltaTime;
pos_x_ += vel_x_ * delta_time;
const float MIN_X = -WIDTH;
const float MAX_X = play_area_.w;
pos_x_ = std::clamp(pos_x_, MIN_X, MAX_X);
@@ -290,15 +286,15 @@ void Player::handleLeavingScreen(float deltaTime) {
}
}
void Player::handleEnteringScreen(float deltaTime) {
void Player::handleEnteringScreen(float delta_time) {
// updateStepCounter se llama desde move() con deltaTime
switch (id_) {
case Id::PLAYER1:
handlePlayer1Entering(deltaTime);
handlePlayer1Entering(delta_time);
break;
case Id::PLAYER2:
handlePlayer2Entering(deltaTime);
handlePlayer2Entering(delta_time);
break;
default:
break;
@@ -307,18 +303,18 @@ void Player::handleEnteringScreen(float deltaTime) {
shiftSprite();
}
void Player::handlePlayer1Entering(float deltaTime) {
void Player::handlePlayer1Entering(float delta_time) {
setInputPlaying(Input::Action::RIGHT);
pos_x_ += vel_x_ * deltaTime;
pos_x_ += vel_x_ * delta_time;
if (pos_x_ > default_pos_x_) {
pos_x_ = default_pos_x_;
setPlayingState(State::PLAYING);
}
}
void Player::handlePlayer2Entering(float deltaTime) {
void Player::handlePlayer2Entering(float delta_time) {
setInputPlaying(Input::Action::LEFT);
pos_x_ += vel_x_ * deltaTime;
pos_x_ += vel_x_ * delta_time;
if (pos_x_ < default_pos_x_) {
pos_x_ = default_pos_x_;
setPlayingState(State::PLAYING);
@@ -326,8 +322,8 @@ void Player::handlePlayer2Entering(float deltaTime) {
}
// Movimiento general en la pantalla de créditos (time-based)
void Player::handleCreditsMovement(float deltaTime) {
pos_x_ += (vel_x_ / 2.0F) * deltaTime;
void Player::handleCreditsMovement(float delta_time) {
pos_x_ += (vel_x_ / 2.0F) * delta_time;
if (vel_x_ > 0) {
handleCreditsRightMovement();
@@ -354,11 +350,11 @@ void Player::handleCreditsLeftMovement() {
}
// Controla la animación del jugador saludando (time-based)
void Player::handleWaitingMovement(float deltaTime) {
waiting_time_accumulator_ += deltaTime;
const float WAITING_DURATION_S = static_cast<float>(WAITING_COUNTER) / 60.0f; // Convert frames to seconds
void Player::handleWaitingMovement(float delta_time) {
waiting_time_accumulator_ += delta_time;
const float WAITING_DURATION_S = static_cast<float>(WAITING_COUNTER) / 60.0F; // Convert frames to seconds
if (waiting_time_accumulator_ >= WAITING_DURATION_S) {
waiting_time_accumulator_ = 0.0f;
waiting_time_accumulator_ = 0.0F;
player_sprite_->resetAnimation();
}
}
@@ -385,11 +381,11 @@ void Player::setInputBasedOnPlayerId() {
}
// Incrementa o ajusta el contador de pasos (time-based)
void Player::updateStepCounter(float deltaTime) {
step_time_accumulator_ += deltaTime;
const float STEP_INTERVAL_S = 10.0f / 60.0f; // 10 frames converted to seconds
void Player::updateStepCounter(float delta_time) {
step_time_accumulator_ += delta_time;
const float STEP_INTERVAL_S = 10.0F / 60.0F; // 10 frames converted to seconds
if (step_time_accumulator_ >= STEP_INTERVAL_S) {
step_time_accumulator_ = 0.0f;
step_time_accumulator_ = 0.0F;
playSound("walk.wav");
}
}
@@ -460,7 +456,7 @@ auto Player::computeAnimation() const -> std::pair<std::string, SDL_FlipMode> {
}
// Establece la animación correspondiente al estado
void Player::setAnimation(float deltaTime) {
void Player::setAnimation(float delta_time) {
switch (playing_state_) {
case State::PLAYING:
case State::ENTERING_SCREEN:
@@ -497,22 +493,22 @@ void Player::setAnimation(float deltaTime) {
}
// La diferencia clave: usa deltaTime para las animaciones
player_sprite_->update(deltaTime);
power_sprite_->update(deltaTime);
player_sprite_->update(delta_time);
power_sprite_->update(delta_time);
}
// Actualiza al jugador con deltaTime (time-based)
void Player::update(float deltaTime) {
move(deltaTime); // Sistema de movimiento time-based
setAnimation(deltaTime); // Animaciones time-based
shiftColliders(); // Sin cambios (posicional)
updateFireSystem(deltaTime); // Sistema de disparo de dos líneas
updatePowerUp(deltaTime); // Sistema de power-up time-based
updateInvulnerable(deltaTime); // Sistema de invulnerabilidad time-based
updateScoreboard(); // Sin cambios (no temporal)
updateContinueCounter(deltaTime); // Sistema de continue time-based
updateEnterNameCounter(deltaTime); // Sistema de name entry time-based
updateShowingName(deltaTime); // Sistema de showing name time-based
void Player::update(float delta_time) {
move(delta_time); // Sistema de movimiento time-based
setAnimation(delta_time); // Animaciones time-based
shiftColliders(); // Sin cambios (posicional)
updateFireSystem(delta_time); // Sistema de disparo de dos líneas
updatePowerUp(delta_time); // Sistema de power-up time-based
updateInvulnerable(delta_time); // Sistema de invulnerabilidad time-based
updateScoreboard(); // Sin cambios (no temporal)
updateContinueCounter(delta_time); // Sistema de continue time-based
updateEnterNameCounter(delta_time); // Sistema de name entry time-based
updateShowingName(delta_time); // Sistema de showing name time-based
}
void Player::passShowingName() {
@@ -584,7 +580,7 @@ void Player::setPlayingState(State state) {
case State::CONTINUE: {
// Inicializa el contador de continuar
continue_counter_ = 9;
continue_time_accumulator_ = 0.0f; // Initialize time accumulator
continue_time_accumulator_ = 0.0F; // Initialize time accumulator
playSound("continue_clock.wav");
setScoreboardMode(Scoreboard::Mode::CONTINUE);
break;
@@ -603,7 +599,7 @@ void Player::setPlayingState(State state) {
}
pos_y_ = default_pos_y_;
waiting_counter_ = 0;
waiting_time_accumulator_ = 0.0f; // Initialize time accumulator
waiting_time_accumulator_ = 0.0F; // Initialize time accumulator
shiftSprite();
player_sprite_->setCurrentAnimation("hello");
player_sprite_->animtionPause();
@@ -615,7 +611,7 @@ void Player::setPlayingState(State state) {
break;
}
case State::SHOWING_NAME: {
showing_name_time_accumulator_ = 0.0f; // Inicializar acumulador time-based
showing_name_time_accumulator_ = 0.0F; // Inicializar acumulador time-based
setScoreboardMode(Scoreboard::Mode::ENTER_TO_SHOW_NAME); // Iniciar animación de transición
Scoreboard::get()->setEnterName(scoreboard_panel_, last_enter_name_);
addScoreToScoreBoard();
@@ -624,7 +620,7 @@ void Player::setPlayingState(State state) {
case State::ROLLING: {
// Activa la animación de rodar dando botes
player_sprite_->setCurrentAnimation("rolling");
player_sprite_->setAnimationSpeed(4.0f / 60.0f); // 4 frames convertido a segundos
player_sprite_->setAnimationSpeed(4.0F / 60.0F); // 4 frames convertido a segundos
player_sprite_->setVelY(-396.0F); // Velocidad inicial (6.6 * 60 = 396 pixels/s)
player_sprite_->setAccelY(720.0F); // Gravedad (0.2 * 60² = 720 pixels/s²)
player_sprite_->setPosY(pos_y_ - 2); // Para "sacarlo" del suelo, ya que está hundido un pixel para ocultar el outline de los pies
@@ -648,7 +644,7 @@ void Player::setPlayingState(State state) {
player_sprite_->setVelY(-240.0F); // -4.0 * 60 = -240 pixels/s
player_sprite_->setVelX(0.0F);
player_sprite_->setCurrentAnimation("rolling");
player_sprite_->setAnimationSpeed(5.0f / 60.0f); // 5 frames convertido a segundos
player_sprite_->setAnimationSpeed(5.0F / 60.0F); // 5 frames convertido a segundos
setScoreboardMode(Scoreboard::Mode::GAME_OVER);
playSound("voice_aw_aw_aw.wav");
playSound("jump.wav");
@@ -671,14 +667,14 @@ void Player::setPlayingState(State state) {
}
case State::LEAVING_SCREEN: {
step_counter_ = 0;
step_time_accumulator_ = 0.0f; // Initialize time accumulator
step_time_accumulator_ = 0.0F; // Initialize time accumulator
setScoreboardMode(Scoreboard::Mode::GAME_COMPLETED);
break;
}
case State::ENTERING_SCREEN: {
init();
step_counter_ = 0;
step_time_accumulator_ = 0.0f; // Initialize time accumulator
step_time_accumulator_ = 0.0F; // Initialize time accumulator
setScoreboardMode(Scoreboard::Mode::SCORE);
switch (id_) {
case Id::PLAYER1:
@@ -719,25 +715,25 @@ void Player::decScoreMultiplier() {
void Player::setInvulnerable(bool value) {
invulnerable_ = value;
invulnerable_counter_ = invulnerable_ ? INVULNERABLE_COUNTER : 0;
invulnerable_time_accumulator_ = invulnerable_ ? static_cast<float>(INVULNERABLE_COUNTER) / 60.0f : 0.0f; // Convert frames to seconds
invulnerable_time_accumulator_ = invulnerable_ ? static_cast<float>(INVULNERABLE_COUNTER) / 60.0F : 0.0F; // Convert frames to seconds
}
// Monitoriza el estado (time-based)
void Player::updateInvulnerable(float deltaTime) {
void Player::updateInvulnerable(float delta_time) {
if (playing_state_ == State::PLAYING && invulnerable_) {
if (invulnerable_time_accumulator_ > 0) {
invulnerable_time_accumulator_ -= deltaTime;
invulnerable_time_accumulator_ -= delta_time;
// Frecuencia fija de parpadeo adaptada a deltaTime (en segundos)
constexpr float BLINK_PERIOD_S = 8.0f / 60.0f; // 8 frames convertidos a segundos
constexpr float BLINK_PERIOD_S = 8.0F / 60.0F; // 8 frames convertidos a segundos
// Calcula proporción decreciente basada en tiempo restante
const float TOTAL_INVULNERABLE_TIME_S = static_cast<float>(INVULNERABLE_COUNTER) / 60.0f;
float progress = 1.0f - (invulnerable_time_accumulator_ / TOTAL_INVULNERABLE_TIME_S);
float white_proportion = 0.5f - progress * 0.2f; // Menos blanco hacia el final
const float TOTAL_INVULNERABLE_TIME_S = static_cast<float>(INVULNERABLE_COUNTER) / 60.0F;
float progress = 1.0F - (invulnerable_time_accumulator_ / TOTAL_INVULNERABLE_TIME_S);
float white_proportion = 0.5F - (progress * 0.2F); // Menos blanco hacia el final
// Calcula si debe mostrar textura de invulnerabilidad basado en el ciclo temporal
float cycle_position = fmod(invulnerable_time_accumulator_, BLINK_PERIOD_S) / BLINK_PERIOD_S;
float cycle_position = std::fmod(invulnerable_time_accumulator_, BLINK_PERIOD_S) / BLINK_PERIOD_S;
bool should_show_invulnerable = cycle_position < white_proportion;
size_t target_texture = should_show_invulnerable ? INVULNERABLE_TEXTURE : coffees_;
@@ -758,17 +754,17 @@ void Player::updateInvulnerable(float deltaTime) {
void Player::setPowerUp() {
power_up_ = true;
power_up_counter_ = POWERUP_COUNTER;
power_up_time_accumulator_ = static_cast<float>(POWERUP_COUNTER) / 60.0f; // Convert frames to seconds
power_up_time_accumulator_ = static_cast<float>(POWERUP_COUNTER) / 60.0F; // Convert frames to seconds
power_sprite_visible_ = true; // Inicialmente visible cuando se activa el power-up
in_power_up_ending_phase_ = false; // Empezar en fase normal
bullet_color_toggle_ = false; // Resetear toggle
}
// Actualiza el valor de la variable (time-based)
void Player::updatePowerUp(float deltaTime) {
void Player::updatePowerUp(float delta_time) {
if (playing_state_ == State::PLAYING) {
if (power_up_) {
power_up_time_accumulator_ -= deltaTime;
power_up_time_accumulator_ -= delta_time;
power_up_ = power_up_time_accumulator_ > 0;
if (!power_up_) {
power_up_time_accumulator_ = 0;
@@ -778,8 +774,8 @@ void Player::updatePowerUp(float deltaTime) {
// Los colores ahora se manejan dinámicamente en getNextBulletColor()
} else {
// Calcular visibilidad del power sprite
const float TOTAL_POWERUP_TIME_S = static_cast<float>(POWERUP_COUNTER) / 60.0f;
const float QUARTER_TIME_S = TOTAL_POWERUP_TIME_S / 4.0f;
const float TOTAL_POWERUP_TIME_S = static_cast<float>(POWERUP_COUNTER) / 60.0F;
const float QUARTER_TIME_S = TOTAL_POWERUP_TIME_S / 4.0F;
if (power_up_time_accumulator_ > QUARTER_TIME_S) {
// En los primeros 75% del tiempo, siempre visible
@@ -787,10 +783,10 @@ void Player::updatePowerUp(float deltaTime) {
in_power_up_ending_phase_ = false;
} else {
// En el último 25%, parpadea cada 20 frames (≈0.333s)
constexpr float BLINK_PERIOD_S = 20.0f / 60.0f;
constexpr float VISIBLE_PROPORTION = 4.0f / 20.0f;
constexpr float BLINK_PERIOD_S = 20.0F / 60.0F;
constexpr float VISIBLE_PROPORTION = 4.0F / 20.0F;
float cycle_position = fmod(power_up_time_accumulator_, BLINK_PERIOD_S) / BLINK_PERIOD_S;
float cycle_position = std::fmod(power_up_time_accumulator_, BLINK_PERIOD_S) / BLINK_PERIOD_S;
power_sprite_visible_ = cycle_position >= VISIBLE_PROPORTION;
in_power_up_ending_phase_ = true; // Activar modo alternancia de colores de balas
}
@@ -836,10 +832,10 @@ void Player::setPlayerTextures(const std::vector<std::shared_ptr<Texture>>& text
}
// Actualiza el contador de continue (time-based)
void Player::updateContinueCounter(float deltaTime) {
void Player::updateContinueCounter(float delta_time) {
if (playing_state_ == State::CONTINUE) {
continue_time_accumulator_ += deltaTime;
constexpr float CONTINUE_INTERVAL_S = 1.0f; // 1 segundo
continue_time_accumulator_ += delta_time;
constexpr float CONTINUE_INTERVAL_S = 1.0F; // 1 segundo
if (continue_time_accumulator_ >= CONTINUE_INTERVAL_S) {
continue_time_accumulator_ -= CONTINUE_INTERVAL_S;
decContinueCounter();
@@ -848,10 +844,10 @@ void Player::updateContinueCounter(float deltaTime) {
}
// Actualiza el contador de entrar nombre (time-based)
void Player::updateEnterNameCounter(float deltaTime) {
void Player::updateEnterNameCounter(float delta_time) {
if (playing_state_ == State::ENTERING_NAME || playing_state_ == State::ENTERING_NAME_GAME_COMPLETED) {
name_entry_time_accumulator_ += deltaTime;
constexpr float NAME_ENTRY_INTERVAL_S = 1.0f; // 1 segundo
name_entry_time_accumulator_ += delta_time;
constexpr float NAME_ENTRY_INTERVAL_S = 1.0F; // 1 segundo
if (name_entry_time_accumulator_ >= NAME_ENTRY_INTERVAL_S) {
name_entry_time_accumulator_ -= NAME_ENTRY_INTERVAL_S;
decNameEntryCounter();
@@ -860,10 +856,10 @@ void Player::updateEnterNameCounter(float deltaTime) {
}
// Actualiza el estado de SHOWING_NAME (time-based)
void Player::updateShowingName(float deltaTime) {
void Player::updateShowingName(float delta_time) {
if (playing_state_ == State::SHOWING_NAME) {
showing_name_time_accumulator_ += deltaTime;
constexpr float SHOWING_NAME_DURATION_S = 5.0f; // 5 segundos
showing_name_time_accumulator_ += delta_time;
constexpr float SHOWING_NAME_DURATION_S = 5.0F; // 5 segundos
if (showing_name_time_accumulator_ >= SHOWING_NAME_DURATION_S) {
game_completed_ ? setPlayingState(State::LEAVING_SCREEN) : setPlayingState(State::CONTINUE);
}
@@ -872,7 +868,7 @@ void Player::updateShowingName(float deltaTime) {
// Decrementa el contador de continuar
void Player::decContinueCounter() {
continue_time_accumulator_ = 0.0f; // Reset time accumulator
continue_time_accumulator_ = 0.0F; // Reset time accumulator
--continue_counter_;
if (continue_counter_ < 0) {
setPlayingState(State::CONTINUE_TIME_OUT);
@@ -883,16 +879,16 @@ void Player::decContinueCounter() {
// Decrementa el contador de entrar nombre
void Player::decNameEntryCounter() {
name_entry_time_accumulator_ = 0.0f; // Reset time accumulator
name_entry_time_accumulator_ = 0.0F; // Reset time accumulator
// Incrementa acumuladores de tiempo (1 segundo)
name_entry_idle_time_accumulator_ += 1.0f;
name_entry_total_time_accumulator_ += 1.0f;
name_entry_idle_time_accumulator_ += 1.0F;
name_entry_total_time_accumulator_ += 1.0F;
if ((name_entry_total_time_accumulator_ >= param.game.name_entry_total_time) ||
(name_entry_idle_time_accumulator_ >= param.game.name_entry_idle_time)) {
name_entry_total_time_accumulator_ = 0.0f;
name_entry_idle_time_accumulator_ = 0.0f;
name_entry_total_time_accumulator_ = 0.0F;
name_entry_idle_time_accumulator_ = 0.0F;
if (playing_state_ == State::ENTERING_NAME) {
last_enter_name_ = getRecordName();
setPlayingState(State::SHOWING_NAME);
@@ -977,15 +973,15 @@ void Player::addCredit() {
// ========================================
// Método principal del sistema de disparo
void Player::updateFireSystem(float deltaTime) {
updateFunctionalLine(deltaTime); // Línea 1: CanFire
updateVisualLine(deltaTime); // Línea 2: Animaciones
void Player::updateFireSystem(float delta_time) {
updateFunctionalLine(delta_time); // Línea 1: CanFire
updateVisualLine(delta_time); // Línea 2: Animaciones
}
// LÍNEA 1: Sistema Funcional (CanFire)
void Player::updateFunctionalLine(float deltaTime) {
void Player::updateFunctionalLine(float delta_time) {
if (fire_cooldown_timer_ > 0) {
fire_cooldown_timer_ -= deltaTime;
fire_cooldown_timer_ -= delta_time;
can_fire_new_system_ = false;
} else {
fire_cooldown_timer_ = 0; // Evitar valores negativos
@@ -994,12 +990,12 @@ void Player::updateFunctionalLine(float deltaTime) {
}
// LÍNEA 2: Sistema Visual (Animaciones)
void Player::updateVisualLine(float deltaTime) {
void Player::updateVisualLine(float delta_time) {
if (visual_fire_state_ == VisualFireState::NORMAL) {
return; // No hay temporizador activo en estado NORMAL
}
visual_state_timer_ -= deltaTime;
visual_state_timer_ -= delta_time;
switch (visual_fire_state_) {
case VisualFireState::AIMING:
@@ -1029,7 +1025,7 @@ void Player::updateVisualLine(float deltaTime) {
// Inicia un disparo en ambas líneas
void Player::startFiringSystem(int cooldown_frames) {
// LÍNEA 1: Inicia cooldown funcional
fire_cooldown_timer_ = static_cast<float>(cooldown_frames) / 60.0f; // Convertir frames a segundos
fire_cooldown_timer_ = static_cast<float>(cooldown_frames) / 60.0F; // Convertir frames a segundos
can_fire_new_system_ = false;
// LÍNEA 2: Resetea completamente el estado visual