// IWYU pragma: no_include #pragma once #include // Para Uint8, SDL_FRect, SDL_FPoint, SDL_Renderer #include // Para max, min #include // Para array #include // Para isxdigit #include // Para int32_t #include // Para size_t, abs #include // Para invalid_argument #include // Para string, basic_string, stoi #include // Para vector // --- Constantes --- constexpr int BLOCK = 8; constexpr int TOTAL_DEMO_DATA = 2000; constexpr size_t COLOR_CYCLE_SIZE = 6; // Mitad del ciclo espejado // --- Estructuras y tipos --- struct Overrides { std::string param_file; // Fichero de parametros a utilizar bool clear_hi_score_table{false}; // Reinicia la tabla de records Overrides() = default; }; extern Overrides overrides; // Estructura para definir un circulo struct Circle { int x, y, r; Circle() : x(0), y(0), r(0) {} Circle(int x_coord, int y_coord, int radius) : x(x_coord), y(y_coord), r(radius) {} }; // Estructura para definir un color RGBA struct Color { private: static constexpr Uint8 MAX_COLOR_VALUE = 255; static constexpr Uint8 MIN_COLOR_VALUE = 0; static constexpr Uint8 DEFAULT_ALPHA = 255; static constexpr int DEFAULT_LIGHTEN_AMOUNT = 50; static constexpr int DEFAULT_DARKEN_AMOUNT = 50; static constexpr int DEFAULT_APPROACH_STEP = 1; static constexpr size_t HEX_RGB_LENGTH = 6; static constexpr size_t HEX_RGBA_LENGTH = 8; static constexpr int HEX_BASE = 16; static constexpr size_t HEX_COMPONENT_LENGTH = 2; public: Uint8 r, g, b, a; constexpr Color() : r(MIN_COLOR_VALUE), g(MIN_COLOR_VALUE), b(MIN_COLOR_VALUE), a(DEFAULT_ALPHA) {} explicit constexpr Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = DEFAULT_ALPHA) : r(red), g(green), b(blue), a(alpha) {} [[nodiscard]] constexpr auto INVERSE() const -> Color { return Color(MAX_COLOR_VALUE - r, MAX_COLOR_VALUE - g, MAX_COLOR_VALUE - b, a); } [[nodiscard]] constexpr auto LIGHTEN(int amount = DEFAULT_LIGHTEN_AMOUNT) const -> Color { return Color( std::min(static_cast(MAX_COLOR_VALUE), r + amount), std::min(static_cast(MAX_COLOR_VALUE), g + amount), std::min(static_cast(MAX_COLOR_VALUE), b + amount), a); } [[nodiscard]] constexpr auto DARKEN(int amount = DEFAULT_DARKEN_AMOUNT) const -> Color { return Color( std::max(static_cast(MIN_COLOR_VALUE), r - amount), std::max(static_cast(MIN_COLOR_VALUE), g - amount), std::max(static_cast(MIN_COLOR_VALUE), b - amount), a); } // Método estático para crear Color desde string hexadecimal static auto fromHex(const std::string &hex_str) -> Color { std::string hex = hex_str; // Quitar '#' si existe if (!hex.empty() && hex[0] == '#') { hex = hex.substr(1); } // Verificar longitud válida (6 para RGB o 8 para RGBA) if (hex.length() != HEX_RGB_LENGTH && hex.length() != HEX_RGBA_LENGTH) { throw std::invalid_argument("String hexadecimal debe tener 6 o 8 caracteres"); } // 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"); } } // Convertir cada par de caracteres a valores RGB(A) Uint8 r = static_cast(std::stoi(hex.substr(0, HEX_COMPONENT_LENGTH), nullptr, HEX_BASE)); Uint8 g = static_cast(std::stoi(hex.substr(HEX_COMPONENT_LENGTH, HEX_COMPONENT_LENGTH), nullptr, HEX_BASE)); Uint8 b = static_cast(std::stoi(hex.substr(HEX_COMPONENT_LENGTH * 2, HEX_COMPONENT_LENGTH), nullptr, HEX_BASE)); Uint8 a = DEFAULT_ALPHA; // Alpha por defecto // Si tiene 8 caracteres, extraer el alpha if (hex.length() == HEX_RGBA_LENGTH) { a = static_cast(std::stoi(hex.substr(HEX_COMPONENT_LENGTH * 3, HEX_COMPONENT_LENGTH), nullptr, HEX_BASE)); } return Color(r, g, b, a); } [[nodiscard]] constexpr auto IS_EQUAL_TO(const Color &other) const -> bool { return r == other.r && g == other.g && b == other.b && a == other.a; } [[nodiscard]] constexpr auto APPROACH_TO(const Color &target, int step = DEFAULT_APPROACH_STEP) const -> Color { auto approach_component = [step](Uint8 current, Uint8 target_val) -> Uint8 { if (std::abs(current - target_val) <= step) { return target_val; } return (current < target_val) ? current + step : current - step; }; Uint8 new_r = approach_component(r, target.r); Uint8 new_g = approach_component(g, target.g); Uint8 new_b = approach_component(b, target.b); Uint8 new_a = approach_component(a, target.a); return Color(new_r, new_g, new_b, new_a); } }; // Estructura para definir un color HSV struct HSV { float h, s, v; }; // Estructura para definir el ciclo de color enum class ColorCycleStyle { SUBTLE_PULSE, // Variación leve en brillo (por defecto) HUE_WAVE, // Variación suave en tono (sin verde) VIBRANT, // Cambios agresivos en tono y brillo DARKEN_GLOW, // Oscurece hacia el centro y regresa LIGHT_FLASH // Ilumina hacia el centro y regresa }; // Posiciones de las notificaciones enum class NotifyPosition { TOP, BOTTOM, LEFT, MIDDLE, RIGHT, }; // Estructura para datos de la demo struct DemoKeys { Uint8 left; Uint8 right; Uint8 no_input; Uint8 fire; Uint8 fire_left; Uint8 fire_right; explicit DemoKeys(Uint8 l = 0, Uint8 r = 0, Uint8 ni = 0, Uint8 f = 0, Uint8 fl = 0, Uint8 fr = 0) : left(l), right(r), no_input(ni), fire(f), fire_left(fl), fire_right(fr) {} }; using DemoData = std::vector; struct Demo { bool enabled; // Indica si está activo el modo demo bool recording; // Indica si está activado el modo para grabar la demo int counter; // Contador para el modo demo DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo std::vector data; // Vector con diferentes sets de datos con los movimientos para la demo Demo() : enabled(false), recording(false), counter(0) {} Demo(bool e, bool r, int c, const DemoKeys &k, const std::vector &d) : enabled(e), recording(r), counter(c), keys(k), data(d) {} }; // Posiciones dentro de un rectangulo struct Zone { SDL_FRect rect; // Rectangulo que define la zona float center_x; // Anclaje al 50% del eje X float first_quarter_x; // Anclaje al 25% del eje X float third_quarter_x; // Anclaje al 75% del eje X float center_y; // Anclaje al 50% del eje Y float first_quarter_y; // Anclaje al 25% del eje Y float third_quarter_y; // Anclaje al 75% del eje Y }; // --- Alias --- using ColorCycle = std::array; // --- Funciones utilitarias --- // Colores constexpr Color NO_TEXT_COLOR = Color(0XFF, 0XFF, 0XFF); constexpr Color SHADOW_TEXT_COLOR = Color(0X43, 0X43, 0X4F); constexpr Color TITLE_SHADOW_TEXT_COLOR = Color(0x14, 0x87, 0xc4); constexpr Color FLASH_COLOR = Color(0XFF, 0XFF, 0XFF); constexpr Color BLUE_SKY_COLOR = Color(0X02, 0X88, 0XD1); constexpr Color PINK_SKY_COLOR = Color(0XFF, 0X6B, 0X97); constexpr Color GREEN_SKY_COLOR = Color(0X00, 0X79, 0X6B); // Colores y gráficos auto getColorLikeKnightRider(const std::vector &colors, int counter) -> Color; constexpr auto rgbToHsv(Color color) -> HSV; constexpr auto hsvToRgb(HSV hsv) -> Color; auto generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SUBTLE_PULSE) -> ColorCycle; // Colisiones y geometría auto distanceSquared(int x1, int y1, int x2, int y2) -> double; auto checkCollision(const Circle &a, const Circle &b) -> bool; auto checkCollision(const Circle &a, const SDL_FRect &b) -> bool; auto checkCollision(const SDL_FRect &a, const SDL_FRect &b) -> bool; auto checkCollision(const SDL_FPoint &p, const SDL_FRect &r) -> bool; // Conversión y manipulación de cadenas auto stringToBool(const std::string &str) -> bool; auto boolToString(bool value) -> std::string; auto boolToOnOff(bool value) -> std::string; auto toLower(const std::string &str) -> std::string; auto trim(const std::string &str) -> std::string; // Dibujo void drawCircle(SDL_Renderer *renderer, int32_t center_x, int32_t center_y, int32_t radius); // Manipulación de color auto lightenColor(const Color &color, int amount) -> Color; auto darkenColor(const Color &color, int amount) -> Color; // Funciones de suavizado (easing) auto easeOutQuint(double time) -> double; auto easeInQuint(double time) -> double; auto easeInOutQuint(double time) -> double; auto easeInQuad(double time) -> double; auto easeOutQuad(double time) -> double; auto easeInOutSine(double time) -> double; auto easeInOut(double time) -> double; auto easeInOutExpo(double time) -> double; auto easeOutBounce(double time) -> double; auto easeOutElastic(double time) -> double; auto easeInElastic(double time) -> double; // Utilidades varias auto stringInVector(const std::vector &vec, const std::string &str) -> bool; // Comprueba si un vector contiene una cadena void printWithDots(const std::string &text1, const std::string &text2, const std::string &text3); // Imprime una línea con puntos // Demo auto loadDemoDataFromFile(const std::string &file_path) -> DemoData; #ifdef RECORDING bool saveDemoFile(const std::string &file_path, const DemoData &dd); #endif // Ficheros y rutas auto getFileName(const std::string &path) -> std::string; // Obtiene el nombre de un fichero a partir de una ruta auto getPath(const std::string &full_path) -> std::string; // Obtiene la ruta eliminando el nombre del fichero