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

@@ -52,7 +52,7 @@ Scoreboard::Scoreboard()
continue_counter_.at(i) = 0;
carousel_prev_index_.at(i) = -1; // Inicializar a -1 para detectar primera inicialización
enter_name_ref_.at(i) = nullptr;
text_slide_offset_.at(i) = 0.0f;
text_slide_offset_.at(i) = 0.0F;
}
panel_.at(static_cast<size_t>(Id::LEFT)).mode = Mode::SCORE;
@@ -96,12 +96,12 @@ Scoreboard::~Scoreboard() {
// Configura la animación del carrusel
void Scoreboard::setCarouselAnimation(Id id, int selected_index, EnterName* enter_name_ptr) {
size_t idx = static_cast<size_t>(id);
auto idx = static_cast<size_t>(id);
// Guardar referencia a EnterName
enter_name_ref_.at(idx) = enter_name_ptr;
if (!enter_name_ptr || selected_index < 0) {
if ((enter_name_ptr == nullptr) || selected_index < 0) {
return;
}
@@ -144,7 +144,7 @@ void Scoreboard::setCarouselAnimation(Id id, int selected_index, EnterName* ente
// Establece el modo del panel y gestiona transiciones
void Scoreboard::setMode(Id id, Mode mode) {
size_t idx = static_cast<size_t>(id);
auto idx = static_cast<size_t>(id);
// Cambiar el modo
panel_.at(idx).mode = mode;
@@ -153,7 +153,7 @@ void Scoreboard::setMode(Id id, Mode mode) {
switch (mode) {
case Mode::SCORE_TO_ENTER_NAME:
// Iniciar animación de transición SCORE → ENTER_NAME
text_slide_offset_.at(idx) = 0.0f;
text_slide_offset_.at(idx) = 0.0F;
// Resetear carrusel para que se inicialice correctamente en ENTER_NAME
if (carousel_prev_index_.at(idx) != -1) {
carousel_prev_index_.at(idx) = -1;
@@ -166,17 +166,17 @@ void Scoreboard::setMode(Id id, Mode mode) {
if (carousel_prev_index_.at(idx) != -1) {
carousel_prev_index_.at(idx) = -1;
}
text_slide_offset_.at(idx) = 0.0f;
text_slide_offset_.at(idx) = 0.0F;
break;
case Mode::ENTER_TO_SHOW_NAME:
// Iniciar animación de transición ENTER_NAME → SHOW_NAME
text_slide_offset_.at(idx) = 0.0f;
text_slide_offset_.at(idx) = 0.0F;
break;
case Mode::SHOW_NAME:
// Asegurar que la animación está completa
text_slide_offset_.at(idx) = 1.0f;
text_slide_offset_.at(idx) = 1.0F;
break;
// Otros modos no requieren inicialización especial
@@ -216,17 +216,17 @@ void Scoreboard::updateNameColorIndex() {
}
// Actualiza la animación del carrusel
void Scoreboard::updateCarouselAnimation(float deltaTime) {
constexpr float CAROUSEL_SPEED = 8.0f; // Posiciones por segundo
void Scoreboard::updateCarouselAnimation(float delta_time) {
constexpr float CAROUSEL_SPEED = 8.0F; // Posiciones por segundo
for (size_t i = 0; i < carousel_position_.size(); ++i) {
// Solo animar si no hemos llegado al target
if (std::abs(carousel_position_.at(i) - carousel_target_.at(i)) > 0.01f) {
if (std::abs(carousel_position_.at(i) - carousel_target_.at(i)) > 0.01F) {
// Determinar dirección
float direction = (carousel_target_.at(i) > carousel_position_.at(i)) ? 1.0f : -1.0f;
float direction = (carousel_target_.at(i) > carousel_position_.at(i)) ? 1.0F : -1.0F;
// Calcular movimiento
float movement = CAROUSEL_SPEED * deltaTime * direction;
float movement = CAROUSEL_SPEED * delta_time * direction;
// Mover, pero no sobrepasar el target
float new_position = carousel_position_.at(i) + movement;
@@ -245,24 +245,24 @@ void Scoreboard::updateCarouselAnimation(float deltaTime) {
}
// Actualiza las animaciones de deslizamiento de texto
void Scoreboard::updateTextSlideAnimation(float deltaTime) {
void Scoreboard::updateTextSlideAnimation(float delta_time) {
for (size_t i = 0; i < static_cast<size_t>(Id::SIZE); ++i) {
Mode current_mode = panel_.at(i).mode;
if (current_mode == Mode::SCORE_TO_ENTER_NAME) {
// Incrementar progreso de animación SCORE → ENTER_NAME (0.0 a 1.0)
text_slide_offset_.at(i) += deltaTime / TEXT_SLIDE_DURATION;
text_slide_offset_.at(i) += delta_time / TEXT_SLIDE_DURATION;
// Terminar animación y cambiar a ENTER_NAME cuando se complete
if (text_slide_offset_.at(i) >= 1.0f) {
if (text_slide_offset_.at(i) >= 1.0F) {
setMode(static_cast<Id>(i), Mode::ENTER_NAME);
}
} else if (current_mode == Mode::ENTER_TO_SHOW_NAME) {
// Incrementar progreso de animación ENTER_NAME → SHOW_NAME (0.0 a 1.0)
text_slide_offset_.at(i) += deltaTime / TEXT_SLIDE_DURATION;
text_slide_offset_.at(i) += delta_time / TEXT_SLIDE_DURATION;
// Terminar animación y cambiar a SHOW_NAME cuando se complete
if (text_slide_offset_.at(i) >= 1.0f) {
if (text_slide_offset_.at(i) >= 1.0F) {
setMode(static_cast<Id>(i), Mode::SHOW_NAME);
}
}
@@ -270,11 +270,11 @@ void Scoreboard::updateTextSlideAnimation(float deltaTime) {
}
// Actualiza la lógica del marcador
void Scoreboard::update(float deltaTime) {
void Scoreboard::update(float delta_time) {
updateTimeCounter();
updateNameColorIndex();
updateCarouselAnimation(deltaTime);
updateTextSlideAnimation(deltaTime);
updateCarouselAnimation(delta_time);
updateTextSlideAnimation(delta_time);
fillBackgroundTexture(); // Renderizar DESPUÉS de actualizar
}
@@ -438,30 +438,30 @@ void Scoreboard::renderContinueMode(size_t panel_index) {
void Scoreboard::renderScoreToEnterNameMode(size_t panel_index) {
// Calcular progreso suavizado de la animación (0.0 a 1.0)
const float t = static_cast<float>(easeInOutSine(text_slide_offset_.at(panel_index)));
const auto T = static_cast<float>(easeInOutSine(text_slide_offset_.at(panel_index)));
// Calcular desplazamientos reales entre slots (no son exactamente ROW_SIZE)
const float delta_1_to_2 = slot4_2_.y - slot4_1_.y; // Diferencia real entre ROW1 y ROW2
const float delta_2_to_3 = slot4_3_.y - slot4_2_.y; // Diferencia real entre ROW2 y ROW3
const float delta_3_to_4 = slot4_4_.y - slot4_3_.y; // Diferencia real entre ROW3 y ROW4
const float DELTA_1_TO_2 = slot4_2_.y - slot4_1_.y; // Diferencia real entre ROW1 y ROW2
const float DELTA_2_TO_3 = slot4_3_.y - slot4_2_.y; // Diferencia real entre ROW2 y ROW3
const float DELTA_3_TO_4 = slot4_4_.y - slot4_3_.y; // Diferencia real entre ROW3 y ROW4
// ========== Texto que SALE hacia arriba ==========
// name_ (sale desde ROW1 hacia arriba)
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y - t * delta_1_to_2, name_.at(panel_index), 1, text_color1_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y - (T * DELTA_1_TO_2), name_.at(panel_index), 1, text_color1_);
// ========== Textos que SE MUEVEN hacia arriba ==========
// score_ (se mueve de ROW2 a ROW1)
text_->writeDX(Text::CENTER | Text::COLOR, slot4_2_.x, slot4_2_.y - t * delta_1_to_2, updateScoreText(score_.at(panel_index)), 1, text_color2_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_2_.x, slot4_2_.y - (T * DELTA_1_TO_2), updateScoreText(score_.at(panel_index)), 1, text_color2_);
// "ENTER NAME" (se mueve de ROW3 a ROW2)
text_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y - t * delta_2_to_3, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y - (T * DELTA_2_TO_3), Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
// enter_name_ (se mueve de ROW4 a ROW3)
text_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y - t * delta_3_to_4, enter_name_.at(panel_index), 1, text_color2_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y - (T * DELTA_3_TO_4), enter_name_.at(panel_index), 1, text_color2_);
// ========== Elemento que ENTRA desde abajo ==========
// CARRUSEL (entra desde debajo de ROW4 hacia ROW4)
renderCarousel(panel_index, slot4_4_.x, static_cast<int>(slot4_4_.y + delta_3_to_4 - t * delta_3_to_4));
renderCarousel(panel_index, slot4_4_.x, static_cast<int>(slot4_4_.y + DELTA_3_TO_4 - (T * DELTA_3_TO_4)));
}
void Scoreboard::renderEnterNameMode(size_t panel_index) {
@@ -491,31 +491,31 @@ void Scoreboard::renderEnterNameMode(size_t panel_index) {
void Scoreboard::renderEnterToShowNameMode(size_t panel_index) {
// Calcular progreso suavizado de la animación (0.0 a 1.0)
const float t = static_cast<float>(easeInOutSine(text_slide_offset_.at(panel_index)));
const auto T = static_cast<float>(easeInOutSine(text_slide_offset_.at(panel_index)));
// Calcular desplazamientos reales entre slots (no son exactamente ROW_SIZE)
const float delta_1_to_2 = slot4_2_.y - slot4_1_.y; // Diferencia real entre ROW1 y ROW2
const float delta_2_to_3 = slot4_3_.y - slot4_2_.y; // Diferencia real entre ROW2 y ROW3
const float delta_3_to_4 = slot4_4_.y - slot4_3_.y; // Diferencia real entre ROW3 y ROW4
const float DELTA_1_TO_2 = slot4_2_.y - slot4_1_.y; // Diferencia real entre ROW1 y ROW2
const float DELTA_2_TO_3 = slot4_3_.y - slot4_2_.y; // Diferencia real entre ROW2 y ROW3
const float DELTA_3_TO_4 = slot4_4_.y - slot4_3_.y; // Diferencia real entre ROW3 y ROW4
// ========== Texto que ENTRA desde arriba ==========
// name_ (entra desde arriba hacia ROW1)
// Debe venir desde donde estaría ROW0, que está a delta_1_to_2 píxeles arriba de ROW1
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y + t * delta_1_to_2 - delta_1_to_2, name_.at(panel_index), 1, text_color1_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y + (T * DELTA_1_TO_2) - DELTA_1_TO_2, name_.at(panel_index), 1, text_color1_);
// ========== Textos que SE MUEVEN (renderizar UNA sola vez) ==========
// SCORE (se mueve de ROW1 a ROW2)
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y + t * delta_1_to_2, updateScoreText(score_.at(panel_index)), 1, text_color2_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y + (T * DELTA_1_TO_2), updateScoreText(score_.at(panel_index)), 1, text_color2_);
// "ENTER NAME" (se mueve de ROW2 a ROW3)
text_->writeDX(Text::CENTER | Text::COLOR, slot4_2_.x, slot4_2_.y + t * delta_2_to_3, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_2_.x, slot4_2_.y + (T * DELTA_2_TO_3), Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
// enter_name_ (se mueve de ROW3 a ROW4)
text_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y + t * delta_3_to_4, enter_name_.at(panel_index), 1, text_color2_);
text_->writeDX(Text::CENTER | Text::COLOR, slot4_3_.x, slot4_3_.y + (T * DELTA_3_TO_4), enter_name_.at(panel_index), 1, text_color2_);
// ========== Elemento que SALE hacia abajo ==========
// CARRUSEL (sale desde ROW4 hacia abajo, fuera de pantalla)
renderCarousel(panel_index, slot4_4_.x, static_cast<int>(slot4_4_.y + t * delta_3_to_4));
renderCarousel(panel_index, slot4_4_.x, static_cast<int>(slot4_4_.y + (T * DELTA_3_TO_4)));
}
void Scoreboard::renderShowNameMode(size_t panel_index) {
@@ -652,7 +652,7 @@ void Scoreboard::renderSeparator() {
void Scoreboard::renderCarousel(size_t panel_index, int center_x, int y) {
// Obtener referencia a EnterName
EnterName* enter_name = enter_name_ref_.at(panel_index);
if (!enter_name) {
if (enter_name == nullptr) {
return;
}
@@ -669,7 +669,7 @@ void Scoreboard::renderCarousel(size_t panel_index, int center_x, int y) {
constexpr int HALF_VISIBLE = CAROUSEL_VISIBLE_LETTERS / 2; // 4
// Posición flotante actual del carrusel (índice en character_list_)
const float carousel_pos = carousel_position_.at(panel_index);
const float CAROUSEL_POS = carousel_position_.at(panel_index);
// Calcular ancho promedio de una letra (asumimos ancho uniforme)
std::string sample_char(1, char_list[0]);
@@ -677,58 +677,58 @@ void Scoreboard::renderCarousel(size_t panel_index, int center_x, int y) {
const int CHAR_STEP = AVG_CHAR_WIDTH + EXTRA_SPACING;
// Calcular offset de píxeles basado en la parte fraccionaria de carousel_pos
const float fractional_offset = carousel_pos - std::floor(carousel_pos);
const int pixel_offset = static_cast<int>(fractional_offset * CHAR_STEP);
const float FRACTIONAL_OFFSET = CAROUSEL_POS - std::floor(CAROUSEL_POS);
const int PIXEL_OFFSET = static_cast<int>(FRACTIONAL_OFFSET * CHAR_STEP);
// Índice base en character_list_ (centro del carrusel)
const int base_index = static_cast<int>(std::floor(carousel_pos));
const int char_list_size = static_cast<int>(char_list.size());
const int BASE_INDEX = static_cast<int>(std::floor(CAROUSEL_POS));
const int CHAR_LIST_SIZE = static_cast<int>(char_list.size());
// Calcular posición X inicial (centrar el conjunto de 9 letras)
int start_x = center_x - (HALF_VISIBLE * CHAR_STEP) - (AVG_CHAR_WIDTH / 2) - pixel_offset;
int start_x = center_x - (HALF_VISIBLE * CHAR_STEP) - (AVG_CHAR_WIDTH / 2) - PIXEL_OFFSET;
// Renderizar las 9 letras visibles
for (int i = -HALF_VISIBLE; i <= HALF_VISIBLE; ++i) {
// Índice real en character_list_ (con wrap-around circular)
int char_index = base_index + i;
int char_index = BASE_INDEX + i;
// Wrap-around circular
char_index = char_index % char_list_size;
char_index = char_index % CHAR_LIST_SIZE;
if (char_index < 0) {
char_index += char_list_size;
char_index += CHAR_LIST_SIZE;
}
// Obtener el carácter directamente de character_list_
std::string single_char(1, char_list[char_index]);
// Calcular distancia flotante al centro visual basada en posición real del carácter
float distance_from_center = std::abs(static_cast<float>(char_index) - carousel_pos);
float distance_from_center = std::abs(static_cast<float>(char_index) - CAROUSEL_POS);
// Manejar wrap-around circular: elegir el camino más corto
if (distance_from_center > static_cast<float>(char_list_size) / 2.0f) {
distance_from_center = static_cast<float>(char_list_size) - distance_from_center;
if (distance_from_center > static_cast<float>(CHAR_LIST_SIZE) / 2.0F) {
distance_from_center = static_cast<float>(CHAR_LIST_SIZE) - distance_from_center;
}
// Calcular color con LERP dinámico continuo
Color letter_color;
if (distance_from_center < 0.5f) {
if (distance_from_center < 0.5F) {
// Letra cerca del centro: LERP hacia animated_color_
// distance_from_center va de 0.0 (centro exacto) a 0.5 (borde)
float lerp_to_animated = distance_from_center / 0.5f; // 0.0 a 1.0
float lerp_to_animated = distance_from_center / 0.5F; // 0.0 a 1.0
letter_color = animated_color_.LERP(text_color1_, lerp_to_animated);
} else {
// Letras alejadas: LERP hacia color_ (fade out)
float base_lerp = (distance_from_center - 0.5f) / (HALF_VISIBLE - 0.5f);
base_lerp = std::min(base_lerp, 1.0f);
const float LERP_FACTOR = base_lerp * 0.85f;
float base_lerp = (distance_from_center - 0.5F) / (HALF_VISIBLE - 0.5F);
base_lerp = std::min(base_lerp, 1.0F);
const float LERP_FACTOR = base_lerp * 0.85F;
letter_color = text_color1_.LERP(color_, LERP_FACTOR);
}
// Calcular posición X de esta letra
const int letter_x = start_x + (i + HALF_VISIBLE) * CHAR_STEP;
const int LETTER_X = start_x + ((i + HALF_VISIBLE) * CHAR_STEP);
// Pintar la letra
text_->writeDX(Text::COLOR, letter_x, y, single_char, 1, letter_color);
text_->writeDX(Text::COLOR, LETTER_X, y, single_char, 1, letter_color);
}
}