Sprite.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #include <format>
  2. #include "SDL3/SDL_pixels.h"
  3. #include "Sprite.hpp"
  4. #include "physfs.h"
  5. #define STB_IMAGE_IMPLEMENTATION
  6. #include "../stb_image.h"
  7. namespace Dungeon {
  8. Sprite Sprite::FromFile(SDL_Renderer *renderer, std::string path) {
  9. Sprite sprite{};
  10. SDL_Surface *surface = nullptr;
  11. if (!PHYSFS_exists(path.c_str())) {
  12. throw std::runtime_error(std::format("File not found: {}", path));
  13. }
  14. PHYSFS_file *file = PHYSFS_openRead(path.c_str());
  15. const PHYSFS_sint64 length = PHYSFS_fileLength(file);
  16. auto *buffer = new unsigned char[length];
  17. PHYSFS_readBytes(file, buffer, length);
  18. PHYSFS_close(file);
  19. int width, height, channels;
  20. unsigned char *image = stbi_load_from_memory(
  21. buffer, static_cast<int>(length),
  22. &width, &height, &channels, 4
  23. );
  24. if (!image) {
  25. delete[] buffer;
  26. throw std::runtime_error(std::format("Failed to parse image: {}", path));
  27. }
  28. surface = SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_ABGR8888, image, width * channels);
  29. if (surface == nullptr) {
  30. throw std::runtime_error(std::format("Unable to load spritesheet file: {}", path));
  31. }
  32. sprite.texture = SDL_CreateTextureFromSurface(renderer, surface);
  33. sprite.rect.w = static_cast<float>(sprite.texture->w);
  34. sprite.rect.h = static_cast<float>(sprite.texture->h);
  35. sprite.rect.x = sprite.rect.y = 0;
  36. SDL_SetTextureScaleMode(sprite.texture, SDL_SCALEMODE_NEAREST);
  37. SDL_DestroySurface(surface);
  38. return sprite;
  39. }
  40. Sprite Sprite::FromXML(SDL_Renderer *renderer, tinyxml2::XMLElement *element) {
  41. const char *path;
  42. element->QueryStringAttribute("texture", &path);
  43. Sprite sprite = FromFile(renderer, path);
  44. const auto *rect = element->FirstChildElement();
  45. rect->QueryFloatAttribute("x", &sprite.rect.x);
  46. rect->QueryFloatAttribute("y", &sprite.rect.y);
  47. rect->QueryFloatAttribute("w", &sprite.rect.w);
  48. rect->QueryFloatAttribute("h", &sprite.rect.h);
  49. return sprite;
  50. }
  51. }