A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "Resource.h"
  2. #include <stdio.h>
  3. #include <SDL2/SDL_image.h>
  4. #include "log.h"
  5. #include "common.h"
  6. #include "Game.h"
  7. #include "Win.h"
  8. namespace Swan {
  9. ImageResource::ImageResource(SDL_Renderer *renderer, const Builder &builder) {
  10. SDL_RendererInfo rinfo;
  11. if (SDL_GetRendererInfo(renderer, &rinfo) < 0) {
  12. panic << "GetRendererInfo failed: " << SDL_GetError();
  13. abort();
  14. }
  15. uint32_t format = rinfo.texture_formats[0];
  16. int bpp = 32;
  17. uint32_t rmask, gmask, bmask, amask;
  18. if (SDL_PixelFormatEnumToMasks(format, &bpp, &rmask, &gmask, &bmask, &amask) < 0) {
  19. panic << "PixelFormatEnumToMasks failed: " << SDL_GetError();
  20. abort();
  21. }
  22. surface_.reset(IMG_Load((builder.modpath + "/assets/" + builder.path).c_str()));
  23. // If we have a surface, and it's the wrong pixel format, convert it
  24. if (surface_ && surface_->format->format != format) {
  25. info
  26. << " " << builder.name << ": Converting from "
  27. << SDL_GetPixelFormatName(surface_->format->format) << " to "
  28. << SDL_GetPixelFormatName(format);
  29. surface_.reset(SDL_ConvertSurfaceFormat(surface_.get(), format, 0));
  30. }
  31. // If we don't have a surface yet (either loading or conversion failed),
  32. // create a placeholder
  33. if (!surface_) {
  34. warn << "Loading image " << builder.name << " failed: " << SDL_GetError();
  35. surface_.reset(SDL_CreateRGBSurface(
  36. 0, TILE_SIZE, TILE_SIZE, bpp, rmask, gmask, bmask, amask));
  37. SDL_FillRect(surface_.get(), NULL, SDL_MapRGB(surface_->format,
  38. PLACEHOLDER_RED, PLACEHOLDER_GREEN, PLACEHOLDER_BLUE));
  39. }
  40. frame_height_ = builder.frame_height;
  41. if (frame_height_ < 0)
  42. frame_height_ = surface_->h;
  43. texture_.reset(SDL_CreateTextureFromSurface(renderer, surface_.get()));
  44. if (!texture_) {
  45. panic << "CreateTexture failed: " << SDL_GetError();
  46. abort();
  47. }
  48. num_frames_ = surface_->h / frame_height_;
  49. name_ = builder.name;
  50. }
  51. ImageResource::ImageResource(
  52. SDL_Renderer *renderer, const std::string &name,
  53. int w, int h, uint8_t r, uint8_t g, uint8_t b) {
  54. surface_.reset(SDL_CreateRGBSurface(
  55. 0, TILE_SIZE, TILE_SIZE, 32, 0, 0, 0, 0));
  56. SDL_FillRect(surface_.get(), NULL, SDL_MapRGB(surface_->format, r, g, b));
  57. texture_.reset(SDL_CreateTextureFromSurface(renderer, surface_.get()));
  58. if (!texture_) {
  59. panic << "CreateTexture failed: " << SDL_GetError();
  60. abort();
  61. }
  62. frame_height_ = h;
  63. num_frames_ = 1;
  64. name_ = name;
  65. }
  66. void ImageResource::tick(float dt) {
  67. switch_timer_ -= dt;
  68. if (switch_timer_ <= 0) {
  69. switch_timer_ += switch_interval_;
  70. frame_ += 1;
  71. if (frame_ >= num_frames_)
  72. frame_ = 0;
  73. }
  74. }
  75. std::unique_ptr<ImageResource> ImageResource::createInvalid(Win &win) {
  76. return std::make_unique<ImageResource>(
  77. win.renderer_, "@internal::invalid", TILE_SIZE, TILE_SIZE,
  78. PLACEHOLDER_RED, PLACEHOLDER_GREEN, PLACEHOLDER_BLUE);
  79. }
  80. ResourceManager::ResourceManager(Win &win) {
  81. addImage(ImageResource::createInvalid(win));
  82. }
  83. void ResourceManager::tick(float dt) {
  84. for (auto &[k, v]: images_) {
  85. v->tick(dt);
  86. }
  87. }
  88. ImageResource &ResourceManager::getImage(const std::string &name) const {
  89. auto it = images_.find(name);
  90. if (it == end(images_)) {
  91. warn << "Couldn't find image " << name << "!";
  92. return getImage("@internal::invalid");
  93. }
  94. return *it->second;
  95. }
  96. }