Files
coffee_crisis_arcade_edition/source/utils.h
2025-06-26 18:34:32 +02:00

236 lines
7.2 KiB
C++

#pragma once
#include <SDL3/SDL_rect.h> // Para SDL_FRect, SDL_FPoint
#include <SDL3/SDL_render.h> // Para SDL_Renderer
#include <SDL3/SDL_stdinc.h> // Para Uint8
#include <stdint.h> // Para int32_t
#include <algorithm> // Para max, min
#include <string> // Para string
#include <vector> // Para vector
#include <array> // Para array
#include <stdexcept>
// --- 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; // Reinicia la tabla de records
Overrides()
: param_file(""), clear_hi_score_table(false) {}
};
extern Overrides overrides;
// Estructura para definir un circulo
struct Circle
{
int x, y, r;
Circle() : x(0), y(0), r(0) {}
Circle(int xCoord, int yCoord, int radius)
: x(xCoord), y(yCoord), r(radius) {}
};
// Estructura para definir un color RGBA
struct Color
{
Uint8 r, g, b, a;
constexpr Color() : r(0), g(0), b(0), a(255) {}
explicit constexpr Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = 255) : r(red), g(green), b(blue), a(alpha) {}
constexpr Color inverse() const { return Color(255 - r, 255 - g, 255 - b, a); }
constexpr Color lighten(int amount = 50) const
{
return Color(
std::min(255, r + amount),
std::min(255, g + amount),
std::min(255, b + amount),
a);
}
constexpr Color darken(int amount = 50) const
{
return Color(
std::max(0, r - amount),
std::max(0, g - amount),
std::max(0, b - amount),
a);
}
// Método estático para crear Color desde string hexadecimal
static Color fromHex(const std::string& hexStr)
{
std::string hex = hexStr;
// 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() != 6 && hex.length() != 8) {
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)) {
throw std::invalid_argument("String contiene caracteres no hexadecimales");
}
}
// Convertir cada par de caracteres a valores RGB(A)
Uint8 r = static_cast<Uint8>(std::stoi(hex.substr(0, 2), nullptr, 16));
Uint8 g = static_cast<Uint8>(std::stoi(hex.substr(2, 2), nullptr, 16));
Uint8 b = static_cast<Uint8>(std::stoi(hex.substr(4, 2), nullptr, 16));
Uint8 a = 255; // Alpha por defecto
// Si tiene 8 caracteres, extraer el alpha
if (hex.length() == 8) {
a = static_cast<Uint8>(std::stoi(hex.substr(6, 2), nullptr, 16));
}
return Color(r, g, b, a);
}
};
// Estructura para definir un color HSV
struct HSV
{
float h, s, v;
};
// Estructura para definir el ciclo de color
enum class ColorCycleStyle
{
SubtlePulse, // Variación leve en brillo (por defecto)
HueWave, // Variación suave en tono (sin verde)
Vibrant, // Cambios agresivos en tono y brillo
DarkenGlow, // Oscurece hacia el centro y regresa
LightFlash // 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<DemoKeys>;
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<DemoData> data; // Vector con diferentes sets de datos con los movimientos para la demo
Demo() : enabled(false), recording(false), counter(0), keys(), data() {}
Demo(bool e, bool r, int c, const DemoKeys &k, const std::vector<DemoData> &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<Color, 2 * COLOR_CYCLE_SIZE>;
// --- Funciones utilitarias ---
// Colores
constexpr Color NO_TEXT_COLOR = Color(0XFF, 0XFF, 0XFF);
constexpr Color SHADOW_TEXT_COLOR = Color(0X43, 0X43, 0X4F);
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
Color getColorLikeKnightRider(const std::vector<Color> &colors, int counter_);
constexpr HSV rgbToHsv(Color color);
constexpr Color hsvToRgb(HSV hsv);
ColorCycle generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SubtlePulse);
// Colisiones y geometría
double distanceSquared(int x1, int y1, int x2, int y2);
bool checkCollision(const Circle &a, const Circle &b);
bool checkCollision(const Circle &a, const SDL_FRect &b);
bool checkCollision(const SDL_FRect &a, const SDL_FRect &b);
bool checkCollision(const SDL_FPoint &p, const SDL_FRect &r);
// Conversión y manipulación de cadenas
bool stringToBool(const std::string &str);
std::string boolToString(bool value);
std::string boolToOnOff(bool value);
std::string toLower(const std::string &str);
std::string trim(const std::string &str);
// Dibujo
void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius);
// Manipulación de color
Color lightenColor(const Color &color, int amount);
Color DarkenColor(const Color &color, int amount);
// Funciones de suavizado (easing)
double easeOutQuint(double t);
double easeInQuint(double t);
double easeInOutQuint(double t);
double easeInQuad(double t);
double easeOutQuad(double t);
double easeInOutSine(double t);
double easeInOut(double t);
double easeInOutExpo(double t);
double easeOutBounce(double t);
double easeOutElastic(double t);
double easeInElastic(double t);
// Utilidades varias
bool stringInVector(const std::vector<std::string> &vec, const std::string &str); // 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
DemoData loadDemoDataFromFile(const std::string &file_path);
#ifdef RECORDING
bool saveDemoFile(const std::string &file_path, const DemoData &dd);
#endif
// Ficheros y rutas
std::string getFileName(const std::string &path); // Obtiene el nombre de un fichero a partir de una ruta
std::string getPath(const std::string &full_path); // Obtiene la ruta eliminando el nombre del fichero