This commit is contained in:
2026-04-11 16:25:56 +02:00
parent 5b2f986d32
commit bb38600aac
57 changed files with 371 additions and 347 deletions

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cstdint> // Para int8_t, uint8_t
#include <string> // Para string
#include <utility> // Para move
@@ -7,13 +8,13 @@
class Audio {
public:
// --- Enums ---
enum class Group : int {
enum class Group : std::int8_t {
ALL = -1, // Todos los grupos
GAME = 0, // Sonidos del juego
INTERFACE = 1 // Sonidos de la interfaz
};
enum class MusicState {
enum class MusicState : std::uint8_t {
PLAYING, // Reproduciendo música
PAUSED, // Música pausada
STOPPED, // Música detenida

View File

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

View File

@@ -2,11 +2,12 @@
#include <SDL3/SDL.h>
#include <cstdint>
#include <string>
#include <unordered_map>
// --- Enums ---
enum class InputAction : int { // Acciones de entrada posibles en el juego
enum class InputAction : std::uint8_t { // Acciones de entrada posibles en el juego
// Inputs de movimiento
LEFT,
RIGHT,

View File

@@ -224,8 +224,8 @@ namespace GIF {
if ((screen_descriptor.fields & 0x80) != 0) {
int global_color_table_size = 1 << ((screen_descriptor.fields & 0x07) + 1);
global_color_table.resize(global_color_table_size);
std::memcpy(global_color_table.data(), buffer, 3 * global_color_table_size);
buffer += 3 * global_color_table_size;
std::memcpy(global_color_table.data(), buffer, static_cast<size_t>(3) * static_cast<size_t>(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

View File

@@ -69,7 +69,7 @@ namespace {
if (SZ == 0) { return palette; }
// Matriz de coste NxM (ampliada a SZxSZ con ceros para hacerla cuadrada)
std::vector<int> cost(SZ * SZ, 0);
std::vector<int> cost(static_cast<size_t>(SZ) * static_cast<size_t>(SZ), 0);
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
cost[(i * SZ) + j] = rgbDistanceSq(palette[i], reference[j]);

View File

@@ -3,6 +3,7 @@
#include <SDL3/SDL.h>
#include <array>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
@@ -14,7 +15,7 @@ using Palette = std::array<Uint32, 256>;
class Surface;
// Modo de ordenación de paletas
enum class PaletteSortMode : int {
enum class PaletteSortMode : std::uint8_t {
ORIGINAL = 0, // Paleta tal cual viene del fichero
OPTIMAL = 1, // Asignación óptima a la paleta por defecto (Hungarian algorithm)
REFERENCE = 2, // Asignación greedy a la paleta por defecto

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <memory> // Para shared_ptr
#include <vector> // Para vector
@@ -10,7 +11,7 @@ class Surface;
class PixelReveal {
public:
// Modo de revelado: aleatorio por fila o en orden de bisección (dithering ordenado 1D)
enum class RevealMode { RANDOM,
enum class RevealMode : std::uint8_t { RANDOM,
ORDERED };
// Constructor

View File

@@ -1,5 +1,7 @@
#pragma once
#include <cstdint>
class RenderInfo {
public:
// Singleton
@@ -20,7 +22,7 @@ class RenderInfo {
static constexpr float SLIDE_SPEED = 120.0F;
private:
enum class Status { HIDDEN,
enum class Status : std::uint8_t { HIDDEN,
RISING,
ACTIVE,
VANISHING };

View File

@@ -292,12 +292,12 @@ void Screen::adjustWindowSize() {
// Reservamos memoria una sola vez.
// Si el buffer es más pequeño que la superficie, crash asegurado.
border_pixel_buffer_.resize(static_cast<size_t>(window_width_ * window_height_));
game_pixel_buffer_.resize(static_cast<size_t>(Options::game.width * Options::game.height));
border_pixel_buffer_.resize(static_cast<size_t>(window_width_) * static_cast<size_t>(window_height_));
game_pixel_buffer_.resize(static_cast<size_t>(Options::game.width) * static_cast<size_t>(Options::game.height));
// border_pixel_buffer_ es el buffer que se sube a la GPU (tamaño total ventana).
if (Options::video.border.enabled) {
border_pixel_buffer_.resize(static_cast<size_t>(window_width_ * window_height_));
border_pixel_buffer_.resize(static_cast<size_t>(window_width_) * static_cast<size_t>(window_height_));
}
// Lógica de centrado y redimensionado de ventana SDL
@@ -397,15 +397,17 @@ void Screen::textureToRenderer() {
// Rellena solo el marco con el color cacheado — sin lookups de paleta.
// El área central (juego) se deja sin tocar; el overlay la sobreescribe igualmente.
const auto BORDER_W_SZ = static_cast<size_t>(BORDER_W);
const auto GAME_W_SZ = static_cast<size_t>(GAME_W);
// 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_[(OFF_Y + GAME_H) * BORDER_W],
(BORDER_H - OFF_Y - GAME_H) * BORDER_W,
std::fill_n(border_pixel_buffer_.data(), static_cast<size_t>(OFF_Y) * BORDER_W_SZ, border_argb_color_);
std::fill_n(&border_pixel_buffer_[(static_cast<size_t>(OFF_Y) + GAME_H) * BORDER_W_SZ],
(static_cast<size_t>(BORDER_H - OFF_Y - GAME_H)) * BORDER_W_SZ,
border_argb_color_);
// Columnas laterales en las filas del área de juego
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_[(y * BORDER_W) + OFF_X + GAME_W],
std::fill_n(&border_pixel_buffer_[static_cast<size_t>(y) * BORDER_W_SZ], OFF_X, border_argb_color_);
std::fill_n(&border_pixel_buffer_[(static_cast<size_t>(y) * BORDER_W_SZ) + OFF_X + GAME_W],
BORDER_W - OFF_X - GAME_W,
border_argb_color_);
}
@@ -413,9 +415,9 @@ void Screen::textureToRenderer() {
// Overlay del juego sobre el centro del buffer (ambos paths)
game_surface_->toARGBBuffer(game_pixel_buffer_.data());
for (int y = 0; y < GAME_H; ++y) {
const Uint32* src = &game_pixel_buffer_[y * GAME_W];
Uint32* dst = &border_pixel_buffer_[((OFF_Y + y) * BORDER_W) + OFF_X];
std::memcpy(dst, src, GAME_W * sizeof(Uint32));
const Uint32* src = &game_pixel_buffer_[static_cast<size_t>(y) * GAME_W_SZ];
Uint32* dst = &border_pixel_buffer_[((static_cast<size_t>(OFF_Y) + y) * BORDER_W_SZ) + OFF_X];
std::memcpy(dst, src, GAME_W_SZ * sizeof(Uint32));
}
shader_backend_->uploadPixels(border_pixel_buffer_.data(), BORDER_W, BORDER_H);

View File

@@ -4,6 +4,7 @@
#include <SDL3/SDL_pixels.h> // Para Uint32
#include <cstddef> // Para size_t
#include <cstdint> // Para uint8_t
#include <memory> // Para shared_ptr, __shared_ptr_access
#include <string> // Para string
#include <utility> // Para std::pair
@@ -18,7 +19,7 @@ class Text;
class Screen {
public:
// Tipos de filtro
enum class Filter : Uint32 {
enum class Filter : std::uint8_t {
NEAREST = 0,
LINEAR = 1,
};

View File

@@ -762,7 +762,7 @@ namespace Rendering {
}
// 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) * 4U);
SDL_UnmapGPUTransferBuffer(device_, upload_buffer_);
}

View File

@@ -2,13 +2,14 @@
#include <SDL3/SDL.h>
#include <cstdint>
#include <string>
#include <utility>
namespace Rendering {
/** @brief Identificador del shader de post-procesado activo */
enum class ShaderType { POSTFX,
enum class ShaderType : std::uint8_t { POSTFX,
CRTPI };
/**

View File

@@ -61,7 +61,7 @@ static auto parseAnimations(const fkyaml::node& yaml, float frame_width, float f
animation.speeds.push_back(s.get_value<float>());
}
} else {
float spd = speed_node.get_value<float>();
auto spd = speed_node.get_value<float>();
if (spd > 0.0F) {
animation.speeds.assign(animation.frames.size(), spd);
}

View File

@@ -2,6 +2,7 @@
#include <SDL3/SDL.h>
#include <cstdint>
#include <memory> // Para shared_ptr
#include "core/rendering/sprite/animated_sprite.hpp" // Para SurfaceAnimatedSprite
@@ -9,7 +10,7 @@
class Surface;
// Direcció de la dissolució
enum class DissolveDirection { NONE,
enum class DissolveDirection : std::uint8_t { NONE,
DOWN,
UP };
@@ -41,7 +42,7 @@ class DissolveSprite : public AnimatedSprite {
void setColorReplace(Uint8 source, Uint8 target);
private:
enum class TransitionMode { NONE,
enum class TransitionMode : std::uint8_t { NONE,
DISSOLVING,
GENERATING };

View File

@@ -177,10 +177,10 @@ void Surface::fillRect(const SDL_FRect* rect, Uint8 color) { // NOLINT(readabil
// Rellenar fila a fila con memset (memoria contigua por fila)
Uint8* data_ptr = surface_data_->data.get();
const int SURF_WIDTH = static_cast<int>(surface_data_->width);
const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start);
const auto SURF_WIDTH = static_cast<size_t>(surface_data_->width);
const auto ROW_WIDTH = static_cast<size_t>(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) {
std::memset(data_ptr + (y * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
std::memset(data_ptr + (static_cast<size_t>(y) * SURF_WIDTH) + static_cast<size_t>(x_start), color, ROW_WIDTH);
}
}
@@ -194,10 +194,10 @@ void Surface::drawRectBorder(const SDL_FRect* rect, Uint8 color) { // NOLINT(re
// Dibujar bordes horizontales con memset (líneas contiguas en memoria)
Uint8* data_ptr = surface_data_->data.get();
const int SURF_WIDTH = static_cast<int>(surface_data_->width);
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<int>(y_end) - 1) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
const auto SURF_WIDTH = static_cast<size_t>(surface_data_->width);
const auto ROW_WIDTH = static_cast<size_t>(static_cast<int>(x_end) - static_cast<int>(x_start));
std::memset(data_ptr + (static_cast<size_t>(y_start) * SURF_WIDTH) + static_cast<size_t>(x_start), color, ROW_WIDTH);
std::memset(data_ptr + ((static_cast<size_t>(y_end) - 1) * SURF_WIDTH) + static_cast<size_t>(x_start), color, ROW_WIDTH);
// Dibujar bordes verticales
for (int y = y_start; y < y_end; ++y) {
@@ -295,8 +295,8 @@ void Surface::render(int x, int y, SDL_FRect* src_rect, SDL_FlipMode flip) { //
float h = (src_rect != nullptr) ? src_rect->h : surface_data_->height;
// Guardar dimensiones originales antes del clipping (necesarias para flip)
float orig_w = (src_rect != nullptr) ? src_rect->w : static_cast<float>(surface_data_->width);
float orig_h = (src_rect != nullptr) ? src_rect->h : static_cast<float>(surface_data_->height);
float orig_w = (src_rect != nullptr) ? src_rect->w : surface_data_->width;
float orig_h = (src_rect != nullptr) ? src_rect->h : surface_data_->height;
// Limitar la región para evitar accesos fuera de rango en origen
w = std::min(w, surface_data_->width - sx);
@@ -467,7 +467,7 @@ static auto computeFadeDensity(int screen_y, int fade_h, int canvas_height) -> f
}
// Render amb dissolució als cantons superior/inferior (hash 2D, sense parpelleig)
void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect) const {
void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, const SDL_FRect* src_rect) const {
// Aplicar render offset
x += Screen::get()->getRenderOffsetX();
y += Screen::get()->getRenderOffsetY();
@@ -508,7 +508,7 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height
}
// Idem però reemplaçant un color índex
void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect) const {
void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, const SDL_FRect* src_rect) const {
// Aplicar render offset
x += Screen::get()->getRenderOffsetX();
y += Screen::get()->getRenderOffsetY();
@@ -599,8 +599,8 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture) { //
const int WIDTH = surface_data_->width;
const int HEIGHT = surface_data_->height;
for (int y = 0; y < HEIGHT; ++y) {
const Uint8* src_row = src + (y * WIDTH);
Uint32* dst_row = pixels + (y * row_stride);
const Uint8* src_row = src + (static_cast<size_t>(y) * static_cast<size_t>(WIDTH));
Uint32* dst_row = pixels + (static_cast<size_t>(y) * static_cast<size_t>(row_stride));
for (int x = 0; x < WIDTH; ++x) {
dst_row[x] = pal[src_row[x]];
}
@@ -648,8 +648,8 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FR
const int WIDTH = surface_data_->width;
const int HEIGHT = surface_data_->height;
for (int y = 0; y < HEIGHT; ++y) {
const Uint8* src_row = src + (y * WIDTH);
Uint32* dst_row = pixels + (y * row_stride);
const Uint8* src_row = src + (static_cast<size_t>(y) * static_cast<size_t>(WIDTH));
Uint32* dst_row = pixels + (static_cast<size_t>(y) * static_cast<size_t>(row_stride));
for (int x = 0; x < WIDTH; ++x) {
dst_row[x] = pal[src_row[x]];
}

View File

@@ -85,10 +85,10 @@ class Surface {
void renderWithColorReplace(int x, int y, Uint8 source_color = 0, Uint8 target_color = 0, SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE) const;
// Render amb dissolució als cantons superior/inferior (hash 2D, sense parpelleig)
void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect = nullptr) const;
void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, const SDL_FRect* src_rect = nullptr) const;
// Idem però reemplaçant un color índex (per a sprites sobre fons del mateix color)
void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect = nullptr) const;
void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, const SDL_FRect* src_rect = nullptr) const;
// Establece un color en la paleta
void setColor(int index, Uint32 color);

View File

@@ -22,22 +22,19 @@ auto Text::nextCodepoint(const std::string& s, size_t& pos) -> uint32_t { // NO
if (c < 0x80) {
cp = c;
extra = 0;
} else if (c < 0xC0) {
} else if (c < 0xC0 || c >= 0xF8) {
// Byte de continuación suelto o lead byte inválido
pos++;
return 0xFFFD;
} // byte de continuación suelto
else if (c < 0xE0) {
} else if (c < 0xE0) {
cp = c & 0x1F;
extra = 1;
} else if (c < 0xF0) {
cp = c & 0x0F;
extra = 2;
} else if (c < 0xF8) {
} else {
cp = c & 0x07;
extra = 3;
} else {
pos++;
return 0xFFFD;
}
pos++;
@@ -291,7 +288,7 @@ void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerni
if (COLORED) {
writeColored(x, y, text, text_color, kerning, lenght);
} else {
writeColored(x, y, text, text_color, kerning, lenght);
write(x, y, text, kerning, lenght);
}
}

View File

@@ -235,7 +235,7 @@ namespace Resource {
// Obtiene todas las habitaciones
auto Cache::getRooms() -> std::vector<RoomResource>& {
if (loading_mode_ == LoadingMode::LAZY) {
for (auto& r : rooms_) {
for (const auto& r : rooms_) {
if (r.room == nullptr) { loadRoomByName(r.name); }
}
}
@@ -248,6 +248,7 @@ namespace Resource {
std::cerr << "[ ERROR ] Path: " << file_path << '\n';
std::cerr << "[ ERROR ] Reason: " << e.what() << '\n';
std::cerr << "[ ERROR ] Check config/assets.yaml configuration\n";
// cppcheck-suppress rethrowNoCurrentException -- helper [[noreturn]] invocado desde dentro de un catch; cppcheck no puede ver que el rethrow es válido a través de la llamada.
throw;
}
@@ -548,6 +549,8 @@ namespace Resource {
exit(0);
}
break;
default:
break;
}
}
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <memory> // Para shared_ptr
#include <string> // Para string
#include <utility>
@@ -11,7 +12,7 @@ namespace Resource {
class Cache {
public:
enum class LoadingMode {
enum class LoadingMode : std::uint8_t {
EAGER, // Carga todos los recursos en init() (comportamiento por defecto, producción)
LAZY // Sólo registra nombres; carga cada recurso la primera vez que se pide (desarrollo)
};

View File

@@ -75,11 +75,11 @@ namespace Resource {
}
// Buscar la última entrada con el mismo prefijo de ruta e insertar después
std::string entry = " - " + var_path + "\n";
auto last_pos = content.rfind(var_path.substr(0, var_path.rfind('/')));
if (last_pos != std::string::npos) {
auto end_of_line = content.find('\n', last_pos);
if (end_of_line != std::string::npos) {
std::string entry = " - " + var_path + "\n";
content.insert(end_of_line + 1, entry);
}
}

View File

@@ -12,7 +12,7 @@ namespace Resource {
class List {
public:
// --- Enums ---
enum class Type : int {
enum class Type : std::uint8_t {
DATA, // Datos
BITMAP, // Imágenes
ANIMATION, // Animaciones

View File

@@ -41,9 +41,11 @@ void Debug::render() { // NOLINT(readability-make-member-function-const)
// Watch window: valores persistentes (key: value)
for (const auto& [key, value] : watches_) {
const std::string LINE = key + ": " + value;
text->write(x_, y, LINE);
w = std::max(w, text->length(LINE));
std::string line = key;
line += ": ";
line += value;
text->write(x_, y, line);
w = std::max(w, text->length(line));
y += DESP_Y;
if (y > 192 - CHAR_SIZE) {
y = y_;