#pragma once #include #include #include #include #include #include // Cada Surface manté la seua propia paleta (256 colors ARGB). El destí del // render es l'ARGB framebuffer del joc, mantingut per Screen, així que // l'arquitectura és: sprites paletats → imatge final ARGB (>256 colors). using Palette = std::array; using SubPalette = std::array; auto loadPaletteFromGif(const std::string& file_path) -> Palette; struct SurfaceData { std::shared_ptr data; int width{0}; int height{0}; SurfaceData() = default; SurfaceData(int w, int h) : data(std::shared_ptr(new Uint8[static_cast(w) * static_cast(h)](), std::default_delete())), width(w), height(h) {} SurfaceData(int w, int h, std::shared_ptr pixels) : data(std::move(pixels)), width(w), height(h) {} SurfaceData(SurfaceData&&) noexcept = default; auto operator=(SurfaceData&&) noexcept -> SurfaceData& = default; SurfaceData(const SurfaceData&) = delete; auto operator=(const SurfaceData&) -> SurfaceData& = delete; }; class Surface { public: // Crea una surface buida (paleta a zero) amb les dimensions donades. Surface(int w, int h); // Carrega pixels + paleta des d'un fitxer GIF. explicit Surface(const std::string& file_path); ~Surface() = default; static auto loadSurface(const std::string& file_path) -> SurfaceData; // Vobla la regió indicada al framebuffer ARGB del joc usant la paleta propia. void render(int x, int y, const SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE) const; // Igual que render() però substituint els píxels amb valor source_color per // target_color abans d'aplicar la paleta. Útil per a la classe Text: els // glifs guarden "tinta" amb un únic índex i es recoloren per paràmetre. void renderWithColorReplace(int x, int y, Uint8 source_color, Uint8 target_color, const SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE) const; void clear(Uint8 color); void putPixel(int x, int y, Uint8 color); [[nodiscard]] auto getPixel(int x, int y) const -> Uint8; [[nodiscard]] auto getSurfaceData() const -> std::shared_ptr { return surface_data_; } [[nodiscard]] auto getWidth() const -> int { return surface_data_->width; } [[nodiscard]] auto getHeight() const -> int { return surface_data_->height; } [[nodiscard]] auto getTransparentColor() const -> Uint8 { return transparent_color_; } void setTransparentColor(Uint8 color = 0) { transparent_color_ = color; } void setPalette(const Palette& palette) { palette_ = palette; } [[nodiscard]] auto getPaletteColor(Uint8 index) const -> Uint32 { return palette_[index]; } static void initializeSubPalette(SubPalette& palette) { std::iota(palette.begin(), palette.end(), 0); } private: std::shared_ptr surface_data_; Palette palette_{}; SubPalette sub_palette_{}; // Convenció de tots els GIFs del projecte (sprites i fonts): l'índex 0 // és el color de fons/transparent. Els tilesets que usen un altre índex // han de cridar setTransparentColor() explícitament. Uint8 transparent_color_{0}; };