fix: resta tidy (60 troballes — empty-catch, widening, branch-clone, etc.)

This commit is contained in:
2026-05-14 23:55:44 +02:00
parent f047ae1a56
commit 8f5d897048
23 changed files with 163 additions and 193 deletions

View File

@@ -8,6 +8,7 @@
// Implementación de stb_vorbis (debe estar ANTES de incluir jail_audio.hpp). // Implementación de stb_vorbis (debe estar ANTES de incluir jail_audio.hpp).
// clang-format off // clang-format off
#undef STB_VORBIS_HEADER_ONLY #undef STB_VORBIS_HEADER_ONLY
// NOLINTNEXTLINE(bugprone-suspicious-include) — stb_vorbis és single-file: el TU principal inclou el .c per portar la implementació.
#include "external/stb_vorbis.c" #include "external/stb_vorbis.c"
// stb_vorbis.c filtra les macros L, C i R (i PLAYBACK_*) al TU. Les netegem // stb_vorbis.c filtra les macros L, C i R (i PLAYBACK_*) al TU. Les netegem
// perquè xocarien amb noms de paràmetres de plantilla en altres headers. // perquè xocarien amb noms de paràmetres de plantilla en altres headers.

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cmath> // Para std::lround
#include <cstdint> // Para int8_t, uint8_t #include <cstdint> // Para int8_t, uint8_t
#include <string> // Para string #include <string> // Para string
#include <utility> // Para move #include <utility> // Para move
@@ -64,8 +65,8 @@ class Audio {
// --- Helpers de conversió per a la capa de presentació --- // --- Helpers de conversió per a la capa de presentació ---
// UI (menús, notificacions) manega enters 0..100; internament viu float 0..1. // UI (menús, notificacions) manega enters 0..100; internament viu float 0..1.
static constexpr auto toPercent(float volume) -> int { static auto toPercent(float volume) -> int {
return static_cast<int>(volume * 100.0F + 0.5F); return static_cast<int>(std::lround(volume * 100.0F));
} }
static constexpr auto fromPercent(int percent) -> float { static constexpr auto fromPercent(int percent) -> float {
return static_cast<float>(percent) / 100.0F; return static_cast<float>(percent) / 100.0F;

View File

@@ -57,12 +57,14 @@ namespace Ja {
std::unique_ptr<Uint8[], SdlFreeDeleter> buffer; std::unique_ptr<Uint8[], SdlFreeDeleter> buffer;
}; };
// L'ordre (punters primer, ints després, enum de 8 bits al final) minimitza
// el padding a 64-bit (evita avisos de clang-analyzer-optin.performance.Padding).
struct Channel { struct Channel {
Sound* sound{nullptr}; Sound* sound{nullptr};
SDL_AudioStream* stream{nullptr};
int pos{0}; int pos{0};
int times{0}; int times{0};
int group{0}; int group{0};
SDL_AudioStream* stream{nullptr};
ChannelState state{ChannelState::FREE}; ChannelState state{ChannelState::FREE};
}; };
@@ -314,7 +316,11 @@ namespace Ja {
std::fseek(f, 0, SEEK_END); std::fseek(f, 0, SEEK_END);
const long FSIZE = std::ftell(f); const long FSIZE = std::ftell(f);
std::fseek(f, 0, SEEK_SET); std::fseek(f, 0, SEEK_SET);
auto* buffer = static_cast<Uint8*>(std::malloc(FSIZE + 1)); if (FSIZE <= 0) {
std::fclose(f);
return nullptr;
}
auto* buffer = static_cast<Uint8*>(std::malloc(static_cast<size_t>(FSIZE) + 1));
if (buffer == nullptr) { if (buffer == nullptr) {
std::fclose(f); std::fclose(f);
return nullptr; return nullptr;
@@ -520,7 +526,7 @@ namespace Ja {
inline auto loadSound(std::uint8_t* buffer, std::uint32_t size) -> Sound* { inline auto loadSound(std::uint8_t* buffer, std::uint32_t size) -> Sound* {
auto sound = std::make_unique<Sound>(); auto sound = std::make_unique<Sound>();
Uint8* raw = nullptr; Uint8* raw = nullptr;
if (!SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size), 1, &sound->spec, &raw, &sound->length)) { if (!SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size), true, &sound->spec, &raw, &sound->length)) {
std::cout << "Failed to load WAV from memory: " << SDL_GetError() << '\n'; std::cout << "Failed to load WAV from memory: " << SDL_GetError() << '\n';
return nullptr; return nullptr;
} }

View File

@@ -425,9 +425,10 @@ auto Input::handleEvent(const SDL_Event& event) -> std::string { // NOLINT(read
return addGamepad(event.gdevice.which); return addGamepad(event.gdevice.which);
case SDL_EVENT_GAMEPAD_REMOVED: case SDL_EVENT_GAMEPAD_REMOVED:
return removeGamepad(event.gdevice.which); return removeGamepad(event.gdevice.which);
} default:
return {}; return {};
} }
}
auto Input::addGamepad(int device_index) -> std::string { // NOLINT(readability-convert-member-functions-to-static) auto Input::addGamepad(int device_index) -> std::string { // NOLINT(readability-convert-member-functions-to-static)
installWebStandardMapping(device_index); installWebStandardMapping(device_index);

View File

@@ -55,8 +55,8 @@ class Input {
// Evita nombres como "Retroid Controller (vendor: 1001) ..." en las notificaciones. // Evita nombres como "Retroid Controller (vendor: 1001) ..." en las notificaciones.
static auto trimName(const char* raw) -> std::string { static auto trimName(const char* raw) -> std::string {
std::string s(raw != nullptr ? raw : ""); std::string s(raw != nullptr ? raw : "");
const auto pos = s.find_first_of("(["); const auto POS = s.find_first_of("([");
if (pos != std::string::npos) { s.erase(pos); } if (POS != std::string::npos) { s.erase(POS); }
while (!s.empty() && s.back() == ' ') { s.pop_back(); } while (!s.empty() && s.back() == ' ') { s.pop_back(); }
return s; return s;
} }

View File

@@ -224,8 +224,8 @@ namespace GIF {
if ((screen_descriptor.fields & 0x80) != 0) { if ((screen_descriptor.fields & 0x80) != 0) {
int global_color_table_size = 1 << ((screen_descriptor.fields & 0x07) + 1); int global_color_table_size = 1 << ((screen_descriptor.fields & 0x07) + 1);
global_color_table.resize(global_color_table_size); global_color_table.resize(global_color_table_size);
std::memcpy(global_color_table.data(), buffer, 3 * global_color_table_size); std::memcpy(global_color_table.data(), buffer, static_cast<size_t>(3) * global_color_table_size);
buffer += 3 * global_color_table_size; buffer += static_cast<ptrdiff_t>(3) * global_color_table_size;
} }
// Supongamos que 'buffer' es el puntero actual y TRAILER es 0x3B // Supongamos que 'buffer' es el puntero actual y TRAILER es 0x3B

View File

@@ -475,13 +475,13 @@ void Screen::textureToRenderer() {
// Franjas superior e inferior (ancho completo) // Franjas superior e inferior (ancho completo)
std::fill_n(border_pixel_buffer_.data(), OFF_Y * BORDER_W, border_argb_color_); std::fill_n(border_pixel_buffer_.data(), OFF_Y * BORDER_W, border_argb_color_);
std::fill_n(&border_pixel_buffer_[(OFF_Y + GAME_H) * BORDER_W], std::fill_n(&border_pixel_buffer_[static_cast<size_t>(OFF_Y + GAME_H) * BORDER_W],
(BORDER_H - OFF_Y - GAME_H) * BORDER_W, (BORDER_H - OFF_Y - GAME_H) * BORDER_W,
border_argb_color_); border_argb_color_);
// Columnas laterales en las filas del área de juego // Columnas laterales en las filas del área de juego
for (int y = OFF_Y; y < OFF_Y + GAME_H; ++y) { for (int y = OFF_Y; y < OFF_Y + GAME_H; ++y) {
std::fill_n(&border_pixel_buffer_[y * BORDER_W], OFF_X, border_argb_color_); std::fill_n(&border_pixel_buffer_[static_cast<size_t>(y) * BORDER_W], OFF_X, border_argb_color_);
std::fill_n(&border_pixel_buffer_[(y * BORDER_W) + OFF_X + GAME_W], std::fill_n(&border_pixel_buffer_[(static_cast<size_t>(y) * BORDER_W) + OFF_X + GAME_W],
BORDER_W - OFF_X - GAME_W, BORDER_W - OFF_X - GAME_W,
border_argb_color_); border_argb_color_);
} }
@@ -494,7 +494,7 @@ void Screen::textureToRenderer() {
// Overlay del juego sobre el centro del buffer (ambos paths) // Overlay del juego sobre el centro del buffer (ambos paths)
game_surface_->toARGBBuffer(game_pixel_buffer_.data()); game_surface_->toARGBBuffer(game_pixel_buffer_.data());
for (int y = 0; y < GAME_H; ++y) { for (int y = 0; y < GAME_H; ++y) {
const Uint32* src = &game_pixel_buffer_[y * GAME_W]; const Uint32* src = &game_pixel_buffer_[static_cast<size_t>(y) * GAME_W];
Uint32* dst = &border_pixel_buffer_[((OFF_Y + y) * BORDER_W) + OFF_X]; Uint32* dst = &border_pixel_buffer_[((OFF_Y + y) * BORDER_W) + OFF_X];
std::memcpy(dst, src, GAME_W * sizeof(Uint32)); std::memcpy(dst, src, GAME_W * sizeof(Uint32));
} }

View File

@@ -762,7 +762,7 @@ namespace Rendering {
} }
// Copia directa — el upscale lo hace la GPU en el primer render pass // Copia directa — el upscale lo hace la GPU en el primer render pass
std::memcpy(mapped, pixels, static_cast<size_t>(width * height * 4)); std::memcpy(mapped, pixels, static_cast<size_t>(width) * static_cast<size_t>(height) * 4);
SDL_UnmapGPUTransferBuffer(device_, upload_buffer_); SDL_UnmapGPUTransferBuffer(device_, upload_buffer_);
} }

View File

@@ -10,10 +10,10 @@ class Surface; // lines 5-5
class Sprite { class Sprite {
public: public:
// Constructores // Constructores
Sprite(std::shared_ptr<Surface>, float x, float y, float w, float h); Sprite(std::shared_ptr<Surface> surface, float x, float y, float w, float h);
Sprite(std::shared_ptr<Surface>, SDL_FRect rect); Sprite(std::shared_ptr<Surface> surface, SDL_FRect rect);
Sprite(); Sprite();
explicit Sprite(std::shared_ptr<Surface>); explicit Sprite(std::shared_ptr<Surface> surface);
// Destructor // Destructor
virtual ~Sprite() = default; virtual ~Sprite() = default;

View File

@@ -180,7 +180,7 @@ void Surface::fillRect(const SDL_FRect* rect, Uint8 color) { // NOLINT(readabil
const int SURF_WIDTH = surface_data_->width; const int SURF_WIDTH = surface_data_->width;
const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start); const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start);
for (int y = static_cast<int>(y_start); y < static_cast<int>(y_end); ++y) { for (int y = static_cast<int>(y_start); y < static_cast<int>(y_end); ++y) {
std::memset(data_ptr + (y * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH); std::memset(data_ptr + (static_cast<ptrdiff_t>(y) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
} }
} }
@@ -196,8 +196,8 @@ void Surface::drawRectBorder(const SDL_FRect* rect, Uint8 color) { // NOLINT(re
Uint8* data_ptr = surface_data_->data.get(); Uint8* data_ptr = surface_data_->data.get();
const int SURF_WIDTH = surface_data_->width; const int SURF_WIDTH = surface_data_->width;
const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start); const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start);
std::memset(data_ptr + (static_cast<int>(y_start) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH); std::memset(data_ptr + (static_cast<ptrdiff_t>(y_start) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
std::memset(data_ptr + ((static_cast<int>(y_end) - 1) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH); std::memset(data_ptr + ((static_cast<ptrdiff_t>(y_end) - 1) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
// Dibujar bordes verticales // Dibujar bordes verticales
for (int y = y_start; y < y_end; ++y) { for (int y = y_start; y < y_end; ++y) {
@@ -539,8 +539,8 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture) { //
const int WIDTH = surface_data_->width; const int WIDTH = surface_data_->width;
const int HEIGHT = surface_data_->height; const int HEIGHT = surface_data_->height;
for (int y = 0; y < HEIGHT; ++y) { for (int y = 0; y < HEIGHT; ++y) {
const Uint8* src_row = src + (y * WIDTH); const Uint8* src_row = src + (static_cast<ptrdiff_t>(y) * WIDTH);
Uint32* dst_row = pixels + (y * row_stride); Uint32* dst_row = pixels + (static_cast<ptrdiff_t>(y) * row_stride);
for (int x = 0; x < WIDTH; ++x) { for (int x = 0; x < WIDTH; ++x) {
dst_row[x] = pal[src_row[x]]; dst_row[x] = pal[src_row[x]];
} }
@@ -588,8 +588,8 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FR
const int WIDTH = surface_data_->width; const int WIDTH = surface_data_->width;
const int HEIGHT = surface_data_->height; const int HEIGHT = surface_data_->height;
for (int y = 0; y < HEIGHT; ++y) { for (int y = 0; y < HEIGHT; ++y) {
const Uint8* src_row = src + (y * WIDTH); const Uint8* src_row = src + (static_cast<ptrdiff_t>(y) * WIDTH);
Uint32* dst_row = pixels + (y * row_stride); Uint32* dst_row = pixels + (static_cast<ptrdiff_t>(y) * row_stride);
for (int x = 0; x < WIDTH; ++x) { for (int x = 0; x < WIDTH; ++x) {
dst_row[x] = pal[src_row[x]]; dst_row[x] = pal[src_row[x]];
} }

View File

@@ -22,11 +22,11 @@ auto Text::nextCodepoint(const std::string& s, size_t& pos) -> uint32_t { // NO
if (c < 0x80) { if (c < 0x80) {
cp = c; cp = c;
extra = 0; extra = 0;
} else if (c < 0xC0) { } else if (c < 0xE0) {
if (c < 0xC0) {
pos++; pos++;
return 0xFFFD; return 0xFFFD; // byte de continuación suelto
} // byte de continuación suelto }
else if (c < 0xE0) {
cp = c & 0x1F; cp = c & 0x1F;
extra = 1; extra = 1;
} else if (c < 0xF0) { } else if (c < 0xF0) {
@@ -260,7 +260,7 @@ void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerni
if (COLORED) { if (COLORED) {
writeColored(x, y, text, text_color, kerning, lenght); writeColored(x, y, text, text_color, kerning, lenght);
} else { } else {
writeColored(x, y, text, text_color, kerning, lenght); write(x, y, text, kerning, lenght);
} }
} }

View File

@@ -87,123 +87,73 @@ namespace Resource {
return stage_ == LoadStage::DONE; return stage_ == LoadStage::DONE;
} }
// Helper per a una etapa que itera una llista de recursos.
// Imprimeix la capçalera i neteja el vector al primer cop; després carrega
// un element per crida fins exhaurir la llista, moment en què passa a `next`.
void Cache::stepEachInList(List::Type type, const char* header, const std::function<void()>& clear_fn, LoadStage next, const std::function<void(size_t)>& load_fn) {
auto list = List::get()->getListByType(type);
if (stage_index_ == 0) {
std::cout << "\n>> " << header << '\n';
clear_fn();
}
if (stage_index_ >= list.size()) {
stage_ = next;
stage_index_ = 0;
return;
}
load_fn(stage_index_++);
}
// Carga assets hasta agotar el presupuesto de tiempo o completar todas las etapas. // Carga assets hasta agotar el presupuesto de tiempo o completar todas las etapas.
// Devuelve true cuando ya no queda nada por cargar. // Devuelve true cuando ya no queda nada por cargar.
auto Cache::loadStep(int budget_ms) -> bool { auto Cache::loadStep(int budget_ms) -> bool {
if (stage_ == LoadStage::DONE) { return true; } if (stage_ == LoadStage::DONE) { return true; }
const Uint64 start_ns = SDL_GetTicksNS(); const Uint64 START_NS = SDL_GetTicksNS();
const Uint64 budget_ns = static_cast<Uint64>(budget_ms) * 1'000'000ULL; const Uint64 BUDGET_NS = static_cast<Uint64>(budget_ms) * 1'000'000ULL;
auto listOf = [](List::Type t) { return List::get()->getListByType(t); };
while (stage_ != LoadStage::DONE) { while (stage_ != LoadStage::DONE) {
switch (stage_) { switch (stage_) {
case LoadStage::SOUNDS: { case LoadStage::SOUNDS:
auto list = listOf(List::Type::SOUND); stepEachInList(List::Type::SOUND, "SOUND FILES", [this] { sounds_.clear(); }, LoadStage::MUSICS, [this](size_t i) { loadOneSound(i); });
if (stage_index_ == 0) {
std::cout << "\n>> SOUND FILES" << '\n';
sounds_.clear();
}
if (stage_index_ >= list.size()) {
stage_ = LoadStage::MUSICS;
stage_index_ = 0;
break; break;
} case LoadStage::MUSICS:
loadOneSound(stage_index_++); stepEachInList(List::Type::MUSIC, "MUSIC FILES", [this] { musics_.clear(); }, LoadStage::SURFACES, [this](size_t i) { loadOneMusic(i); });
break; break;
} case LoadStage::SURFACES:
case LoadStage::MUSICS: { stepEachInList(List::Type::BITMAP, "SURFACES", [this] { surfaces_.clear(); }, LoadStage::SURFACES_POST, [this](size_t i) { loadOneSurface(i); });
auto list = listOf(List::Type::MUSIC);
if (stage_index_ == 0) {
std::cout << "\n>> MUSIC FILES" << '\n';
musics_.clear();
}
if (stage_index_ >= list.size()) {
stage_ = LoadStage::SURFACES;
stage_index_ = 0;
break; break;
} case LoadStage::SURFACES_POST:
loadOneMusic(stage_index_++);
break;
}
case LoadStage::SURFACES: {
auto list = listOf(List::Type::BITMAP);
if (stage_index_ == 0) {
std::cout << "\n>> SURFACES" << '\n';
surfaces_.clear();
}
if (stage_index_ >= list.size()) {
stage_ = LoadStage::SURFACES_POST;
stage_index_ = 0;
break;
}
loadOneSurface(stage_index_++);
break;
}
case LoadStage::SURFACES_POST: {
finalizeSurfaces(); finalizeSurfaces();
stage_ = LoadStage::PALETTES; stage_ = LoadStage::PALETTES;
stage_index_ = 0; stage_index_ = 0;
break; break;
} case LoadStage::PALETTES:
case LoadStage::PALETTES: { stepEachInList(List::Type::PALETTE, "PALETTES", [this] { palettes_.clear(); }, LoadStage::TEXT_FILES, [this](size_t i) { loadOnePalette(i); });
auto list = listOf(List::Type::PALETTE); break;
if (stage_index_ == 0) { case LoadStage::TEXT_FILES:
std::cout << "\n>> PALETTES" << '\n'; stepEachInList(List::Type::FONT, "TEXT FILES", [this] { text_files_.clear(); }, LoadStage::ANIMATIONS, [this](size_t i) { loadOneTextFile(i); });
palettes_.clear(); break;
} case LoadStage::ANIMATIONS:
if (stage_index_ >= list.size()) { stepEachInList(List::Type::ANIMATION, "ANIMATIONS", [this] { animations_.clear(); }, LoadStage::ROOMS, [this](size_t i) { loadOneAnimation(i); });
stage_ = LoadStage::TEXT_FILES; break;
stage_index_ = 0; case LoadStage::ROOMS:
stepEachInList(List::Type::ROOM, "ROOMS", [this] { rooms_.clear(); }, LoadStage::TEXTS, [this](size_t i) { loadOneRoom(i); });
break;
case LoadStage::TEXTS:
stepTexts();
break;
case LoadStage::DONE:
break; break;
} }
loadOnePalette(stage_index_++);
break; if ((SDL_GetTicksNS() - START_NS) >= BUDGET_NS) { break; }
} }
case LoadStage::TEXT_FILES: {
auto list = listOf(List::Type::FONT); return stage_ == LoadStage::DONE;
if (stage_index_ == 0) {
std::cout << "\n>> TEXT FILES" << '\n';
text_files_.clear();
} }
if (stage_index_ >= list.size()) {
stage_ = LoadStage::ANIMATIONS; void Cache::stepTexts() {
stage_index_ = 0;
break;
}
loadOneTextFile(stage_index_++);
break;
}
case LoadStage::ANIMATIONS: {
auto list = listOf(List::Type::ANIMATION);
if (stage_index_ == 0) {
std::cout << "\n>> ANIMATIONS" << '\n';
animations_.clear();
}
if (stage_index_ >= list.size()) {
stage_ = LoadStage::ROOMS;
stage_index_ = 0;
break;
}
loadOneAnimation(stage_index_++);
break;
}
case LoadStage::ROOMS: {
auto list = listOf(List::Type::ROOM);
if (stage_index_ == 0) {
std::cout << "\n>> ROOMS" << '\n';
rooms_.clear();
}
if (stage_index_ >= list.size()) {
stage_ = LoadStage::TEXTS;
stage_index_ = 0;
break;
}
loadOneRoom(stage_index_++);
break;
}
case LoadStage::TEXTS: {
// createText itera sobre una lista fija de 5 fuentes // createText itera sobre una lista fija de 5 fuentes
constexpr size_t TEXT_COUNT = 5; constexpr size_t TEXT_COUNT = 5;
if (stage_index_ == 0) { if (stage_index_ == 0) {
@@ -214,19 +164,9 @@ namespace Resource {
stage_ = LoadStage::DONE; stage_ = LoadStage::DONE;
stage_index_ = 0; stage_index_ = 0;
std::cout << "\n** RESOURCES LOADED" << '\n'; std::cout << "\n** RESOURCES LOADED" << '\n';
break; return;
} }
createOneText(stage_index_++); createOneText(stage_index_++);
break;
}
case LoadStage::DONE:
break;
}
if ((SDL_GetTicksNS() - start_ns) >= budget_ns) { break; }
}
return stage_ == LoadStage::DONE;
} }
// Recarga todos los recursos (síncrono, solo para hot-reload de debug) // Recarga todos los recursos (síncrono, solo para hot-reload de debug)
@@ -382,13 +322,13 @@ namespace Resource {
}; };
auto getTextObjectInfos() -> const std::vector<TextObjectInfo>& { auto getTextObjectInfos() -> const std::vector<TextObjectInfo>& {
static const std::vector<TextObjectInfo> info = { static const std::vector<TextObjectInfo> INFO = {
{.key = "aseprite", .texture_file = "aseprite.gif", .text_file = "aseprite.fnt"}, {.key = "aseprite", .texture_file = "aseprite.gif", .text_file = "aseprite.fnt"},
{.key = "gauntlet", .texture_file = "gauntlet.gif", .text_file = "gauntlet.fnt"}, {.key = "gauntlet", .texture_file = "gauntlet.gif", .text_file = "gauntlet.fnt"},
{.key = "smb2", .texture_file = "smb2.gif", .text_file = "smb2.fnt"}, {.key = "smb2", .texture_file = "smb2.gif", .text_file = "smb2.fnt"},
{.key = "subatomic", .texture_file = "subatomic.gif", .text_file = "subatomic.fnt"}, {.key = "subatomic", .texture_file = "subatomic.gif", .text_file = "subatomic.fnt"},
{.key = "8bithud", .texture_file = "8bithud.gif", .text_file = "8bithud.fnt"}}; {.key = "8bithud", .texture_file = "8bithud.gif", .text_file = "8bithud.fnt"}};
return info; return INFO;
} }
} // namespace } // namespace

View File

@@ -1,11 +1,13 @@
#pragma once #pragma once
#include <cstdint> // Para uint8_t #include <cstdint> // Para uint8_t
#include <functional> // Para std::function
#include <memory> // Para shared_ptr #include <memory> // Para shared_ptr
#include <string> // Para string #include <string> // Para string
#include <utility> #include <utility>
#include <vector> // Para vector #include <vector> // Para vector
#include "core/resources/resource_list.hpp" // Para List::Type
#include "core/resources/resource_types.hpp" // Para structs de recursos #include "core/resources/resource_types.hpp" // Para structs de recursos
namespace Resource { namespace Resource {
@@ -103,6 +105,11 @@ namespace Resource {
// Helper para mensajes de error de carga // Helper para mensajes de error de carga
static void logLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e); static void logLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e);
// Helper d'iteració per a una etapa que recorre una llista de recursos.
// Crida `load_fn(i)` per a cada element i, en exhaurir-se, transiciona a `next`.
void stepEachInList(List::Type type, const char* header, const std::function<void()>& clear_fn, LoadStage next, const std::function<void(size_t)>& load_fn);
void stepTexts(); // Etapa especial: no usa List, itera sobre TEXT_COUNT fonts fixes.
// Constructor y destructor // Constructor y destructor
Cache(); Cache();
~Cache() = default; ~Cache() = default;

View File

@@ -13,7 +13,7 @@ namespace GlobalEvents {
namespace { namespace {
// Flag per saber si en aquest frame s'ha rebut un button down del gamepad. // Flag per saber si en aquest frame s'ha rebut un button down del gamepad.
// El consumeix GlobalInputs perquè un botó del comandament salti escenes. // El consumeix GlobalInputs perquè un botó del comandament salti escenes.
bool gamepad_button_pressed_ = false; bool gamepad_button_pressed = false;
} // namespace } // namespace
// Comprueba los eventos que se pueden producir en cualquier sección del juego. // Comprueba los eventos que se pueden producir en cualquier sección del juego.
@@ -56,7 +56,7 @@ namespace GlobalEvents {
const bool RESERVE_BACK = IS_BACK; const bool RESERVE_BACK = IS_BACK;
#endif #endif
if (!RESERVE_BACK && !IS_SHOULDER) { if (!RESERVE_BACK && !IS_SHOULDER) {
gamepad_button_pressed_ = true; gamepad_button_pressed = true;
} }
} }
@@ -72,8 +72,8 @@ namespace GlobalEvents {
} }
auto consumeGamepadButtonPressed() -> bool { auto consumeGamepadButtonPressed() -> bool {
const bool RESULT = gamepad_button_pressed_; const bool RESULT = gamepad_button_pressed;
gamepad_button_pressed_ = false; gamepad_button_pressed = false;
return RESULT; return RESULT;
} }
} // namespace GlobalEvents } // namespace GlobalEvents

View File

@@ -836,8 +836,6 @@ void Player::updateVelocity() {
sprite_->setFlip(Flip::RIGHT); sprite_->setFlip(Flip::RIGHT);
break; break;
case Direction::NONE: case Direction::NONE:
vx_ = 0.0F;
break;
default: default:
vx_ = 0.0F; vx_ = 0.0F;
break; break;

View File

@@ -368,12 +368,14 @@ namespace Options {
if (sh_node.contains("current_postfx_preset")) { if (sh_node.contains("current_postfx_preset")) {
try { try {
video.shader.current_postfx_preset_name = sh_node["current_postfx_preset"].get_value<std::string>(); video.shader.current_postfx_preset_name = sh_node["current_postfx_preset"].get_value<std::string>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (sh_node.contains("current_crtpi_preset")) { if (sh_node.contains("current_crtpi_preset")) {
try { try {
video.shader.current_crtpi_preset_name = sh_node["current_crtpi_preset"].get_value<std::string>(); video.shader.current_crtpi_preset_name = sh_node["current_crtpi_preset"].get_value<std::string>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
} }
@@ -573,24 +575,28 @@ namespace Options {
if (a.contains("enabled")) { if (a.contains("enabled")) {
try { try {
audio.enabled = a["enabled"].get_value<bool>(); audio.enabled = a["enabled"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (a.contains("volume")) { if (a.contains("volume")) {
try { try {
audio.volume = std::clamp(a["volume"].get_value<float>(), 0.0F, 1.0F); audio.volume = std::clamp(a["volume"].get_value<float>(), 0.0F, 1.0F);
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (a.contains("music")) { if (a.contains("music")) {
const auto& m = a["music"]; const auto& m = a["music"];
if (m.contains("enabled")) { if (m.contains("enabled")) {
try { try {
audio.music.enabled = m["enabled"].get_value<bool>(); audio.music.enabled = m["enabled"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (m.contains("volume")) { if (m.contains("volume")) {
try { try {
audio.music.volume = std::clamp(m["volume"].get_value<float>(), 0.0F, 1.0F); audio.music.volume = std::clamp(m["volume"].get_value<float>(), 0.0F, 1.0F);
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
} }
if (a.contains("sound")) { if (a.contains("sound")) {
@@ -598,12 +604,14 @@ namespace Options {
if (s.contains("enabled")) { if (s.contains("enabled")) {
try { try {
audio.sound.enabled = s["enabled"].get_value<bool>(); audio.sound.enabled = s["enabled"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (s.contains("volume")) { if (s.contains("volume")) {
try { try {
audio.sound.volume = std::clamp(s["volume"].get_value<float>(), 0.0F, 1.0F); audio.sound.volume = std::clamp(s["volume"].get_value<float>(), 0.0F, 1.0F);
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
} }
} }
@@ -891,7 +899,8 @@ namespace Options {
if (node.contains(key)) { if (node.contains(key)) {
try { try {
target = node[key].get_value<float>(); target = node[key].get_value<float>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
} }
@@ -1181,32 +1190,38 @@ namespace Options {
if (p.contains("mask_type")) { if (p.contains("mask_type")) {
try { try {
preset.mask_type = p["mask_type"].get_value<int>(); preset.mask_type = p["mask_type"].get_value<int>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (p.contains("enable_scanlines")) { if (p.contains("enable_scanlines")) {
try { try {
preset.enable_scanlines = p["enable_scanlines"].get_value<bool>(); preset.enable_scanlines = p["enable_scanlines"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (p.contains("enable_multisample")) { if (p.contains("enable_multisample")) {
try { try {
preset.enable_multisample = p["enable_multisample"].get_value<bool>(); preset.enable_multisample = p["enable_multisample"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (p.contains("enable_gamma")) { if (p.contains("enable_gamma")) {
try { try {
preset.enable_gamma = p["enable_gamma"].get_value<bool>(); preset.enable_gamma = p["enable_gamma"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (p.contains("enable_curvature")) { if (p.contains("enable_curvature")) {
try { try {
preset.enable_curvature = p["enable_curvature"].get_value<bool>(); preset.enable_curvature = p["enable_curvature"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
if (p.contains("enable_sharper")) { if (p.contains("enable_sharper")) {
try { try {
preset.enable_sharper = p["enable_sharper"].get_value<bool>(); preset.enable_sharper = p["enable_sharper"].get_value<bool>();
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
} }
crtpi_presets.push_back(preset); crtpi_presets.push_back(preset);
} }

View File

@@ -238,9 +238,6 @@ void Logo::endSection() {
break; break;
case SceneManager::Options::LOGO_TO_LOADING_SCREEN: case SceneManager::Options::LOGO_TO_LOADING_SCREEN:
SceneManager::current = SceneManager::Scene::LOADING_SCREEN;
break;
default: default:
SceneManager::current = SceneManager::Scene::LOADING_SCREEN; SceneManager::current = SceneManager::Scene::LOADING_SCREEN;
break; break;

View File

@@ -66,9 +66,11 @@ auto Console::wrapText(const std::string& text) const -> std::vector<std::string
std::istringstream word_stream(segment); std::istringstream word_stream(segment);
std::string word; std::string word;
while (word_stream >> word) { while (word_stream >> word) {
const std::string TEST = current_line.empty() ? word : (current_line + ' ' + word); std::string test = current_line;
if (text_->length(TEST) <= MAX_PX) { if (!test.empty()) { test += ' '; }
current_line = TEST; test += word;
if (text_->length(test) <= MAX_PX) {
current_line = std::move(test);
} else { } else {
if (!current_line.empty()) { result.push_back(current_line); } if (!current_line.empty()) { result.push_back(current_line); }
current_line = word; current_line = word;
@@ -182,10 +184,10 @@ void Console::update(float delta_time) { // NOLINT(readability-function-cogniti
// Efecto typewriter: revelar letras una a una (solo cuando ACTIVE) // Efecto typewriter: revelar letras una a una (solo cuando ACTIVE)
if (status_ == Status::ACTIVE) { if (status_ == Status::ACTIVE) {
const int total_chars = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, [](int acc, const auto& line) { return acc + static_cast<int>(line.size()); }); const int TOTAL_CHARS = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, [](int acc, const auto& line) { return acc + static_cast<int>(line.size()); });
if (typewriter_chars_ < total_chars) { if (typewriter_chars_ < TOTAL_CHARS) {
typewriter_timer_ += delta_time; typewriter_timer_ += delta_time;
while (typewriter_timer_ >= TYPEWRITER_CHAR_DELAY && typewriter_chars_ < total_chars) { while (typewriter_timer_ >= TYPEWRITER_CHAR_DELAY && typewriter_chars_ < TOTAL_CHARS) {
typewriter_timer_ -= TYPEWRITER_CHAR_DELAY; typewriter_timer_ -= TYPEWRITER_CHAR_DELAY;
++typewriter_chars_; ++typewriter_chars_;
} }
@@ -345,7 +347,10 @@ void Console::handleEvent(const SDL_Event& event) { // NOLINT(readability-funct
const auto OPTS = registry_.getCompletions(BASE_CMD); const auto OPTS = registry_.getCompletions(BASE_CMD);
for (const auto& arg : OPTS) { for (const auto& arg : OPTS) {
if (SUB_PREFIX.empty() || std::string_view{arg}.starts_with(SUB_PREFIX)) { if (SUB_PREFIX.empty() || std::string_view{arg}.starts_with(SUB_PREFIX)) {
tab_matches_.emplace_back(BASE_CMD + " " + arg); std::string match = BASE_CMD;
match += ' ';
match += arg;
tab_matches_.push_back(std::move(match));
} }
} }
} }

View File

@@ -259,7 +259,8 @@ static auto cmdZoom(const std::vector<std::string>& args) -> std::string {
if (N == Options::window.zoom) { return "Zoom already " + std::to_string(N); } if (N == Options::window.zoom) { return "Zoom already " + std::to_string(N); }
Screen::get()->setWindowZoom(N); Screen::get()->setWindowZoom(N);
return "Zoom " + std::to_string(Options::window.zoom); return "Zoom " + std::to_string(Options::window.zoom);
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
return "usage: zoom [up|down|<1-" + std::to_string(Screen::getMaxZoom()) + ">]"; return "usage: zoom [up|down|<1-" + std::to_string(Screen::getMaxZoom()) + ">]";
} }
@@ -912,7 +913,8 @@ static auto cmdPlayer(const std::vector<std::string>& args) -> std::string {
int color = -1; int color = -1;
try { try {
color = std::stoi(args[1]); color = std::stoi(args[1]);
} catch (...) {} } catch (...) { /* @INTENTIONAL: camp YAML malformat → conservem default */
}
if (color < 0 || color > 15) { return "usage: player color <0-15>|default"; } if (color < 0 || color > 15) { return "usage: player color <0-15>|default"; }
if (!GameControl::change_player_color) { return "Game not initialized"; } if (!GameControl::change_player_color) { return "Game not initialized"; }
GameControl::change_player_color(color); GameControl::change_player_color(color);

View File

@@ -117,8 +117,6 @@ void Notifier::update(float delta_time) {
} }
case Status::FINISHED: case Status::FINISHED:
break;
default: default:
break; break;
} }
@@ -172,7 +170,7 @@ void Notifier::show(std::vector<std::string> texts, const Style& style, int icon
const int ICON_SPACE = icon >= 0 ? ICON_SIZE + PADDING_IN_H : 0; const int ICON_SPACE = icon >= 0 ? ICON_SIZE + PADDING_IN_H : 0;
const TextAlign TEXT_IS = ICON_SPACE > 0 ? TextAlign::LEFT : style.text_align; const TextAlign TEXT_IS = ICON_SPACE > 0 ? TextAlign::LEFT : style.text_align;
const float WIDTH = Options::game.width - (PADDING_OUT * 2); const float WIDTH = Options::game.width - (PADDING_OUT * 2);
const float HEIGHT = (TEXT_SIZE * texts.size()) + (PADDING_IN_V * 2); const float HEIGHT = (TEXT_SIZE * static_cast<float>(texts.size())) + (PADDING_IN_V * 2);
const auto SHAPE = style.shape; const auto SHAPE = style.shape;
// Posición horizontal // Posición horizontal
@@ -287,7 +285,7 @@ void Notifier::clearNotifications() {
} }
// Y absoluta de la base de la pila (justo debajo de Console, o 0 si no hay Console) // Y absoluta de la base de la pila (justo debajo de Console, o 0 si no hay Console)
auto Notifier::getStackBaseY() const -> int { auto Notifier::getStackBaseY() -> int {
return Console::get() != nullptr ? Console::get()->getVisibleHeight() : 0; return Console::get() != nullptr ? Console::get()->getVisibleHeight() : 0;
} }
@@ -297,7 +295,7 @@ auto Notifier::getVisibleHeight() const -> int {
for (const auto& n : notifications_) { for (const auto& n : notifications_) {
if (n.state == Status::FINISHED) { continue; } if (n.state == Status::FINISHED) { continue; }
const int N_BOTTOM = static_cast<int>(n.rect.y + n.rect.h); const int N_BOTTOM = static_cast<int>(n.rect.y + n.rect.h);
if (N_BOTTOM > bottom) { bottom = N_BOTTOM; } bottom = std::max(N_BOTTOM, bottom);
} }
return bottom; return bottom;
} }

View File

@@ -100,7 +100,7 @@ class Notifier {
// Métodos privados // Métodos privados
void clearFinishedNotifications(); // Elimina las notificaciones finalizadas void clearFinishedNotifications(); // Elimina las notificaciones finalizadas
void clearNotifications(); // Finaliza y elimina todas las notificaciones activas void clearNotifications(); // Finaliza y elimina todas las notificaciones activas
[[nodiscard]] auto getStackBaseY() const -> int; // Y absoluta de la base de la pila (leída de Console) [[nodiscard]] static auto getStackBaseY() -> int; // Y absoluta de la base de la pila (leída de Console)
// Constructor y destructor privados [SINGLETON] // Constructor y destructor privados [SINGLETON]
Notifier(const std::string& icon_file, const std::string& text); Notifier(const std::string& icon_file, const std::string& text);

View File

@@ -2,8 +2,7 @@
DeltaTimer::DeltaTimer() noexcept DeltaTimer::DeltaTimer() noexcept
: last_counter_(SDL_GetPerformanceCounter()), : last_counter_(SDL_GetPerformanceCounter()),
perf_freq_(static_cast<double>(SDL_GetPerformanceFrequency())), perf_freq_(static_cast<double>(SDL_GetPerformanceFrequency())) {
time_scale_(1.0F) {
} }
auto DeltaTimer::tick() noexcept -> float { auto DeltaTimer::tick() noexcept -> float {

View File

@@ -24,5 +24,5 @@ class DeltaTimer {
private: private:
Uint64 last_counter_; Uint64 last_counter_;
double perf_freq_; double perf_freq_;
float time_scale_; float time_scale_{1.0F};
}; };