Compare commits

...

3 Commits

Author SHA1 Message Date
88d814f371 Visualment, el carrusel ja salta al ultim caracter (instantani)
Si no hi ha lletres per a borrar, no fa roidet
2025-10-22 18:47:42 +02:00
b933ceee63 Traslladada logica de clavar nom de game a player
Si no caben mes lletres, salta a l'ultim caracter i bloqueja el carrusel
2025-10-22 18:36:32 +02:00
75ccddbaa1 style: ja hi ha un caracter per acabar de posar el nom 2025-10-22 18:17:58 +02:00
6 changed files with 89 additions and 69 deletions

View File

@@ -44,7 +44,7 @@ Director::Director(int argc, std::span<char*> argv) {
Section::name = Section::Name::GAME; Section::name = Section::Name::GAME;
Section::options = Section::Options::GAME_PLAY_1P; Section::options = Section::Options::GAME_PLAY_1P;
#elif _DEBUG #elif _DEBUG
Section::name = Section::Name::HI_SCORE_TABLE; Section::name = Section::Name::GAME;
Section::options = Section::Options::GAME_PLAY_1P; Section::options = Section::Options::GAME_PLAY_1P;
#else // NORMAL GAME #else // NORMAL GAME
Section::name = Section::Name::LOGO; Section::name = Section::Name::LOGO;

View File

@@ -17,24 +17,31 @@ void EnterName::init(const std::string& name) {
// Incrementa el índice del carácter seleccionado // Incrementa el índice del carácter seleccionado
void EnterName::incIndex() { void EnterName::incIndex() {
++selected_index_; ++selected_index_;
if (selected_index_ >= static_cast<int>(character_list_.size())) { if (selected_index_ >= character_list_.size()) {
selected_index_ = 0; selected_index_ = 0;
} }
} }
// Decrementa el índice del carácter seleccionado // Decrementa el índice del carácter seleccionado
void EnterName::decIndex() { void EnterName::decIndex() {
--selected_index_; if (selected_index_ == 0) {
if (selected_index_ < 0) {
selected_index_ = character_list_.size() - 1; selected_index_ = character_list_.size() - 1;
} else {
--selected_index_;
} }
} }
// Añade el carácter seleccionado al nombre // Añade el carácter seleccionado al nombre
void EnterName::addCharacter() { void EnterName::addCharacter() {
// Si no es el ultimo caracter, lo añade
if (name_.length() < MAX_NAME_SIZE) { if (name_.length() < MAX_NAME_SIZE) {
name_.push_back(character_list_[selected_index_]); name_.push_back(character_list_[selected_index_]);
} }
// Si el nombre está completo, cambia el caracter seleccionado a el caracter de finalizar
if (nameIsFull()) {
forceEndCharSelected();
}
} }
// Elimina el último carácter del nombre // Elimina el último carácter del nombre

View File

@@ -26,13 +26,17 @@ class EnterName {
[[nodiscard]] auto getCarousel(int size) const -> std::string; // Devuelve el carrusel de caracteres (size debe ser impar) [[nodiscard]] auto getCarousel(int size) const -> std::string; // Devuelve el carrusel de caracteres (size debe ser impar)
[[nodiscard]] auto getSelectedIndex() const -> int { return selected_index_; } // Obtiene el índice del carácter seleccionado [[nodiscard]] auto getSelectedIndex() const -> int { return selected_index_; } // Obtiene el índice del carácter seleccionado
[[nodiscard]] auto getCharacterList() const -> const std::string& { return character_list_; } // Obtiene la lista completa de caracteres [[nodiscard]] auto getCharacterList() const -> const std::string& { return character_list_; } // Obtiene la lista completa de caracteres
[[nodiscard]] auto nameIsFull() const -> bool { return name_.size() == MAX_NAME_SIZE; } // Informa de si el nombre ha alcanzado su limite
[[nodiscard]] auto nameIsEmpty() const -> bool { return name_.empty(); } // Informa de si el nombre está vacío
[[nodiscard]] auto endCharSelected() const -> bool { return selected_index_ == character_list_.size() - 1; } // Informa de si está seleccionado el caracter de terminar
private: private:
// --- Variables de estado --- // --- Variables de estado ---
std::string character_list_; // Lista de caracteres permitidos std::string character_list_; // Lista de caracteres permitidos
std::string name_; // Nombre en proceso std::string name_; // Nombre en proceso
int selected_index_ = 0; // Índice del carácter seleccionado en "character_list_" size_t selected_index_ = 0; // Índice del carácter seleccionado en "character_list_"
[[nodiscard]] auto sanitizeName(const std::string& name) const -> std::string; // Valida y limpia el nombre [[nodiscard]] auto sanitizeName(const std::string& name) const -> std::string; // Valida y limpia el nombre
static auto getRandomName() -> std::string; // Devuelve un nombre al azar static auto getRandomName() -> std::string; // Devuelve un nombre al azar
void forceEndCharSelected() { selected_index_ = character_list_.size() - 1; } // Establece como seleccionado el caracter de terminar
}; };

View File

@@ -78,6 +78,7 @@ void Player::setInput(Input::Action action) {
setInputPlaying(action); setInputPlaying(action);
break; break;
} }
case State::SHOWING_NAME:
case State::ENTERING_NAME: case State::ENTERING_NAME:
case State::ENTERING_NAME_GAME_COMPLETED: { case State::ENTERING_NAME_GAME_COMPLETED: {
setInputEnteringName(action); setInputEnteringName(action);
@@ -124,20 +125,50 @@ void Player::setInputPlaying(Input::Action action) {
// Procesa inputs para cuando está introduciendo el nombre // Procesa inputs para cuando está introduciendo el nombre
void Player::setInputEnteringName(Input::Action action) { void Player::setInputEnteringName(Input::Action action) {
switch (action) { switch (action) {
case Input::Action::FIRE_LEFT: case Input::Action::FIRE_LEFT: // Añade una letra
if (isShowingName()) {
passShowingName();
} else {
if (enter_name_->endCharSelected()) {
last_enter_name_ = getRecordName();
setPlayingState(Player::State::SHOWING_NAME);
playSound("name_input_accept.wav");
} else {
enter_name_->addCharacter(); enter_name_->addCharacter();
playSound("service_menu_select.wav");
}
}
break; break;
case Input::Action::FIRE_CENTER: case Input::Action::FIRE_CENTER: // Borra una letra
if (isShowingName()) {
passShowingName();
} else {
if (!enter_name_->nameIsEmpty()) {
enter_name_->removeLastCharacter(); enter_name_->removeLastCharacter();
playSound("service_menu_back.wav");
}
}
break; break;
case Input::Action::RIGHT: case Input::Action::RIGHT:
if (!enter_name_->nameIsFull()) {
enter_name_->incIndex(); enter_name_->incIndex();
playSound("service_menu_move.wav");
}
break; break;
case Input::Action::LEFT: case Input::Action::LEFT:
if (!enter_name_->nameIsFull()) {
enter_name_->decIndex(); enter_name_->decIndex();
playSound("service_menu_move.wav");
}
break; break;
case Input::Action::START: case Input::Action::START:
if (isShowingName()) {
passShowingName();
} else {
last_enter_name_ = getRecordName(); last_enter_name_ = getRecordName();
setPlayingState(Player::State::SHOWING_NAME);
playSound("name_input_accept.wav");
}
break; break;
default: default:
break; break;

View File

@@ -95,19 +95,18 @@ Scoreboard::~Scoreboard() {
} }
} }
// Configura la animación del carrusel
// Configura la animación del carrusel // Configura la animación del carrusel
void Scoreboard::setCarouselAnimation(Id id, int selected_index, EnterName* enter_name_ptr) { void Scoreboard::setCarouselAnimation(Id id, int selected_index, EnterName* enter_name_ptr) {
auto idx = static_cast<size_t>(id); auto idx = static_cast<size_t>(id);
// Guardar referencia a EnterName // Guardar referencia al objeto EnterName
enter_name_ref_.at(idx) = enter_name_ptr; enter_name_ref_.at(idx) = enter_name_ptr;
if ((enter_name_ptr == nullptr) || selected_index < 0) { if ((enter_name_ptr == nullptr) || selected_index < 0) {
return; return;
} }
// Primera inicialización: posicionar directamente sin animar // ===== Primera inicialización =====
if (carousel_prev_index_.at(idx) == -1) { if (carousel_prev_index_.at(idx) == -1) {
carousel_position_.at(idx) = static_cast<float>(selected_index); carousel_position_.at(idx) = static_cast<float>(selected_index);
carousel_target_.at(idx) = static_cast<float>(selected_index); carousel_target_.at(idx) = static_cast<float>(selected_index);
@@ -116,46 +115,43 @@ void Scoreboard::setCarouselAnimation(Id id, int selected_index, EnterName* ente
} }
int prev_index = carousel_prev_index_.at(idx); int prev_index = carousel_prev_index_.at(idx);
// Si el índice seleccionado no cambia, no hay nada que hacer
if (selected_index == prev_index) { if (selected_index == prev_index) {
return; // No hay cambio
}
// ===== Bloqueo: si aún está animando, ignorar nueva orden =====
if (std::abs(carousel_position_.at(idx) - carousel_target_.at(idx)) > 0.01f) {
return; return;
} }
// 🚫 BLOQUEO: si todavía hay una animación en curso, ignoramos el nuevo movimiento // ===== Calcular el salto =====
if (std::abs(carousel_position_.at(idx) - carousel_target_.at(idx)) > 0.01f) { int delta = selected_index - prev_index;
return; // Aún animando: no aceptar nuevo target hasta terminar
}
// ---- Animación completada → procesar el nuevo movimiento ----
int direction = selected_index - prev_index;
// Obtener tamaño de la lista para manejar wrap-around
const int LIST_SIZE = static_cast<int>(enter_name_ptr->getCharacterList().size()); const int LIST_SIZE = static_cast<int>(enter_name_ptr->getCharacterList().size());
// Manejar wrap-around circular // Ajustar para wrap-around circular (camino más corto)
if (direction > LIST_SIZE / 2) { if (delta > LIST_SIZE / 2) {
direction = -(LIST_SIZE - direction); // Wrap backward (ej: Z → A) delta -= LIST_SIZE;
} else if (direction < -LIST_SIZE / 2) { } else if (delta < -LIST_SIZE / 2) {
direction = LIST_SIZE + direction; // Wrap forward (ej: A → Z) delta += LIST_SIZE;
} }
// Normalizar dirección a -1 o +1 // ===== Diferenciar salto corto o largo =====
direction = (direction > 0) ? 1 : ((direction < 0) ? -1 : 0); if (std::abs(delta) > 2) {
// Salto grande → ir directo sin animación
if (direction != 0) { carousel_position_.at(idx) = static_cast<float>(selected_index);
// Asegurar que partimos de una posición alineada carousel_target_.at(idx) = static_cast<float>(selected_index);
} else {
// Salto corto → animación suave normal
carousel_position_.at(idx) = std::round(carousel_position_.at(idx)); carousel_position_.at(idx) = std::round(carousel_position_.at(idx));
carousel_target_.at(idx) = carousel_position_.at(idx) + static_cast<float>(delta);
// Actualizar el nuevo target relativo
carousel_target_.at(idx) = carousel_position_.at(idx) + static_cast<float>(direction);
// Guardar el nuevo índice seleccionado
carousel_prev_index_.at(idx) = selected_index;
} }
// Actualizar índice actual
carousel_prev_index_.at(idx) = selected_index;
} }
// Establece el modo del panel y gestiona transiciones // Establece el modo del panel y gestiona transiciones
void Scoreboard::setMode(Id id, Mode mode) { void Scoreboard::setMode(Id id, Mode mode) {
auto idx = static_cast<size_t>(id); auto idx = static_cast<size_t>(id);

View File

@@ -1438,46 +1438,28 @@ void Game::handlePlayerWaitingInput(const std::shared_ptr<Player>& player) {
// Procesa las entradas para la introducción del nombre del jugador. // Procesa las entradas para la introducción del nombre del jugador.
void Game::handleNameInput(const std::shared_ptr<Player>& player) { void Game::handleNameInput(const std::shared_ptr<Player>& player) {
if (input_->checkAction(Input::Action::FIRE_LEFT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) { if (input_->checkAction(Input::Action::FIRE_LEFT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
if (player->isShowingName()) {
player->passShowingName();
return;
}
player->setInput(Input::Action::FIRE_LEFT); player->setInput(Input::Action::FIRE_LEFT);
playSound("service_menu_select.wav");
return; return;
} }
if (input_->checkAction(Input::Action::FIRE_CENTER, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad()) || if (input_->checkAction(Input::Action::FIRE_CENTER, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad()) ||
input_->checkAction(Input::Action::FIRE_RIGHT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) { input_->checkAction(Input::Action::FIRE_RIGHT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
if (player->isShowingName()) {
player->passShowingName();
return;
}
player->setInput(Input::Action::FIRE_CENTER); player->setInput(Input::Action::FIRE_CENTER);
playSound("service_menu_back.wav");
return; return;
} }
if (input_->checkAction(Input::Action::LEFT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) { if (input_->checkAction(Input::Action::LEFT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
player->setInput(Input::Action::LEFT); player->setInput(Input::Action::LEFT);
playSound("service_menu_move.wav");
return; return;
} }
if (input_->checkAction(Input::Action::RIGHT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) { if (input_->checkAction(Input::Action::RIGHT, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
player->setInput(Input::Action::RIGHT); player->setInput(Input::Action::RIGHT);
playSound("service_menu_move.wav");
return; return;
} }
if (input_->checkAction(Input::Action::START, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) { if (input_->checkAction(Input::Action::START, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
if (player->isShowingName()) {
player->passShowingName();
return;
}
player->setInput(Input::Action::START); player->setInput(Input::Action::START);
player->setPlayingState(Player::State::SHOWING_NAME);
playSound("name_input_accept.wav");
updateHiScoreName(); updateHiScoreName();
} }
} }