neteja cppcheck (105 → 0)

This commit is contained in:
2026-05-16 19:35:23 +02:00
parent c9d16959d0
commit fcd2718794
48 changed files with 293 additions and 486 deletions
+3 -3
View File
@@ -265,13 +265,13 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
auto* music = new JA_Music_t();
music->ogg_data.assign(buffer, buffer + length);
int error = 0;
int err_code = 0;
music->vorbis = stb_vorbis_open_memory(music->ogg_data.data(),
static_cast<int>(length),
&error,
&err_code,
nullptr);
if (!music->vorbis) {
std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << error << ")" << '\n';
std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << err_code << ")" << '\n';
delete music;
return nullptr;
}
+5 -5
View File
@@ -1,6 +1,7 @@
#include "core/input/define_buttons.hpp"
#include <algorithm> // Para __all_of_fn, all_of
#include <algorithm> // Para __all_of_fn, all_of, ranges::transform
#include <iterator> // Para back_inserter
#include <memory> // Para unique_ptr, allocator, shared_ptr, operator==, make_unique
#include "core/input/input.hpp" // Para Input
@@ -16,10 +17,9 @@ DefineButtons::DefineButtons()
: input_(Input::get()) {
clearButtons();
auto gamepads = input_->getGamepads();
for (const auto& gamepad : gamepads) {
controller_names_.emplace_back(Input::getControllerName(gamepad));
}
const auto gamepads = input_->getGamepads();
controller_names_.reserve(gamepads.size());
std::ranges::transform(gamepads, std::back_inserter(controller_names_), Input::getControllerName);
// Crear la ventana de mensaje
WindowMessage::Config config(param.service_menu.window_message);
+24 -70
View File
@@ -118,53 +118,22 @@ auto Input::checkAction(Action action, bool repeat, bool check_keyboard, const s
// Comprueba si hay almenos una acción activa
auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr<Gamepad>& gamepad) -> bool {
// Obtenemos el número total de acciones posibles para iterar sobre ellas.
const auto JUST_PRESSED = [](const auto& pair) { return pair.second.just_pressed; };
// --- Comprobación del Teclado ---
if (check_keyboard) {
for (const auto& pair : keyboard_.bindings) {
// Simplemente leemos el estado pre-calculado por Input::update().
// Ya no se llama a SDL_GetKeyboardState ni se modifica el estado '.active'.
if (pair.second.just_pressed) {
return true; // Se encontró una acción recién pulsada.
}
}
if (check_keyboard && std::ranges::any_of(keyboard_.bindings, JUST_PRESSED)) {
return true;
}
// --- Comprobación del Mando ---
// Comprobamos si hay mandos y si el índice solicitado es válido.
if (gamepad != nullptr) {
// Iteramos sobre todas las acciones, no sobre el número de mandos.
for (const auto& pair : gamepad->bindings) {
// Leemos el estado pre-calculado para el mando y la acción específicos.
if (pair.second.just_pressed) {
return true; // Se encontró una acción recién pulsada en el mando.
}
}
}
// Si llegamos hasta aquí, no se detectó ninguna nueva pulsación.
return false;
return gamepad != nullptr && std::ranges::any_of(gamepad->bindings, JUST_PRESSED);
}
// Comprueba si hay algún botón pulsado
auto Input::checkAnyButton(bool repeat) -> bool {
// Solo comprueba los botones definidos previamente
for (auto bi : BUTTON_INPUTS) {
// Comprueba el teclado
if (checkAction(bi, repeat, CHECK_KEYBOARD)) {
return true;
}
// Comprueba los mandos
for (const auto& gamepad : gamepads_) {
if (checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gamepad)) {
return true;
}
}
}
return false;
return std::ranges::any_of(BUTTON_INPUTS, [this, repeat](auto bi) {
if (checkAction(bi, repeat, CHECK_KEYBOARD)) { return true; }
return std::ranges::any_of(gamepads_, [this, bi, repeat](const auto& gamepad) {
return checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gamepad);
});
});
}
// Comprueba si hay algun mando conectado
@@ -178,9 +147,8 @@ auto Input::getControllerName(const std::shared_ptr<Gamepad>& gamepad) -> std::s
// Obtiene la lista de nombres de mandos
auto Input::getControllerNames() const -> std::vector<std::string> {
std::vector<std::string> names;
for (const auto& gamepad : gamepads_) {
names.push_back(gamepad->name);
}
names.reserve(gamepads_.size());
std::ranges::transform(gamepads_, std::back_inserter(names), [](const auto& gamepad) { return gamepad->name; });
return names;
}
@@ -189,21 +157,15 @@ auto Input::getNumGamepads() const -> int { return gamepads_.size(); }
// Obtiene el gamepad a partir de un event.id
auto Input::getGamepad(SDL_JoystickID id) const -> std::shared_ptr<Input::Gamepad> {
for (const auto& gamepad : gamepads_) {
if (gamepad->instance_id == id) {
return gamepad;
}
}
return nullptr;
const auto it = std::ranges::find_if(gamepads_,
[id](const auto& gamepad) { return gamepad->instance_id == id; });
return it != gamepads_.end() ? *it : nullptr;
}
auto Input::getGamepadByName(const std::string& name) const -> std::shared_ptr<Input::Gamepad> {
for (const auto& gamepad : gamepads_) {
if (gamepad && gamepad->name == name) {
return gamepad;
}
}
return nullptr;
const auto it = std::ranges::find_if(gamepads_,
[&name](const auto& gamepad) { return gamepad && gamepad->name == name; });
return it != gamepads_.end() ? *it : nullptr;
}
// Obtiene el SDL_GamepadButton asignado a un action
@@ -359,7 +321,7 @@ void Input::resetInputStates() {
key.second.just_pressed = false;
}
// Resetear todos los ControllerBindings.active a false
for (auto& gamepad : gamepads_) {
for (const auto& gamepad : gamepads_) {
for (auto& binding : gamepad->bindings) {
binding.second.is_held = false;
binding.second.just_pressed = false;
@@ -568,19 +530,11 @@ auto Input::findAvailableGamepadByName(const std::string& gamepad_name) -> std::
}
// Buscar por nombre
for (const auto& gamepad : gamepads_) {
if (gamepad && gamepad->name == gamepad_name) {
return gamepad;
}
}
auto by_name = std::ranges::find_if(gamepads_,
[&gamepad_name](const auto& gamepad) { return gamepad && gamepad->name == gamepad_name; });
if (by_name != gamepads_.end()) { return *by_name; }
// Si no se encuentra por nombre, devolver el primer gamepad válido
for (const auto& gamepad : gamepads_) {
if (gamepad) {
return gamepad;
}
}
// Si llegamos aquí, no hay gamepads válidos
return nullptr;
auto first_valid = std::ranges::find_if(gamepads_, [](const auto& gamepad) { return gamepad != nullptr; });
return first_valid != gamepads_.end() ? *first_valid : nullptr;
}
+4 -4
View File
@@ -32,7 +32,7 @@ class Input {
bool is_held; // Está pulsada ahora mismo
bool just_pressed; // Se acaba de pulsar en este fotograma
KeyState(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false)
explicit KeyState(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false)
: scancode(scancode),
is_held(is_held),
just_pressed(just_pressed) {}
@@ -45,7 +45,7 @@ class Input {
bool axis_active; // Estado del eje
bool trigger_active{false}; // Estado del trigger como botón digital
ButtonState(int btn = static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID), bool is_held = false, bool just_pressed = false, bool axis_act = false)
explicit ButtonState(int btn = static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID), bool is_held = false, bool just_pressed = false, bool axis_act = false)
: button(btn),
is_held(is_held),
just_pressed(just_pressed),
@@ -115,7 +115,7 @@ class Input {
return s;
}
Gamepad(SDL_Gamepad* gamepad)
explicit Gamepad(SDL_Gamepad* gamepad)
: pad(gamepad),
instance_id(SDL_GetJoystickID(SDL_GetGamepadJoystick(gamepad))),
name(trimName(SDL_GetGamepadName(gamepad))),
@@ -148,7 +148,7 @@ class Input {
// Reasigna un botón a una acción
void rebindAction(Action action, SDL_GamepadButton new_button) {
bindings[action] = static_cast<int>(new_button);
bindings[action] = ButtonState{static_cast<int>(new_button)};
}
};
+13 -24
View File
@@ -1,9 +1,11 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <functional>
#include <string>
#include <utility>
#include <vector>
// --- Clase PauseManager: maneja el sistema de pausa del juego ---
class PauseManager {
@@ -48,7 +50,7 @@ class PauseManager {
// --- Métodos principales ---
void setFlag(Source source, bool enable) { // Establece/quita una fuente de pausa específica
bool was_paused = isPaused();
const bool WAS_PAUSED = isPaused();
if (enable) {
flags_ |= source;
@@ -56,7 +58,8 @@ class PauseManager {
flags_ &= ~source; // Ahora funciona: Source &= uint8_t
}
if (was_paused != isPaused()) {
// cppcheck-suppress knownConditionTrueFalse // false-positive: flags_ ha estat modificat entre les dues crides a isPaused()
if (WAS_PAUSED != isPaused()) {
notifyPauseChanged();
}
}
@@ -88,30 +91,16 @@ class PauseManager {
return "Active";
}
std::vector<std::string> parts;
if (hasFlag(Source::PLAYER)) { parts.emplace_back("Player"); }
if (hasFlag(Source::SERVICE_MENU)) { parts.emplace_back("ServiceMenu"); }
if (hasFlag(Source::FOCUS_LOST)) { parts.emplace_back("FocusLoss"); }
std::string result = "Paused by: ";
bool first = true;
if (hasFlag(Source::PLAYER)) {
if (!first) {
result += ", ";
}
result += "Player";
first = false;
for (size_t i = 0; i < parts.size(); ++i) {
if (i > 0) { result += ", "; }
result += parts[i];
}
if (hasFlag(Source::SERVICE_MENU)) {
if (!first) {
result += ", ";
}
result += "ServiceMenu";
first = false;
}
if (hasFlag(Source::FOCUS_LOST)) {
if (!first) {
result += ", ";
}
result += "FocusLoss";
}
return result;
}
void setCallback(std::function<void(bool)> callback) { // Permite cambiar el callback en runtime
+14 -28
View File
@@ -1,5 +1,6 @@
#include "core/locale/lang.hpp"
#include <algorithm> // Para ranges::find_if
#include <cstddef> // Para size_t
#include <exception> // Para exception
#include <fstream> // Para basic_ifstream, basic_istream, ifstream
@@ -80,35 +81,23 @@ namespace Lang {
// Obtiene un idioma del vector de idiomas a partir de un código
auto getLanguage(Code code) -> Language {
for (const auto& lang : languages) {
if (lang.code == code) {
return lang;
}
}
// Si no se encuentra, devuelve el primero por defecto
return languages[0];
const auto it = std::ranges::find_if(languages,
[code](const auto& lang) { return lang.code == code; });
return it != languages.end() ? *it : languages[0];
}
// Devuelve el código de un idioma a partir de un nombre
auto getCodeFromName(const std::string& name) -> Code {
for (const auto& lang : languages) {
if (lang.name == name) {
return lang.code;
}
}
// Si no se encuentra, devuelve el primero por defecto
return languages[0].code;
const auto it = std::ranges::find_if(languages,
[&name](const auto& lang) { return lang.name == name; });
return it != languages.end() ? it->code : languages[0].code;
}
// Devuelve el nombre de un idioma a partir de un código
auto getNameFromCode(Code code) -> std::string {
for (const auto& lang : languages) {
if (lang.code == code) {
return lang.name;
}
}
// Si no se encuentra, devuelve el nombre del primer idioma por defecto
return languages[0].name;
const auto it = std::ranges::find_if(languages,
[code](const auto& lang) { return lang.code == code; });
return it != languages.end() ? it->name : languages[0].name;
}
// Actualiza los nombres de los idiomas
@@ -155,13 +144,10 @@ namespace Lang {
// Obtiene una fichero a partir de un lang::Code
auto getLanguageFileName(Lang::Code code) -> std::string {
for (const auto& lang : languages) {
if (lang.code == code) {
return Asset::get()->getPath(lang.file_name);
}
}
// Si no se encuentra, devuelve el fichero del primer idioma por defecto
return Asset::get()->getPath(languages[0].file_name);
const auto it = std::ranges::find_if(languages,
[code](const auto& lang) { return lang.code == code; });
const auto& file = (it != languages.end()) ? it->file_name : languages[0].file_name;
return Asset::get()->getPath(file);
}
// Establece el idioma
+4 -5
View File
@@ -562,14 +562,13 @@ void Background::createMoonPath() {
const int FREEZE_START_INDEX = static_cast<int>(NUM_STEPS * (1.0F - FREEZE_PERCENTAGE));
for (int i = 0; i < NUM_STEPS; ++i) {
double theta = i * STEP;
float x = CENTER_X + (RADIUS * cos(theta));
float y = CENTER_Y - (RADIUS * sin(theta));
if (i >= FREEZE_START_INDEX && !moon_path_.empty()) {
moon_path_.push_back(moon_path_.back()); // Repite el último punto válido
} else {
moon_path_.push_back({.x = x, .y = y});
const double THETA = i * STEP;
const float X = CENTER_X + (RADIUS * cos(THETA));
const float Y = CENTER_Y - (RADIUS * sin(THETA));
moon_path_.push_back({.x = X, .y = Y});
}
}
}
+2 -2
View File
@@ -28,8 +28,8 @@ class Background {
using ProgressCallback = std::function<void(float)>; // Callback para sincronización
// --- Constructor y destructor ---
Background(float total_progress_to_complete = 6100.0F); // Constructor principal
~Background(); // Destructor
explicit Background(float total_progress_to_complete = 6100.0F); // Constructor principal
~Background(); // Destructor
// --- Métodos principales ---
void update(float delta_time); // Actualiza la lógica del objeto
+1 -1
View File
@@ -66,7 +66,7 @@ class Screen {
[[nodiscard]] auto getText() const -> std::shared_ptr<Text> { return text_; } // Obtiene el puntero al texto de Screen
// --- Display Monitor getters ---
[[nodiscard]] auto getDisplayMonitorName() const -> std::string { return display_monitor_.name; }
[[nodiscard]] auto getDisplayMonitorName() const -> const std::string& { return display_monitor_.name; }
[[nodiscard]] auto getDisplayMonitorWidth() const -> int { return display_monitor_.width; }
[[nodiscard]] auto getDisplayMonitorHeight() const -> int { return display_monitor_.height; }
[[nodiscard]] auto getDisplayMonitorRefreshRate() const -> int { return display_monitor_.refresh_rate; }
+6 -6
View File
@@ -25,12 +25,12 @@ enum class PathCentered { // Centrado del recorrido
// --- Estructuras ---
struct Path { // Define un recorrido para el sprite
float start_pos; // Posición inicial
float end_pos; // Posición final
PathType type; // Tipo de movimiento (horizontal/vertical)
float fixed_pos; // Posición fija en el eje contrario
float duration_s; // Duración de la animación en segundos
float waiting_time_s; // Tiempo de espera una vez en el destino
float start_pos = 0.0F; // Posición inicial
float end_pos = 0.0F; // Posición final
PathType type = PathType::HORIZONTAL; // Tipo de movimiento (horizontal/vertical)
float fixed_pos = 0.0F; // Posición fija en el eje contrario
float duration_s = 0.0F; // Duración de la animación en segundos
float waiting_time_s = 0.0F; // Tiempo de espera una vez en el destino
std::function<double(double)> easing_function; // Función de easing
float elapsed_time = 0.0F; // Tiempo transcurrido
float waiting_elapsed = 0.0F; // Tiempo de espera transcurrido
+1 -2
View File
@@ -403,9 +403,8 @@ auto Text::loadFile(const std::string& file_path) -> std::shared_ptr<Text::File>
file.open(file_path);
}
std::istream& input_stream = using_resource_data ? stream : static_cast<std::istream&>(file);
if ((using_resource_data && stream.good()) || (!using_resource_data && file.is_open() && file.good())) {
std::istream& input_stream = using_resource_data ? stream : static_cast<std::istream&>(file);
std::string buffer;
// Lee los dos primeros valores del fichero
+1 -1
View File
@@ -39,7 +39,7 @@ class Text {
int kerning;
// Constructor con argumentos por defecto
Style(Uint8 flags = 0,
explicit Style(Uint8 flags = 0,
Color text = Color(),
Color shadow = Color(),
Uint8 distance = 1,
+54 -73
View File
@@ -2,12 +2,14 @@
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_LogError, SDL_SetRenderDrawColor, SDL_EventType, SDL_PollEvent, SDL_RenderFillRect, SDL_RenderRect, SDLK_ESCAPE, SDL_Event
#include <algorithm> // Para ranges::transform, ranges::find_if
#include <array> // Para array
#include <cstdlib> // Para exit
#include <exception> // Para exception
#include <filesystem> // Para exists, path, remove
#include <fstream> // Para basic_ofstream, basic_ios, basic_ostream::write, ios, ofstream
#include <iostream> // Para std::cout
#include <iterator> // Para back_inserter
#include <ranges> // Para __find_if_fn, find_if, __find_fn, find
#include <stdexcept> // Para runtime_error
#include <utility> // Para move
@@ -138,40 +140,37 @@ void Resource::loadEssentialTextures() {
// Inicializa las listas de recursos sin cargar el contenido (modo lazy)
void Resource::initResourceLists() {
const auto file_to_name = [](const auto& file) { return getFileName(file); };
// Inicializa lista de sonidos
auto sound_list = Asset::get()->getListByType(Asset::Type::SOUND);
const auto sound_list = Asset::get()->getListByType(Asset::Type::SOUND);
sounds_.clear();
for (const auto& file : sound_list) {
sounds_.emplace_back(getFileName(file));
}
sounds_.reserve(sound_list.size());
std::ranges::transform(sound_list, std::back_inserter(sounds_), [&](const auto& file) { return ResourceSound(file_to_name(file)); });
// Inicializa lista de músicas
auto music_list = Asset::get()->getListByType(Asset::Type::MUSIC);
const auto music_list = Asset::get()->getListByType(Asset::Type::MUSIC);
musics_.clear();
for (const auto& file : music_list) {
musics_.emplace_back(getFileName(file));
}
musics_.reserve(music_list.size());
std::ranges::transform(music_list, std::back_inserter(musics_), [&](const auto& file) { return ResourceMusic(file_to_name(file)); });
// Inicializa lista de texturas
auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
const auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
textures_.clear();
for (const auto& file : texture_list) {
textures_.emplace_back(getFileName(file));
}
textures_.reserve(texture_list.size());
std::ranges::transform(texture_list, std::back_inserter(textures_), [&](const auto& file) { return ResourceTexture(file_to_name(file)); });
// Inicializa lista de ficheros de texto
auto text_file_list = Asset::get()->getListByType(Asset::Type::FONT);
const auto text_file_list = Asset::get()->getListByType(Asset::Type::FONT);
text_files_.clear();
for (const auto& file : text_file_list) {
text_files_.emplace_back(getFileName(file));
}
text_files_.reserve(text_file_list.size());
std::ranges::transform(text_file_list, std::back_inserter(text_files_), [&](const auto& file) { return ResourceTextFile(file_to_name(file)); });
// Inicializa lista de animaciones
auto animation_list = Asset::get()->getListByType(Asset::Type::ANIMATION);
const auto animation_list = Asset::get()->getListByType(Asset::Type::ANIMATION);
animations_.clear();
for (const auto& file : animation_list) {
animations_.emplace_back(getFileName(file));
}
animations_.reserve(animation_list.size());
std::ranges::transform(animation_list, std::back_inserter(animations_), [&](const auto& file) { return ResourceAnimation(file_to_name(file)); });
// Los demos se cargan directamente sin mostrar progreso (son pocos y pequeños)
loadDemoDataQuiet();
@@ -192,9 +191,8 @@ void Resource::initResourceLists() {
"smb2_grad"};
texts_.clear();
for (const auto& text_name : TEXT_OBJECTS) {
texts_.emplace_back(text_name); // Constructor con nullptr por defecto
}
texts_.reserve(TEXT_OBJECTS.size());
std::ranges::transform(TEXT_OBJECTS, std::back_inserter(texts_), [](const auto& text_name) { return ResourceText(text_name); });
}
// Obtiene el sonido a partir de un nombre (con carga perezosa)
@@ -336,23 +334,17 @@ auto Resource::loadMusicLazy(const std::string& name) -> JA_Music_t* {
}
auto Resource::loadTextureLazy(const std::string& name) -> std::shared_ptr<Texture> {
auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
for (const auto& file : texture_list) {
if (getFileName(file) == name) {
return std::make_shared<Texture>(Screen::get()->getRenderer(), file);
}
}
return nullptr;
const auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
const auto it = std::ranges::find_if(texture_list,
[&name](const auto& file) { return getFileName(file) == name; });
return it != texture_list.end() ? std::make_shared<Texture>(Screen::get()->getRenderer(), *it) : nullptr;
}
auto Resource::loadTextFileLazy(const std::string& name) -> std::shared_ptr<Text::File> {
auto text_file_list = Asset::get()->getListByType(Asset::Type::FONT);
for (const auto& file : text_file_list) {
if (getFileName(file) == name) {
return Text::loadFile(file);
}
}
return nullptr;
const auto text_file_list = Asset::get()->getListByType(Asset::Type::FONT);
const auto it = std::ranges::find_if(text_file_list,
[&name](const auto& file) { return getFileName(file) == name; });
return it != text_file_list.end() ? Text::loadFile(*it) : nullptr;
}
auto Resource::loadTextLazy(const std::string& name) -> std::shared_ptr<Text> {
@@ -377,27 +369,22 @@ auto Resource::loadTextLazy(const std::string& name) -> std::shared_ptr<Text> {
{.key = "smb2", .texture_file = "smb2.png", .text_file = "smb2.txt"},
{.key = "smb2_grad", .texture_file = "smb2_grad.png", .text_file = "smb2.txt"}};
for (const auto& mapping : TEXT_MAPPINGS) {
if (mapping.key == name) {
// Cargar las dependencias automáticamente
auto texture = getTexture(mapping.texture_file); // Esto cargará la textura si no está cargada
auto text_file = getTextFile(mapping.text_file); // Esto cargará el archivo de texto si no está cargado
if (texture && text_file) {
return std::make_shared<Text>(texture, text_file);
}
}
const auto it = std::ranges::find_if(TEXT_MAPPINGS,
[&name](const auto& mapping) { return mapping.key == name; });
if (it == TEXT_MAPPINGS.end()) {
return nullptr;
}
return nullptr;
auto texture = getTexture(it->texture_file); // Esto cargará la textura si no está cargada
auto text_file = getTextFile(it->text_file); // Esto cargará el archivo de texto si no está cargado
return (texture && text_file) ? std::make_shared<Text>(texture, text_file) : nullptr;
}
auto Resource::loadAnimationLazy(const std::string& name) -> AnimationsFileBuffer {
auto animation_list = Asset::get()->getListByType(Asset::Type::ANIMATION);
for (const auto& file : animation_list) {
if (getFileName(file) == name) {
return loadAnimationsFromFile(file);
}
const auto animation_list = Asset::get()->getListByType(Asset::Type::ANIMATION);
const auto it = std::ranges::find_if(animation_list,
[&name](const auto& file) { return getFileName(file) == name; });
if (it != animation_list.end()) {
return loadAnimationsFromFile(*it);
}
// Si no se encuentra, retorna vector vacío
return AnimationsFileBuffer{};
@@ -640,14 +627,10 @@ void Resource::createPlayerTextures() {
const auto& player = players[player_idx]; // Obtenemos el jugador actual
// Encontrar el archivo original de la textura
std::string texture_file_path;
auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
for (const auto& file : texture_list) {
if (getFileName(file) == player.base_texture) {
texture_file_path = file;
break;
}
}
const auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
const auto it = std::ranges::find_if(texture_list,
[&player](const auto& file) { return getFileName(file) == player.base_texture; });
const std::string texture_file_path = (it != texture_list.end()) ? *it : std::string{};
// Crear las 4 texturas con sus respectivas paletas
for (int palette_idx = 0; palette_idx < 4; ++palette_idx) {
@@ -720,9 +703,9 @@ void Resource::createTextTextures() {
{"game_text_1000000_points", Lang::getText("[GAME_TEXT] 8")}};
auto text1 = getText("04b_25_enhanced");
for (const auto& s : strings1) {
textures_.emplace_back(s.name, text1->writeDXToTexture(Text::STROKE, s.text, -2, Colors::NO_COLOR_MOD, 1, param.game.item_text_outline_color));
}
std::ranges::transform(strings1, std::back_inserter(textures_), [&](const auto& s) {
return ResourceTexture(s.name, text1->writeDXToTexture(Text::STROKE, s.text, -2, Colors::NO_COLOR_MOD, 1, param.game.item_text_outline_color));
});
// Texturas de tamaño doble
std::vector<NameAndText> strings2 = {
@@ -734,9 +717,9 @@ void Resource::createTextTextures() {
{"game_text_game_over", "Game Over"}};
auto text2 = getText("04b_25_2x_enhanced");
for (const auto& s : strings2) {
textures_.emplace_back(s.name, text2->writeDXToTexture(Text::STROKE, s.text, -4, Colors::NO_COLOR_MOD, 1, param.game.item_text_outline_color));
}
std::ranges::transform(strings2, std::back_inserter(textures_), [&](const auto& s) {
return ResourceTexture(s.name, text2->writeDXToTexture(Text::STROKE, s.text, -4, Colors::NO_COLOR_MOD, 1, param.game.item_text_outline_color));
});
}
// Crea los objetos de texto a partir de los archivos de textura y texto
@@ -897,12 +880,10 @@ void Resource::renderProgress() {
// Carga los datos para el modo demostración (sin mostrar progreso)
void Resource::loadDemoDataQuiet() {
auto list = Asset::get()->getListByType(Asset::Type::DEMODATA);
const auto list = Asset::get()->getListByType(Asset::Type::DEMODATA);
demos_.clear();
for (const auto& l : list) {
demos_.emplace_back(loadDemoDataFromFile(l));
}
demos_.reserve(list.size());
std::ranges::transform(list, std::back_inserter(demos_), [this](const auto& l) { return loadDemoDataFromFile(l); });
}
// Inicializa los rectangulos que definen la barra de progreso
+7 -7
View File
@@ -60,7 +60,7 @@ class Resource {
std::string name; // Nombre del sonido
JA_Sound_t* sound; // Objeto con el sonido
ResourceSound(std::string name, JA_Sound_t* sound = nullptr)
explicit ResourceSound(std::string name, JA_Sound_t* sound = nullptr)
: name(std::move(name)),
sound(sound) {}
};
@@ -69,7 +69,7 @@ class Resource {
std::string name; // Nombre de la música
JA_Music_t* music; // Objeto con la música
ResourceMusic(std::string name, JA_Music_t* music = nullptr)
explicit ResourceMusic(std::string name, JA_Music_t* music = nullptr)
: name(std::move(name)),
music(music) {}
};
@@ -78,7 +78,7 @@ class Resource {
std::string name; // Nombre de la textura
std::shared_ptr<Texture> texture; // Objeto con la textura
ResourceTexture(std::string name, std::shared_ptr<Texture> texture = nullptr)
explicit ResourceTexture(std::string name, std::shared_ptr<Texture> texture = nullptr)
: name(std::move(name)),
texture(std::move(texture)) {}
};
@@ -87,7 +87,7 @@ class Resource {
std::string name; // Nombre del fichero
std::shared_ptr<Text::File> text_file; // Objeto con los descriptores de la fuente de texto
ResourceTextFile(std::string name, std::shared_ptr<Text::File> text_file = nullptr)
explicit ResourceTextFile(std::string name, std::shared_ptr<Text::File> text_file = nullptr)
: name(std::move(name)),
text_file(std::move(text_file)) {}
};
@@ -96,7 +96,7 @@ class Resource {
std::string name; // Nombre del objeto
std::shared_ptr<Text> text; // Objeto de texto
ResourceText(std::string name, std::shared_ptr<Text> text = nullptr)
explicit ResourceText(std::string name, std::shared_ptr<Text> text = nullptr)
: name(std::move(name)),
text(std::move(text)) {}
};
@@ -105,7 +105,7 @@ class Resource {
std::string name; // Nombre de la animación
AnimationsFileBuffer animation; // Objeto con las animaciones
ResourceAnimation(std::string name, AnimationsFileBuffer animation = {})
explicit ResourceAnimation(std::string name, AnimationsFileBuffer animation = {})
: name(std::move(name)),
animation(std::move(animation)) {}
};
@@ -116,7 +116,7 @@ class Resource {
size_t loaded{0}; // Número de recursos cargados
ResourceCount() = default;
ResourceCount(size_t total)
explicit ResourceCount(size_t total)
: total(total) {}
void add(size_t amount) { loaded += amount; }
+3 -25
View File
@@ -1,10 +1,8 @@
#pragma once
#include <cstdint> // Para uint8_t
#include <filesystem> // Para remove, path
#include <fstream> // Para basic_ofstream, basic_ios, basic_ostream::write, ios, ofstream
#include <string> // Para string, basic_string, hash, operator+, to_string, __str_hash_base
#include <vector> // Para vector
#include <cstdint> // Para uint8_t
#include <string> // Para string
#include <vector> // Para vector
// Helper functions para integrar ResourceLoader con el sistema existente
namespace ResourceHelper {
@@ -22,24 +20,4 @@ namespace ResourceHelper {
// Convierte ruta Asset a ruta relativa para ResourceLoader
auto getPackPath(const std::string& asset_path) -> std::string;
// Wrappea la carga de archivos para mantener compatibilidad
template <typename T>
auto loadResourceFile(const std::string& asset_path, T* (*loader_func)(const char*)) -> T* {
auto data = loadFile(asset_path);
if (data.empty()) {
return loader_func(asset_path.c_str());
}
// Crear archivo temporal para funciones que esperan path
std::string temp_path = "/tmp/ccae_" + std::to_string(std::hash<std::string>{}(asset_path));
std::ofstream temp_file(temp_path, std::ios::binary);
temp_file.write(reinterpret_cast<const char*>(data.data()), data.size());
temp_file.close();
T* result = loader_func(temp_path.c_str());
std::filesystem::remove(temp_path);
return result;
}
} // namespace ResourceHelper
+10 -17
View File
@@ -1,10 +1,11 @@
#include "core/resources/resource_pack.hpp"
#include <algorithm> // Para replace
#include <algorithm> // Para replace, ranges::all_of
#include <array> // Para array
#include <filesystem> // Para path, recursive_directory_iterator, directory_entry, exists, relative
#include <fstream> // Para basic_ifstream, basic_ostream, basic_ofstream, operator<<, basic_ios, basic_istream::read, basic_ostream::write, endl, ios, basic_istream, ifstream, operator|, basic_istream::seekg, basic_istream::tellg, ofstream, streamsize
#include <iostream> // Para cerr
#include <numeric> // Para accumulate
#include <utility> // Para pair
const std::string ResourcePack::DEFAULT_ENCRYPT_KEY = "CCAE_RESOURCES__2024";
@@ -17,11 +18,7 @@ ResourcePack::~ResourcePack() {
}
auto ResourcePack::calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t {
uint32_t checksum = 0x12345678;
for (unsigned char i : data) {
checksum = ((checksum << 5) + checksum) + i;
}
return checksum;
return std::accumulate(data.begin(), data.end(), static_cast<uint32_t>(0x12345678), [](uint32_t checksum, unsigned char i) { return ((checksum << 5) + checksum) + i; });
}
void ResourcePack::encryptData(std::vector<uint8_t>& data, const std::string& key) {
@@ -162,20 +159,16 @@ auto ResourcePack::addDirectory(const std::string& directory) -> bool {
return false; // NOLINT(readability-simplify-boolean-expr)
}
for (const auto& entry : std::filesystem::recursive_directory_iterator(directory)) {
if (entry.is_regular_file()) {
return std::ranges::all_of(std::filesystem::recursive_directory_iterator(directory),
[this, &directory](const auto& entry) {
if (!entry.is_regular_file()) {
return true;
}
std::string filepath = entry.path().string();
std::string filename = std::filesystem::relative(entry.path(), directory).string();
std::ranges::replace(filename, '\\', '/');
if (!addFile(filename, filepath)) {
return false;
}
}
}
return true;
return addFile(filename, filepath);
});
}
auto ResourcePack::getResource(const std::string& filename) -> std::vector<uint8_t> {
+1 -1
View File
@@ -520,7 +520,7 @@ auto Director::iterate() -> SDL_AppResult {
}
// Procesa un evento SDL (llamado desde SDL_AppEvent)
auto Director::handleEvent(SDL_Event& event) -> SDL_AppResult {
auto Director::handleEvent(const SDL_Event& event) -> SDL_AppResult {
// Eventos globales (SDL_EVENT_QUIT, resize, render target reset, hotplug, service menu, ratón)
GlobalEvents::handle(event);
+2 -2
View File
@@ -29,8 +29,8 @@ class Director {
~Director();
// --- Callbacks para SDL_MAIN_USE_CALLBACKS ---
auto iterate() -> SDL_AppResult; // Avanza un frame de la sección activa
auto handleEvent(SDL_Event& event) -> SDL_AppResult; // Procesa un evento SDL
auto iterate() -> SDL_AppResult; // Avanza un frame de la sección activa
auto handleEvent(const SDL_Event& event) -> SDL_AppResult; // Procesa un evento SDL
// --- Debug config (accesible desde otras clases) ---
struct DebugConfig {
+1 -1
View File
@@ -85,7 +85,7 @@ class Balloon {
};
// --- Constructores y destructor ---
Balloon(const Config& config);
explicit Balloon(const Config& config);
~Balloon() = default;
// --- Métodos principales ---
+1 -1
View File
@@ -977,7 +977,7 @@ void Player::playSound(const std::string& name) const {
return;
}
static auto* audio_ = Audio::get();
static const auto* audio_ = Audio::get();
audio_->playSound(name);
}
+7 -7
View File
@@ -114,7 +114,7 @@ class Player {
};
// --- Constructor y destructor ---
Player(const Config& config);
explicit Player(const Config& config);
~Player() = default;
// --- Inicialización y ciclo de vida ---
@@ -201,16 +201,16 @@ class Player {
[[nodiscard]] auto getCoffees() const -> int { return coffees_; }
[[nodiscard]] auto getPowerUpCounter() const -> int { return power_up_counter_; }
[[nodiscard]] auto getInvulnerableCounter() const -> int { return invulnerable_counter_; }
[[nodiscard]] auto getBulletColor() const -> Bullet::Color; // Devuelve el color actual de bala según el estado
auto getNextBulletColor() -> Bullet::Color; // Devuelve el color para la próxima bala (alterna si está en modo toggle)
void setBulletColors(Bullet::Color normal, Bullet::Color powered); // Establece los colores de bala para este jugador
[[nodiscard]] auto getBulletSoundFile() const -> std::string { return bullet_sound_file_; } // Devuelve el archivo de sonido de bala
void setBulletSoundFile(const std::string& filename); // Establece el archivo de sonido de bala para este jugador
[[nodiscard]] auto getBulletColor() const -> Bullet::Color; // Devuelve el color actual de bala según el estado
auto getNextBulletColor() -> Bullet::Color; // Devuelve el color para la próxima bala (alterna si está en modo toggle)
void setBulletColors(Bullet::Color normal, Bullet::Color powered); // Establece los colores de bala para este jugador
[[nodiscard]] auto getBulletSoundFile() const -> const std::string& { return bullet_sound_file_; } // Devuelve el archivo de sonido de bala
void setBulletSoundFile(const std::string& filename); // Establece el archivo de sonido de bala para este jugador
// Contadores y timers
[[nodiscard]] auto getContinueCounter() const -> int { return continue_counter_; }
[[nodiscard]] auto getRecordName() const -> std::string { return enter_name_ ? enter_name_->getFinalName() : "xxx"; }
[[nodiscard]] auto getLastEnterName() const -> std::string { return last_enter_name_; }
[[nodiscard]] auto getLastEnterName() const -> const std::string& { return last_enter_name_; }
// --- Configuración e interfaz externa ---
void setName(const std::string& name) { name_ = name; }
+9 -12
View File
@@ -222,13 +222,13 @@ void BalloonFormations::createFloaterVariants() {
formations_.resize(100);
// Crear variantes flotantes de las primeras 50 formaciones
for (size_t k = 0; k < 50 && k < formations_.size(); k++) {
for (size_t k = 0; k < 50; k++) {
const auto& source = formations_.at(k).balloons;
std::vector<SpawnParams> floater_params;
floater_params.reserve(formations_.at(k).balloons.size());
for (const auto& original : formations_.at(k).balloons) {
floater_params.emplace_back(original.x, original.y, original.vel_x, Balloon::Type::FLOATER, original.size, original.creation_counter);
}
floater_params.reserve(source.size());
std::ranges::transform(source, std::back_inserter(floater_params), [](const auto& original) {
return SpawnParams{original.x, original.y, original.vel_x, Balloon::Type::FLOATER, original.size, original.creation_counter};
});
formations_.at(k + 50) = Formation(floater_params);
}
@@ -395,24 +395,21 @@ void BalloonFormations::loadDefaultPools() {
}
}
// Pool 2: Mix de formaciones normales y floaters (50+)
// Pools 2 i 3: requereixen formacions de floaters (>50)
if (total_formations > 50) {
// Pool 2: Mix de formacions normals i floaters
Pool pool2;
// Agregar algunas formaciones básicas
for (size_t i = 0; i < std::min(static_cast<size_t>(5), total_formations); ++i) {
pool2.push_back(static_cast<int>(i));
}
// Agregar algunas floaters si existen
for (size_t i = 50; i < std::min(static_cast<size_t>(55), total_formations); ++i) {
pool2.push_back(static_cast<int>(i));
}
if (!pool2.empty()) {
pools_.push_back(pool2);
}
}
// Pool 3: Solo floaters (si existen formaciones 50+)
if (total_formations > 50) {
// Pool 3: Només floaters
Pool pool3;
for (size_t i = 50; i < std::min(static_cast<size_t>(70), total_formations); ++i) {
pool3.push_back(static_cast<int>(i));
+1 -1
View File
@@ -39,7 +39,7 @@ class BalloonFormations {
std::vector<SpawnParams> balloons; // Vector con todas las inicializaciones de los globos de la formación
// Constructor con parámetros
Formation(const std::vector<SpawnParams>& spawn_params)
explicit Formation(const std::vector<SpawnParams>& spawn_params)
: balloons(spawn_params) {}
// Constructor por defecto
+3 -3
View File
@@ -106,7 +106,7 @@ void BalloonManager::deployRandomFormation(int stage) {
// Crea los globos de la formación
const auto BALLOONS = balloon_formations_->getFormationFromPool(stage, formation_id).balloons;
for (auto balloon : BALLOONS) {
for (const auto& balloon : BALLOONS) {
Balloon::Config config = {
.x = balloon.x,
.y = balloon.y,
@@ -127,7 +127,7 @@ void BalloonManager::deployRandomFormation(int stage) {
// Crea una formación de globos específica
void BalloonManager::deployFormation(int formation_id) {
const auto BALLOONS = balloon_formations_->getFormation(formation_id).balloons;
for (auto balloon : BALLOONS) {
for (const auto& balloon : BALLOONS) {
Balloon::Config config = {
.x = balloon.x,
.y = balloon.y,
@@ -143,7 +143,7 @@ void BalloonManager::deployFormation(int formation_id) {
// Crea una formación de globos específica a una altura determinada
void BalloonManager::deployFormation(int formation_id, float y) {
const auto BALLOONS = balloon_formations_->getFormation(formation_id).balloons;
for (auto balloon : BALLOONS) {
for (const auto& balloon : BALLOONS) {
Balloon::Config config = {
.x = balloon.x,
.y = y,
+1 -1
View File
@@ -24,7 +24,7 @@ using Balloons = std::list<std::shared_ptr<Balloon>>;
class BalloonManager {
public:
// --- Constructor y destructor ---
BalloonManager(IStageInfo* stage_info);
explicit BalloonManager(IStageInfo* stage_info);
~BalloonManager() = default;
// --- Métodos principales ---
+2 -2
View File
@@ -14,7 +14,7 @@ BulletManager::BulletManager()
// Actualiza el estado de todas las balas
void BulletManager::update(float delta_time) {
for (auto& bullet : bullets_) {
for (const auto& bullet : bullets_) {
if (bullet->isEnabled()) {
processBulletUpdate(bullet, delta_time);
}
@@ -23,7 +23,7 @@ void BulletManager::update(float delta_time) {
// Renderiza todas las balas activas
void BulletManager::render() {
for (auto& bullet : bullets_) {
for (const auto& bullet : bullets_) {
if (bullet->isEnabled()) {
bullet->render();
}
+1 -1
View File
@@ -4,7 +4,7 @@
class Cooldown {
public:
Cooldown(float first_delay_s = 0.0F, float repeat_delay_s = 0.0F)
explicit Cooldown(float first_delay_s = 0.0F, float repeat_delay_s = 0.0F)
: first_delay_s_(first_delay_s),
repeat_delay_s_(repeat_delay_s) {}
+10 -9
View File
@@ -1,6 +1,7 @@
#include "game/gameplay/difficulty.hpp"
#include <vector> // Para vector
#include <algorithm> // Para ranges::find_if
#include <vector> // Para vector
namespace Difficulty {
@@ -18,19 +19,19 @@ namespace Difficulty {
}
auto getNameFromCode(Code code) -> std::string {
for (const auto& difficulty : difficulties_list) {
if (difficulty.code == code) {
return difficulty.name;
}
const auto it = std::ranges::find_if(difficulties_list,
[code](const auto& difficulty) { return difficulty.code == code; });
if (it != difficulties_list.end()) {
return it->name;
}
return !difficulties_list.empty() ? difficulties_list.front().name : "Unknown";
}
auto getCodeFromName(const std::string& name) -> Code {
for (const auto& difficulty : difficulties_list) {
if (difficulty.name == name) {
return difficulty.code;
}
const auto it = std::ranges::find_if(difficulties_list,
[&name](const auto& difficulty) { return difficulty.name == name; });
if (it != difficulties_list.end()) {
return it->code;
}
return !difficulties_list.empty() ? difficulties_list.front().code : Code::NORMAL;
}
+1 -1
View File
@@ -21,7 +21,7 @@ class EnterName {
void removeLastCharacter(); // Elimina el último carácter del nombre
auto getFinalName() -> std::string; // Obtiene el nombre final (o aleatorio si vacío)
[[nodiscard]] auto getCurrentName() const -> std::string { return name_; } // Obtiene el nombre actual en proceso
[[nodiscard]] auto getCurrentName() const -> const std::string& { return name_; } // Obtiene el nombre actual en proceso
[[nodiscard]] auto getSelectedCharacter(int offset = 0) const -> std::string; // Devuelve el carácter seleccionado con offset relativo
[[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
+5 -15
View File
@@ -8,6 +8,7 @@
#include <iomanip> // Para std::setw, std::setfill
#include <iostream> // Para std::cout
#include <iterator> // Para distance
#include <numeric> // Para accumulate
#include <ranges> // Para __find_if_fn, find_if
#include <utility> // Para move
@@ -260,22 +261,11 @@ auto ManageHiScoreTable::verifyChecksum(SDL_IOStream* file, const std::string& f
// Calcula checksum de la tabla
auto ManageHiScoreTable::calculateChecksum(const Table& table) -> unsigned int {
unsigned int checksum = 0x12345678; // Magic seed
for (const auto& entry : table) {
// Checksum del score
return std::accumulate(table.begin(), table.end(), 0x12345678U, [](unsigned int checksum, const auto& entry) {
checksum = ((checksum << 5) + checksum) + static_cast<unsigned int>(entry.score);
// Checksum del nombre
for (char c : entry.name) {
checksum = ((checksum << 5) + checksum) + static_cast<unsigned int>(c);
}
// Checksum de one_credit_complete
checksum = ((checksum << 5) + checksum) + (entry.one_credit_complete ? 1U : 0U);
}
return checksum;
checksum = std::accumulate(entry.name.begin(), entry.name.end(), checksum, [](unsigned int acc, char c) { return ((acc << 5) + acc) + static_cast<unsigned int>(c); });
return ((checksum << 5) + checksum) + (entry.one_credit_complete ? 1U : 0U);
});
}
// Guarda la tabla en un fichero
+1 -1
View File
@@ -724,7 +724,7 @@ void Scoreboard::renderSeparator() {
// Pinta el carrusel de caracteres con efecto de color LERP y animación suave
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);
const EnterName* enter_name = enter_name_ref_.at(panel_index);
if (enter_name == nullptr) {
return;
}
+2 -5
View File
@@ -3,6 +3,7 @@
#include <algorithm> // Para max, min
#include <exception> // Para exception
#include <fstream> // Para basic_istream, basic_ifstream, ifstream, stringstream
#include <numeric> // Para accumulate
#include <sstream> // Para basic_stringstream
#include <utility> // Para move
@@ -282,11 +283,7 @@ auto StageManager::getPowerNeededForCurrentStage() const -> int {
}
auto StageManager::getTotalPowerNeededToCompleteGame() const -> int {
int total_power_needed = 0;
for (const auto& stage : stages_) {
total_power_needed += stage.getPowerToComplete();
}
return total_power_needed;
return std::accumulate(stages_.begin(), stages_.end(), 0, [](int total, const auto& stage) { return total + stage.getPowerToComplete(); });
}
auto StageManager::getPowerNeededToReachStage(size_t target_stage_index) const -> int {
+27 -27
View File
@@ -2,7 +2,7 @@
#include <SDL3/SDL.h> // Para SDL_ScaleMode, SDL_LogCategory, SDL_LogError, SDL_LogInfo, SDL_LogWarn
#include <algorithm> // Para clamp
#include <algorithm> // Para clamp, ranges::find_if
#include <cstddef> // Para size_t
#include <fstream> // Para ifstream, ofstream
#include <iostream> // Para std::cout
@@ -820,14 +820,14 @@ namespace Options {
continue;
}
for (const auto& physical_gamepad : physical_gamepads) {
if (physical_gamepad->path == desired_path && !isGamepadAssigned(physical_gamepad, assigned_instances)) {
gamepads_[i].instance = physical_gamepad;
gamepads_[i].name = physical_gamepad->name;
assigned_instances.push_back(physical_gamepad);
break;
}
const auto it = std::ranges::find_if(physical_gamepads,
[this, &desired_path, &assigned_instances](const auto& pg) {
return pg->path == desired_path && !isGamepadAssigned(pg, assigned_instances);
});
if (it != physical_gamepads.end()) {
gamepads_[i].instance = *it;
gamepads_[i].name = (*it)->name;
assigned_instances.push_back(*it);
}
}
}
@@ -849,15 +849,15 @@ namespace Options {
continue;
}
for (const auto& physical_gamepad : physical_gamepads) {
if (physical_gamepad->name == desired_name && !isGamepadAssigned(physical_gamepad, assigned_instances)) {
gamepads_[i].instance = physical_gamepad;
gamepads_[i].name = physical_gamepad->name;
gamepads_[i].path = physical_gamepad->path;
assigned_instances.push_back(physical_gamepad);
break;
}
const auto it = std::ranges::find_if(physical_gamepads,
[this, &desired_name, &assigned_instances](const auto& pg) {
return pg->name == desired_name && !isGamepadAssigned(pg, assigned_instances);
});
if (it != physical_gamepads.end()) {
gamepads_[i].instance = *it;
gamepads_[i].name = (*it)->name;
gamepads_[i].path = (*it)->path;
assigned_instances.push_back(*it);
}
}
}
@@ -871,15 +871,15 @@ namespace Options {
continue;
}
for (const auto& physical_gamepad : physical_gamepads) {
if (!isGamepadAssigned(physical_gamepad, assigned_instances)) {
gamepads_[i].instance = physical_gamepad;
gamepads_[i].name = physical_gamepad->name;
gamepads_[i].path = physical_gamepad->path;
assigned_instances.push_back(physical_gamepad);
break;
}
const auto it = std::ranges::find_if(physical_gamepads,
[this, &assigned_instances](const auto& pg) {
return !isGamepadAssigned(pg, assigned_instances);
});
if (it != physical_gamepads.end()) {
gamepads_[i].instance = *it;
gamepads_[i].name = (*it)->name;
gamepads_[i].path = (*it)->path;
assigned_instances.push_back(*it);
}
}
}
+1 -1
View File
@@ -141,7 +141,7 @@ namespace Options {
std::string path; // Ruta física del dispositivo
Player::Id player_id; // Jugador asociado al mando
Gamepad(Player::Id custom_player_id = Player::Id::NO_PLAYER)
explicit Gamepad(Player::Id custom_player_id = Player::Id::NO_PLAYER)
: player_id(custom_player_id) {}
};
+3 -2
View File
@@ -683,10 +683,11 @@ void Credits::startCredits() {
init_right_x_ = static_cast<int>(right_black_rect_.x);
// Objetivos
const int CENTER_X = param.game.game_area.center_x;
int top_target_h = param.game.game_area.center_y - 1;
int bottom_target_y = param.game.game_area.center_y + 1;
int left_target_w = param.game.game_area.center_x;
int right_target_x = param.game.game_area.center_x;
int left_target_w = CENTER_X;
int right_target_x = CENTER_X;
// Pasos verticales
int pasos_top = std::max(0, top_target_h - init_top_h_);
+15 -29
View File
@@ -801,7 +801,7 @@ void Game::renderPathSprites() {
}
// Acciones a realizar cuando el jugador colisiona con un globo
void Game::handlePlayerCollision(std::shared_ptr<Player>& player, std::shared_ptr<Balloon>& balloon) {
void Game::handlePlayerCollision(std::shared_ptr<Player>& player, const std::shared_ptr<Balloon>& balloon) {
if (!player->isPlaying() || player->isInvulnerable()) {
return; // Si no está jugando o tiene inmunidad, no hace nada
}
@@ -1243,18 +1243,6 @@ auto Game::getPlayer(Player::Id id) -> std::shared_ptr<Player> {
return nullptr;
}
// Obtiene un controlador a partir del "id" del jugador
auto Game::getController(Player::Id player_id) -> int {
switch (player_id) {
case Player::Id::PLAYER1:
return 0;
case Player::Id::PLAYER2:
return 1;
default:
return -1;
}
}
// Gestiona la entrada durante el juego
void Game::checkInput() {
Input::get()->update();
@@ -1293,11 +1281,12 @@ void Game::checkInput() {
// Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
void Game::checkPauseInput() {
// Comprueba los mandos
for (const auto& gamepad : input_->getGamepads()) {
if (input_->checkAction(Input::Action::PAUSE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
pause_manager_->togglePlayerPause();
return;
}
const auto& gamepads = input_->getGamepads();
if (std::ranges::any_of(gamepads, [this](const auto& gamepad) {
return input_->checkAction(Input::Action::PAUSE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad);
})) {
pause_manager_->togglePlayerPause();
return;
}
// Comprueba el teclado
@@ -1973,7 +1962,7 @@ void Game::playSound(const std::string& name) const {
return;
}
static auto* audio_ = Audio::get();
static const auto* audio_ = Audio::get();
audio_->playSound(name);
}
@@ -2048,9 +2037,7 @@ void Game::handleGameOverEvents() {
void Game::buildPlayerDrawList(const Players& elements, Players& draw_list) {
draw_list.clear();
draw_list.reserve(elements.size());
for (const auto& e : elements) {
draw_list.push_back(e); // copia el shared_ptr
}
std::ranges::copy(elements, std::back_inserter(draw_list));
std::ranges::stable_sort(draw_list, [](const std::shared_ptr<Player>& a, const std::shared_ptr<Player>& b) -> bool {
return a->getZOrder() < b->getZOrder();
});
@@ -2154,8 +2141,8 @@ void Game::autoplayHandleInput() {
// Comprueba los eventos en el modo DEBUG
void Game::handleDebugEvents(const SDL_Event& event) {
static int formation_id_ = 0;
if (event.type == SDL_EVENT_KEY_DOWN && static_cast<int>(event.key.repeat) == 0) {
static int formation_id_ = 0;
switch (event.key.key) {
case SDLK_1: { // Crea una powerball
balloon_manager_->createPowerBall();
@@ -2196,12 +2183,11 @@ void Game::handleDebugEvents(const SDL_Event& event) {
break;
}
case SDLK_8: {
for (const auto& player : players_) {
if (player->isPlaying()) {
createItem(ItemType::COFFEE_MACHINE, player->getPosX(), param.game.game_area.rect.y - Item::COFFEE_MACHINE_HEIGHT);
coffee_machine_enabled_ = true;
break;
}
const auto it = std::ranges::find_if(players_,
[](const auto& player) { return player->isPlaying(); });
if (it != players_.end()) {
createItem(ItemType::COFFEE_MACHINE, (*it)->getPosX(), param.game.game_area.rect.y - Item::COFFEE_MACHINE_HEIGHT);
coffee_machine_enabled_ = true;
}
break;
}
+3 -4
View File
@@ -227,7 +227,6 @@ class Game {
void updatePlayers(float delta_time); // Actualiza las variables y estados de los jugadores
void renderPlayers(); // Renderiza todos los jugadores en pantalla
auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador por su identificador
static auto getController(Player::Id player_id) -> int; // Obtiene el controlador asignado a un jugador
// --- Estado de jugadores ---
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Actualiza estado entre jugadores
@@ -237,9 +236,9 @@ class Game {
auto allPlayersAreNotPlaying() -> bool; // Verifica si ningún jugador está activo
// --- Colisiones de jugadores ---
void handlePlayerCollision(std::shared_ptr<Player>& player, std::shared_ptr<Balloon>& balloon); // Procesa colisión de jugador con globo
auto checkPlayerBalloonCollision(std::shared_ptr<Player>& player) -> std::shared_ptr<Balloon>; // Detecta colisión jugador-globo
void checkPlayerItemCollision(std::shared_ptr<Player>& player); // Detecta colisión jugador-ítem
void handlePlayerCollision(std::shared_ptr<Player>& player, const std::shared_ptr<Balloon>& balloon); // Procesa colisión de jugador con globo
auto checkPlayerBalloonCollision(std::shared_ptr<Player>& player) -> std::shared_ptr<Balloon>; // Detecta colisión jugador-globo
void checkPlayerItemCollision(std::shared_ptr<Player>& player); // Detecta colisión jugador-ítem
// --- Sistema de entrada (input) ---
void checkInput(); // Gestiona toda la entrada durante el juego
-3
View File
@@ -245,9 +245,6 @@ void Title::run() {
}
}
// Reinicia el contador interno
void Title::resetCounter() { counter_time_ = 0.0F; }
// Intercambia la asignación de mandos a los jugadores
void Title::swapControllers() {
if (Input::get()->getNumGamepads() == 0) {
-1
View File
@@ -107,7 +107,6 @@ class Title {
auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame
void updateState(float delta_time); // Actualiza el estado actual del título
void setState(State state); // Cambia el estado del título
void resetCounter(); // Reinicia el contador interno
// --- Entrada de usuario ---
void checkEvents(); // Comprueba los eventos
+2 -5
View File
@@ -3,6 +3,7 @@
#include <algorithm> // Para max, clamp
#include <cstddef> // Para size_t
#include <functional> // Para function
#include <numeric> // Para accumulate
#include <string> // Para allocator, string, basic_string, to_string, operator==, char_traits
#include <utility> // Para move
#include <vector> // Para vector
@@ -174,11 +175,7 @@ class ListOption : public MenuOption {
setter_(value_list_[list_index_]);
}
auto getMaxValueWidth(Text* text_renderer) const -> int override {
int max_w = 0;
for (const auto& val : value_list_) {
max_w = std::max(max_w, text_renderer->length(val, -2));
}
return max_w;
return std::accumulate(value_list_.begin(), value_list_.end(), 0, [text_renderer](int max_w, const auto& val) { return std::max(max_w, text_renderer->length(val, -2)); });
}
private:
+1 -30
View File
@@ -381,9 +381,7 @@ void MenuRenderer::updatePosition() {
// Resto de métodos (sin cambios significativos)
void MenuRenderer::precalculateMenuWidths(const std::vector<std::unique_ptr<MenuOption>>& all_options, const ServiceMenu* menu_state) { // NOLINT(readability-named-parameter)
for (int& w : group_menu_widths_) {
w = ServiceMenu::MIN_WIDTH;
}
std::ranges::fill(group_menu_widths_, ServiceMenu::MIN_WIDTH);
for (int group = 0; group < 5; ++group) {
auto sg = static_cast<ServiceMenu::SettingsGroup>(group);
int max_option_width = 0;
@@ -433,33 +431,6 @@ auto MenuRenderer::getAnimatedSelectedColor() const -> Color {
static auto color_cycle_ = Colors::generateMirroredCycle(param.service_menu.selected_color, ColorCycleStyle::HUE_WAVE);
return color_cycle_.at(color_counter_ % color_cycle_.size());
}
auto MenuRenderer::setRect(SDL_FRect rect) -> SDL_FRect {
border_rect_ = {.x = rect.x - 1, .y = rect.y + 1, .w = rect.w + 2, .h = rect.h - 2};
return rect;
}
auto MenuRenderer::getTruncatedValueWidth(const std::string& value, int available_width) const -> int {
int value_width = element_text_->length(value, -2);
if (value_width <= available_width) {
return value_width;
}
// Calculamos cuántos caracteres podemos mostrar más los puntos suspensivos
// Estimamos el ancho de los puntos suspensivos como 3 caracteres promedio
int ellipsis_width = element_text_->length("...", -2);
int available_for_text = available_width - ellipsis_width;
if (available_for_text <= 0) {
return ellipsis_width; // Solo mostramos los puntos suspensivos
}
// Calculamos aproximadamente cuántos caracteres caben
float char_width = static_cast<float>(value_width) / value.length();
auto max_chars = static_cast<size_t>(available_for_text / char_width);
// Verificamos el ancho real del texto truncado
std::string truncated = truncateWithEllipsis(value, max_chars);
return element_text_->length(truncated, -2);
}
auto MenuRenderer::getTruncatedValue(const std::string& value, int available_width) const -> std::string {
int value_width = element_text_->length(value, -2);
+6 -5
View File
@@ -82,8 +82,10 @@ class MenuRenderer {
// --- Estructuras de Animación ---
struct ResizeAnimation {
bool active = false;
float start_width, start_height;
float target_width, target_height;
float start_width = 0.0F;
float start_height = 0.0F;
float target_width = 0.0F;
float target_height = 0.0F;
float elapsed = 0.0F;
float duration = 0.2F;
@@ -97,7 +99,8 @@ class MenuRenderer {
HIDING };
Type type = Type::NONE;
bool active = false;
float target_width, target_height;
float target_width = 0.0F;
float target_height = 0.0F;
float elapsed = 0.0F;
float duration = 0.25F;
@@ -140,8 +143,6 @@ class MenuRenderer {
[[nodiscard]] auto getMenuWidthForGroup(ServiceMenu::SettingsGroup group) const -> int;
[[nodiscard]] auto getAnimatedSelectedColor() const -> Color;
void updateColorCounter();
auto setRect(SDL_FRect rect) -> SDL_FRect;
[[nodiscard]] auto getTruncatedValueWidth(const std::string& value, int available_width) const -> int;
[[nodiscard]] auto getTruncatedValue(const std::string& value, int available_width) const -> std::string;
[[nodiscard]] static auto easeOut(float t) -> float;
[[nodiscard]] auto shouldShowContent() const -> bool;
+6 -7
View File
@@ -2,8 +2,9 @@
#include <SDL3/SDL.h> // Para SDL_RenderFillRect, SDL_FRect, SDL_RenderClear
#include <algorithm> // Para remove_if, min
#include <string> // Para basic_string, string
#include <algorithm> // Para ranges::transform, min
#include <iterator> // Para back_inserter
#include <string> // Para basic_string, string, erase_if
#include <utility>
#include <vector> // Para vector
@@ -77,7 +78,7 @@ void Notifier::playNotificationSoundIfNeeded(const Notification& notification) {
}
void Notifier::updateNotificationState(int index, float delta_time) {
auto& notification = notifications_[index];
const auto& notification = notifications_[index];
switch (notification.state) {
case State::RISING:
@@ -167,7 +168,7 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string&
}
// Elimina las cadenas vacías
texts.erase(std::ranges::remove_if(texts, [](const std::string& s) -> bool { return s.empty(); }).begin(), texts.end());
std::erase_if(texts, [](const std::string& s) -> bool { return s.empty(); });
// Encuentra la cadena más larga
std::string longest;
@@ -303,8 +304,6 @@ void Notifier::clearAllNotifications() {
auto Notifier::getCodes() -> std::vector<std::string> {
std::vector<std::string> codes;
codes.reserve(notifications_.size());
for (const auto& notification : notifications_) {
codes.emplace_back(notification.code);
}
std::ranges::transform(notifications_, std::back_inserter(codes), [](const auto& notification) { return notification.code; });
return codes;
}
+17 -24
View File
@@ -1,5 +1,8 @@
#include "game/ui/service_menu.hpp"
#include <algorithm>
#include <iterator>
#include <numeric>
#include <utility>
#include "core/audio/audio.hpp" // Para Audio
@@ -175,7 +178,7 @@ void ServiceMenu::selectOption() {
return;
}
if (auto* folder = dynamic_cast<FolderOption*>(selected_option)) {
if (const auto* folder = dynamic_cast<const FolderOption*>(selected_option)) {
previous_settings_group_ = current_settings_group_;
current_settings_group_ = folder->getTargetGroup();
selected_ = 0;
@@ -200,9 +203,8 @@ void ServiceMenu::updateDisplayOptions() {
void ServiceMenu::updateOptionPairs() {
option_pairs_.clear();
for (const auto& option : display_options_) {
option_pairs_.emplace_back(option->getCaption(), option->getValueAsString());
}
option_pairs_.reserve(display_options_.size());
std::ranges::transform(display_options_, std::back_inserter(option_pairs_), [](const auto* option) { return std::pair{option->getCaption(), option->getValueAsString()}; });
}
void ServiceMenu::updateMenu() {
@@ -250,12 +252,9 @@ void ServiceMenu::applySettingsSettings() {
}
auto ServiceMenu::getOptionByCaption(const std::string& caption) const -> MenuOption* {
for (const auto& option : options_) {
if (option->getCaption() == caption) {
return option.get();
}
}
return nullptr;
const auto it = std::ranges::find_if(options_,
[&caption](const auto& option) { return option->getCaption() == caption; });
return it != options_.end() ? it->get() : nullptr;
}
// --- Getters y otros ---
@@ -273,13 +272,8 @@ auto ServiceMenu::getCurrentGroupAlignment() const -> ServiceMenu::GroupAlignmen
}
auto ServiceMenu::countOptionsInGroup(SettingsGroup group) const -> size_t {
size_t count = 0;
for (const auto& option : options_) {
if (option->getGroup() == group && !option->isHidden()) {
count++;
}
}
return count;
return std::ranges::count_if(options_,
[group](const auto& option) { return option->getGroup() == group && !option->isHidden(); });
}
// Inicializa todas las opciones del menú
@@ -300,7 +294,7 @@ void ServiceMenu::initializeOptions() {
[this]() -> void {
// Acción: configurar botones del mando del jugador 1
auto* gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER1);
if ((gamepad != nullptr) && gamepad->instance) {
if (gamepad->instance != nullptr) {
define_buttons_->enable(gamepad);
}
}));
@@ -318,7 +312,7 @@ void ServiceMenu::initializeOptions() {
[this]() -> void {
// Acción: configurar botones del mando del jugador 2
auto* gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER2);
if ((gamepad != nullptr) && gamepad->instance) {
if (gamepad->instance != nullptr) {
define_buttons_->enable(gamepad);
}
}));
@@ -436,11 +430,10 @@ void ServiceMenu::initializeOptions() {
}
Screen::initShaders();
};
auto preset_max_width = [](Text* text) -> int {
int max_w = 0;
for (const auto& p : Options::postfx_presets) { max_w = std::max(max_w, text->length(p.name, -2)); }
for (const auto& p : Options::crtpi_presets) { max_w = std::max(max_w, text->length(p.name, -2)); }
return max_w;
auto preset_max_width = [](const Text* text) -> int {
const auto presets_length = [text](int max_w, const auto& p) { return std::max(max_w, text->length(p.name, -2)); };
int max_w = std::accumulate(Options::postfx_presets.begin(), Options::postfx_presets.end(), 0, presets_length);
return std::accumulate(Options::crtpi_presets.begin(), Options::crtpi_presets.end(), max_w, presets_length);
};
options_.push_back(std::make_unique<CallbackOption>(
+8 -5
View File
@@ -51,7 +51,7 @@ class WindowMessage {
text_color{200, 200, 200, 255} {}
// Constructor que convierte desde ParamServiceMenu::WindowMessage
Config(const ParamServiceMenu::WindowMessage& param_config)
explicit Config(const ParamServiceMenu::WindowMessage& param_config)
: bg_color(param_config.bg_color),
border_color(param_config.border_color),
title_color(param_config.title_color),
@@ -67,7 +67,7 @@ class WindowMessage {
animation_duration(param_config.animation_duration) {}
};
WindowMessage(
explicit WindowMessage(
std::shared_ptr<Text> text_renderer,
std::string title = "",
const Config& config = Config{});
@@ -148,8 +148,10 @@ class WindowMessage {
// Animación de redimensionado
struct ResizeAnimation {
bool active = false;
float start_width, start_height;
float target_width, target_height;
float start_width = 0.0F;
float start_height = 0.0F;
float target_width = 0.0F;
float target_height = 0.0F;
float elapsed = 0.0F;
void start(float from_w, float from_h, float to_w, float to_h) {
@@ -183,7 +185,8 @@ class WindowMessage {
Type type = Type::NONE;
bool active = false;
float target_width, target_height; // Tamaño final al mostrar
float target_width = 0.0F;
float target_height = 0.0F;
float elapsed = 0.0F;
void startShow(float to_w, float to_h) {
+3 -4
View File
@@ -1,6 +1,7 @@
#define _USE_MATH_DEFINES
#include "utils/color.hpp"
#include <algorithm> // Para ranges::any_of
#include <cctype> // Para isxdigit
#include <cmath> // Para sinf, fmaxf, fminf, M_PI, fmodf, roundf, fmod
#include <cstdint> // Para uint8_t
@@ -22,10 +23,8 @@ auto Color::fromHex(const std::string& hex_str) -> Color {
}
// Verificar que todos los caracteres sean hexadecimales válidos
for (char c : hex) {
if (std::isxdigit(c) == 0) {
throw std::invalid_argument("String contiene caracteres no hexadecimales");
}
if (std::ranges::any_of(hex, [](char c) { return std::isxdigit(c) == 0; })) {
throw std::invalid_argument("String contiene caracteres no hexadecimales");
}
// Convertir cada par de caracteres a valores RGB(A)
-2
View File
@@ -189,8 +189,6 @@ namespace {
{"service_menu.window_message.text_safety_margin", [](const std::string& v) -> void { param.service_menu.window_message.text_safety_margin = std::stof(v); }},
{"service_menu.window_message.animation_duration", [](const std::string& v) -> void { param.service_menu.window_message.animation_duration = std::stof(v); }}};
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS_EXTRA = {};
// Colores válidos para globos
static const std::unordered_map<std::string, bool> VALID_BALLOON_COLORS = {
{"blue", true},
+1 -1
View File
@@ -52,7 +52,7 @@ struct ParamBalloon {
float vel;
// Constructor por defecto
constexpr Settings(float grav_val = 0.0F, float vel_val = 0.0F)
explicit constexpr Settings(float grav_val = 0.0F, float vel_val = 0.0F)
: grav(grav_val),
vel(vel_val) {}
};