From 5755947ff7217c28a454dd2f00cefa430340abf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Valor=20Mart=C3=ADnez?= Date: Wed, 5 Feb 2025 22:52:19 +0100 Subject: [PATCH] =?UTF-8?q?La=20tabla=20de=20puntuaci=C3=B3=20ja=20mostra?= =?UTF-8?q?=20amb=20altre=20color=20la=20puntuaci=C3=B3=20que=20s'acaba=20?= =?UTF-8?q?d'afegir=20fix:=20la=20tabla=20de=20punts=20no=20guardava=20a?= =?UTF-8?q?=20disc=20el=20estat=20de=201CC=20de=20cada=20entrada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/game.cpp | 16 +++-- source/game.h | 2 +- source/hiscore_table.cpp | 48 ++++++++++++- source/hiscore_table.h | 24 +++++-- source/manage_hiscore_table.cpp | 115 ++++++++++++++++++++++---------- source/manage_hiscore_table.h | 2 +- source/options.cpp | 1 + source/options.h | 16 +++-- source/player.cpp | 3 +- source/player.h | 3 +- source/screen.cpp | 11 ++- 11 files changed, 175 insertions(+), 66 deletions(-) diff --git a/source/game.cpp b/source/game.cpp index 7fdc5e5..abcac4f 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -1370,11 +1370,11 @@ void Game::pause(bool value) } // Añade una puntuación a la tabla de records -void Game::addScoreToScoreBoard(const std::string &name, int score, bool one_credit_continue) +void Game::addScoreToScoreBoard(const std::shared_ptr &player) { - const auto entry = HiScoreEntry(trim(name), score); + const auto entry = HiScoreEntry(trim(player->getRecordName()), player->getScore(), player->get1CC()); auto manager = std::make_unique(options.game.hi_score_table); - manager->add(entry); + options.game.last_hi_score_entry.at(player->getId() - 1) = manager->add(entry); manager->saveToFile(asset_->get("score.bin")); hi_score_.name = options.game.hi_score_table.front().name; } @@ -1627,6 +1627,7 @@ void Game::handlePlayerContinue(const std::shared_ptr &player) if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index)) { player->setPlayingState(PlayerState::PLAYING); + player->addCredit(); } // Disminuye el contador de continuación si se presiona cualquier botón de disparo. @@ -1634,7 +1635,10 @@ void Game::handlePlayerContinue(const std::shared_ptr &player) input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) || input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index)) { - player->decContinueCounter(); + if (player->getContinueCounter() < 8) + { + player->decContinueCounter(); + } } } @@ -1649,7 +1653,7 @@ void Game::handleNameInput(const std::shared_ptr &player) if (player->getRecordNamePos() == NAME_LENGHT - 1) { player->setInput(InputType::START); - addScoreToScoreBoard(player->getRecordName(), player->getScore(), player->get1CC()); + addScoreToScoreBoard(player); const auto state = player->getPlayingState(); player->setPlayingState(state == PlayerState::ENTERING_NAME ? PlayerState::CONTINUE : PlayerState::LEAVING_SCREEN); } @@ -1673,7 +1677,7 @@ void Game::handleNameInput(const std::shared_ptr &player) else if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index)) { player->setInput(InputType::START); - addScoreToScoreBoard(player->getRecordName(), player->getScore(), player->get1CC()); + addScoreToScoreBoard(player); const auto state = player->getPlayingState(); player->setPlayingState(state == PlayerState::ENTERING_NAME ? PlayerState::CONTINUE : PlayerState::LEAVING_SCREEN); } diff --git a/source/game.h b/source/game.h index cb7e1c2..5e688d1 100644 --- a/source/game.h +++ b/source/game.h @@ -311,7 +311,7 @@ private: void pause(bool value); // Añade una puntuación a la tabla de records - void addScoreToScoreBoard(const std::string &name, int score, bool one_credit_continue); + void addScoreToScoreBoard(const std::shared_ptr &player); // Saca del estado de GAME OVER al jugador si el otro está activo void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); diff --git a/source/hiscore_table.cpp b/source/hiscore_table.cpp index 14a9afc..1300c1b 100644 --- a/source/hiscore_table.cpp +++ b/source/hiscore_table.cpp @@ -44,6 +44,7 @@ HiScoreTable::HiScoreTable() SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); initFade(); initBackground(); + iniEntryColors(); createSprites(); } @@ -51,6 +52,7 @@ HiScoreTable::HiScoreTable() HiScoreTable::~HiScoreTable() { SDL_DestroyTexture(backbuffer_); + options.game.clear_last_hi_score_entries(); } // Actualiza las variables @@ -364,6 +366,8 @@ void HiScoreTable::updateSprites() { entry->update(); } + + glowEntryNames(); } // Inicializa el fade @@ -418,4 +422,46 @@ void HiScoreTable::initBackground() default: break; } -} \ No newline at end of file +} + +// Obtiene un color del vector de colores de entradas +Color HiScoreTable::getEntryColor(int counter_) +{ + int cycle_length = entry_colors_.size() * 2 - 2; // Esto es 6 en este caso + int n = counter_ % cycle_length; + + int index; + if (n < entry_colors_.size()) + { + index = n; // Avanza: 0,1,2,3 + } + else + { + index = 2 * (entry_colors_.size() - 1) - n; // Retrocede: 2,1 + } + + return entry_colors_[index]; +} + +// Inicializa los colores de las entradas +void HiScoreTable::iniEntryColors() +{ + entry_colors_.clear(); + entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(75)); + entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(50)); + entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(25)); + entry_colors_.emplace_back(background_fade_color_.getInverse()); +} + +// Hace brillar los nombres de la tabla de records +void HiScoreTable::glowEntryNames() +{ + const Color entry_color = getEntryColor(counter_ / 5); + for (const auto& entry_index : options.game.last_hi_score_entry) + { + if (entry_index != -1) + { + entry_names_.at(entry_index)->getTexture()->setColor(entry_color); + } + } +} diff --git a/source/hiscore_table.h b/source/hiscore_table.h index cd8828e..545bc5c 100644 --- a/source/hiscore_table.h +++ b/source/hiscore_table.h @@ -7,8 +7,8 @@ #include // Para string #include // Para vector #include "utils.h" -class Background; // lines 10-10 -class Fade; // lines 11-11 +class Background; // lines 10-10 +class Fade; // lines 11-11 class PathSprite; class Sprite; enum class FadeMode : Uint8; // lines 13-13 @@ -42,11 +42,12 @@ private: std::vector paths_; // Vector con los recorridos precalculados // Variables - Uint16 counter_ = 0; // Contador - Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa - SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla - FadeMode fade_mode_; // Modo de fade a utilizar - Color background_fade_color_; // Color de atenuación del fondo + Uint16 counter_ = 0; // Contador + Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa + SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla + FadeMode fade_mode_; // Modo de fade a utilizar + Color background_fade_color_; // Color de atenuación del fondo + std::vector entry_colors_; // Colores para destacar las entradas en la tabla // Actualiza las variables void update(); @@ -84,6 +85,15 @@ private: // Inicializa el fondo void initBackground(); + // Obtiene un color del vector de colores de entradas + Color getEntryColor(int counter_); + + // Inicializa los colores de las entradas + void iniEntryColors(); + + // Hace brillar los nombres de la tabla de records + void glowEntryNames(); + public: // Constructor HiScoreTable(); diff --git a/source/manage_hiscore_table.cpp b/source/manage_hiscore_table.cpp index 8aaa07f..d421b3d 100644 --- a/source/manage_hiscore_table.cpp +++ b/source/manage_hiscore_table.cpp @@ -13,7 +13,7 @@ void ManageHiScoreTable::clear() // Añade 10 entradas predefinidas table_.push_back(HiScoreEntry("BRY", 1000000)); - table_.push_back(HiScoreEntry("USUFON", 500000, true)); + table_.push_back(HiScoreEntry("USUFON", 500000)); table_.push_back(HiScoreEntry("GLUCAS", 100000)); table_.push_back(HiScoreEntry("PDLGAT", 50000)); table_.push_back(HiScoreEntry("PARRAB", 10000)); @@ -27,7 +27,7 @@ void ManageHiScoreTable::clear() } // Añade un elemento a la tabla -void ManageHiScoreTable::add(HiScoreEntry entry) +int ManageHiScoreTable::add(const HiScoreEntry &entry) { // Añade la entrada a la tabla table_.push_back(entry); @@ -35,8 +35,32 @@ void ManageHiScoreTable::add(HiScoreEntry entry) // Ordena la tabla sort(); + // Encontrar la posición del nuevo elemento + auto it = std::find_if(table_.begin(), table_.end(), [&](const HiScoreEntry &e) + { return e.name == entry.name && + e.score == entry.score && + e.one_credit_complete == entry.one_credit_complete; }); + + int position = -1; + if (it != table_.end()) + { + position = std::distance(table_.begin(), it); + } + // Deja solo las 10 primeras entradas - table_.resize(10); + if (table_.size() > 10) + { + table_.resize(10); + + // Si el nuevo elemento quedó fuera del top 10 + if (position >= 10) + { + position = -1; // No entró en el top 10 + } + } + + // Devuelve la posición + return position; } // Ordena la tabla @@ -50,52 +74,55 @@ void ManageHiScoreTable::sort() std::sort(table_.begin(), table_.end(), scoreDescendingComparator); } -// Carga la tabla con los datos de un fichero +// Carga la tabla desde un fichero bool ManageHiScoreTable::loadFromFile(const std::string &file_path) { clear(); auto success = true; - auto file = SDL_RWFromFile(file_path.c_str(), "r+b"); + auto file = SDL_RWFromFile(file_path.c_str(), "rb"); if (file) { - std::cout << "Reading file: " << getFileName(file_path) << std::endl; + table_.clear(); // Limpia la tabla actual - for (auto &entry : table_) + // Lee el número de entradas en la tabla + int tableSize = 0; + SDL_RWread(file, &tableSize, sizeof(int), 1); + + // Lee los datos de cada entrada + for (int i = 0; i < tableSize; ++i) { + HiScoreEntry entry; + + // Lee la puntuación + SDL_RWread(file, &entry.score, sizeof(int), 1); + + // Lee el tamaño del nombre y luego el nombre int nameSize = 0; - - if (SDL_RWread(file, &entry.score, sizeof(int), 1) == 0) - { - success = false; - break; - } - - if (SDL_RWread(file, &nameSize, sizeof(int), 1) == 0) - { - success = false; - break; - } + SDL_RWread(file, &nameSize, sizeof(int), 1); std::vector nameBuffer(nameSize + 1); - if (SDL_RWread(file, nameBuffer.data(), sizeof(char) * nameSize, 1) == 0) - { - success = false; - break; - } - - nameBuffer[nameSize] = '\0'; + SDL_RWread(file, nameBuffer.data(), nameSize, 1); + nameBuffer[nameSize] = '\0'; // Asegurar el fin de la cadena entry.name = std::string(nameBuffer.data()); + + // Lee el valor de one_credit_complete + int occValue = 0; + SDL_RWread(file, &occValue, sizeof(int), 1); + entry.one_credit_complete = (occValue != 0); + + // Añade la entrada a la tabla + table_.push_back(entry); } + std::cout << "Reading file: " << getFileName(file_path) << std::endl; SDL_RWclose(file); } - - if (!success) + else { - clear(); + std::cout << "Error: Unable to load " << getFileName(file_path) << " file! " << SDL_GetError() << std::endl; + success = false; } - return success; } @@ -107,21 +134,35 @@ bool ManageHiScoreTable::saveToFile(const std::string &file_path) if (file) { - // Guarda los datos - for (int i = 0; i < (int)table_.size(); ++i) + // Guarda el número de entradas en la tabla + int tableSize = static_cast(table_.size()); + SDL_RWwrite(file, &tableSize, sizeof(int), 1); + + // Guarda los datos de cada entrada + for (int i = 0; i < tableSize; ++i) { - SDL_RWwrite(file, &table_.at(i).score, sizeof(int), 1); - const int nameSize = (int)table_.at(i).name.size(); + const HiScoreEntry& entry = table_.at(i); + + // Guarda la puntuación + SDL_RWwrite(file, &entry.score, sizeof(int), 1); + + // Guarda el tamaño del nombre y luego el nombre + int nameSize = static_cast(entry.name.size()); SDL_RWwrite(file, &nameSize, sizeof(int), 1); - SDL_RWwrite(file, table_.at(i).name.c_str(), nameSize, 1); + SDL_RWwrite(file, entry.name.c_str(), nameSize, 1); + + // Guarda el valor de one_credit_complete como un entero (0 o 1) + int occValue = entry.one_credit_complete ? 1 : 0; + SDL_RWwrite(file, &occValue, sizeof(int), 1); } - std::cout << "Writing file: " << getFileName(file_path).c_str() << std::endl; + std::cout << "Writing file: " << getFileName(file_path) << std::endl; SDL_RWclose(file); } else { - std::cout << "Error: Unable to save " << getFileName(file_path).c_str() << " file! " << SDL_GetError() << std::endl; + std::cout << "Error: Unable to save " << getFileName(file_path) << " file! " << SDL_GetError() << std::endl; + success = false; } return success; } \ No newline at end of file diff --git a/source/manage_hiscore_table.h b/source/manage_hiscore_table.h index 17ef2ff..d339b32 100644 --- a/source/manage_hiscore_table.h +++ b/source/manage_hiscore_table.h @@ -45,7 +45,7 @@ public: void clear(); // Añade un elemento a la tabla - void add(HiScoreEntry entry); + int add(const HiScoreEntry& entry); // Carga la tabla con los datos de un fichero bool loadFromFile(const std::string &file_path); diff --git a/source/options.cpp b/source/options.cpp index 64259cb..c7f1910 100644 --- a/source/options.cpp +++ b/source/options.cpp @@ -44,6 +44,7 @@ void initOptions() options.game.difficulty = GameDifficulty::NORMAL; options.game.language = lang::Code::ba_BA; options.game.autofire = true; + options.game.clear_last_hi_score_entries(); // Opciones de control options.controllers.clear(); diff --git a/source/options.h b/source/options.h index fb6ad7e..bdcb54b 100644 --- a/source/options.h +++ b/source/options.h @@ -64,10 +64,18 @@ struct OptionsAudio // Estructura para las opciones del juego struct OptionsGame { - GameDifficulty difficulty; // Dificultad del juego - lang::Code language; // Idioma usado en el juego - bool autofire; // Indica si el jugador ha de pulsar repetidamente para disparar o basta con mantener pulsado - std::vector hi_score_table; // Tabla con las mejores puntuaciones + GameDifficulty difficulty; // Dificultad del juego + lang::Code language; // Idioma usado en el juego + bool autofire; // Indicador de autofire + std::vector hi_score_table; // Tabla de mejores puntuaciones + std::vector last_hi_score_entry = { -1, -1 }; // Inicialización directa con dos elementos en -1 + + // Método para reiniciar las últimas entradas de puntuación + void clear_last_hi_score_entries() + { + last_hi_score_entry[0] = -1; + last_hi_score_entry[1] = -1; + } }; // Estructura para los controles del juego diff --git a/source/player.cpp b/source/player.cpp index 47f713e..5443050 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -59,7 +59,6 @@ void Player::init() score_multiplier_ = 1.0f; cool_down_ = 10; enter_name_->init(); - ++credits_used_; // Establece la posición del sprite player_sprite_->clear(); @@ -531,7 +530,7 @@ void Player::setPlayingState(PlayerState state) // Activa la animación de morir player_sprite_->setAccelY(0.2f); player_sprite_->setVelY(-6.6f); - rand() % 2 == 0 ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f); + (rand() % 2 == 0) ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f); break; } case PlayerState::DIED: diff --git a/source/player.h b/source/player.h index 10ae8e8..9436468 100644 --- a/source/player.h +++ b/source/player.h @@ -94,7 +94,7 @@ private: Uint32 enter_name_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente bool game_completed_ = false; // Indica si ha completado el juego - int credits_used_ = 0; // Indica el numero de veces que ha continuado + int credits_used_ = 1; // Indica el numero de veces que ha continuado // Actualiza el circulo de colisión a la posición del jugador void shiftColliders(); @@ -245,4 +245,5 @@ public: void setScoreBoardPanel(int panel) { scoreboard_panel_ = panel; } void setScoreMultiplier(float value) { score_multiplier_ = value; } void setWalkingState(PlayerState state) { walking_state_ = state; } + void addCredit() { ++credits_used_; } }; diff --git a/source/screen.cpp b/source/screen.cpp index 2b3cdeb..8cd5380 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -325,11 +325,11 @@ void Screen::renderShake() // Crea una textura temporal auto temp_texture = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); - + // Vuelca game_canvas_ a la textura temporal SDL_SetRenderTarget(renderer_, temp_texture); SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr); - + // Vuelca textura temporal a game_canvas_ SDL_SetRenderTarget(renderer_, game_canvas_); SDL_RenderCopy(renderer_, temp_texture, &src_rect_, &dst_rect_); @@ -339,7 +339,7 @@ void Screen::renderShake() // Restaura el renderizador de destino original SDL_SetRenderTarget(renderer_, current_target); - } + } } // Activa / desactiva los shaders @@ -394,10 +394,9 @@ void Screen::renderInfo() // Contador de service_pressed_counter if (const int counter = globalInputs::service_pressed_counter; counter > 0) + { dbg_print(0, 8, std::to_string(counter).c_str(), 255, 0, 255); - - const std::string atten = attenuate_effect_ ? "ATTEN YES" : "ATTEN NO"; - dbg_print(0, 16, atten.c_str(), 255, 0, 0); + } } }