#pragma once #include // for SDL_Rect, SDL_FRect #include // for SDL_Renderer, SDL_Texture #include // for Uint8, Uint16, Uint32 #include // for SDL_FlipMode #include // for array #include // for default_delete, shared_ptr, __shared_p... #include // for iota #include // for invalid_argument #include // for string #include // for move // Alias using Palette = std::array; using SubPalette = std::array; // Carga una paleta desde un archivo .gif Palette loadPalette(const std::string &file_path); // Carga una paleta desde un archivo .pal Palette readPalFile(const std::string &file_path); struct SurfaceData { std::shared_ptr data; // Usa std::shared_ptr para gestión automática Uint16 width; // Ancho de la imagen Uint16 height; // Alto de la imagen // Constructor por defecto SurfaceData() : data(nullptr), width(0), height(0) {} // Constructor que inicializa dimensiones y asigna memoria SurfaceData(Uint16 w, Uint16 h) : data(std::shared_ptr(new Uint8[w * h](), std::default_delete())), width(w), height(h) {} // Constructor para inicializar directamente con datos SurfaceData(Uint16 w, Uint16 h, std::shared_ptr pixels) : data(std::move(pixels)), width(w), height(h) {} // Constructor de movimiento SurfaceData(SurfaceData &&other) noexcept = default; // Operador de movimiento SurfaceData &operator=(SurfaceData &&other) noexcept = default; // Evita copias accidentales SurfaceData(const SurfaceData &) = delete; SurfaceData &operator=(const SurfaceData &) = delete; // Escala la superficie por un factor entero void scale(int factor) { if (factor <= 1) { throw std::invalid_argument("El factor debe ser mayor a 1."); } // Calcular nuevas dimensiones Uint16 newWidth = width * factor; Uint16 newHeight = height * factor; // Crear un nuevo buffer para los datos redimensionados auto newData = std::shared_ptr(new Uint8[newWidth * newHeight](), std::default_delete()); // Rellenar los datos del nuevo buffer replicando los píxeles for (Uint16 y = 0; y < height; ++y) { for (Uint16 x = 0; x < width; ++x) { Uint8 value = data[y * width + x]; // Obtener el valor del píxel original // Copiar el píxel a la región escalada for (int dy = 0; dy < factor; ++dy) { for (int dx = 0; dx < factor; ++dx) { newData[(y * factor + dy) * newWidth + (x * factor + dx)] = value; } } } } // Actualizar los datos de la superficie data = std::move(newData); width = newWidth; height = newHeight; } }; class Surface { private: std::shared_ptr surface_data_; // Datos a dibujar Palette palette_; // Paleta para volcar la SurfaceData a una Textura SubPalette sub_palette_; // Paleta para reindexar colores int transparent_color_; // Indice de la paleta que se omite en la copia de datos public: // Constructor Surface(int w, int h); explicit Surface(const std::string &file_path); // Destructor ~Surface() = default; // Carga una SurfaceData desde un archivo SurfaceData loadSurface(const std::string &file_path); // Carga una paleta desde un archivo void loadPalette(const std::string &file_path); void loadPalette(Palette palette); // Copia una región de la SurfaceData de origen a la SurfaceData de destino void render(int dx, int dy, int sx, int sy, int w, int h); void render(int x, int y, SDL_Rect *clip = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); void render(SDL_Rect *srcRect = nullptr, SDL_Rect *dstRect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Copia una región de la SurfaceData de origen a la SurfaceData de destino reemplazando un color por otro void renderWithColorReplace(int x, int y, Uint8 source_color = 0, Uint8 target_color = 0, SDL_Rect *srcRect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Establece un color en la paleta void setColor(int index, Uint32 color); // Rellena la SurfaceData con un color void clear(Uint8 color); // Vuelca la SurfaceData a una textura void copyToTexture(SDL_Renderer *renderer, SDL_Texture *texture); void copyToTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_FRect *srcRect, SDL_FRect *destRect); // Realiza un efecto de fundido en las paletas bool fadePalette(); bool fadeSubPalette(Uint32 delay = 0); // Pone un pixel en la SurfaceData void putPixel(int x, int y, Uint8 color); // Obtiene el color de un pixel de la surface_data Uint8 getPixel(int x, int y); // Dibuja un rectangulo relleno void fillRect(const SDL_Rect *rect, Uint8 color); // Dibuja el borde de un rectangulo void drawRectBorder(const SDL_Rect *rect, Uint8 color); // Dibuja una linea void drawLine(int x1, int y1, int x2, int y2, Uint8 color); // Metodos para gestionar surface_data_ std::shared_ptr getSurfaceData() const { return surface_data_; } void setSurfaceData(std::shared_ptr new_data) { surface_data_ = new_data; } // Obtien ancho y alto int getWidth() const { return surface_data_->width; } int getHeight() const { return surface_data_->height; } // Color transparente Uint8 getTransparentColor() const { return transparent_color_; } void setTransparentColor(Uint8 color = 255) { transparent_color_ = color; } // Paleta void setPalette(const std::array &palette) { palette_ = palette; } // Inicializa la sub paleta void initializeSubPalette(SubPalette &palette) { std::iota(palette.begin(), palette.end(), 0); } // Escala el tamaño de la Surface void scale(int factor) { surface_data_->scale(factor); } };