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.

drawutil.cc 2.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include "drawutil.h"
  2. #include <algorithm>
  3. #include <cmath>
  4. #include "gfxutil.h"
  5. namespace Swan {
  6. namespace Draw {
  7. static Uint8 linearLine(float from, float to, float frac) {
  8. return (Uint8)std::clamp(to * frac + from * (1 - frac), 0.0f, 255.0f);
  9. }
  10. static SDL_Color linearColor(SDL_Color from, SDL_Color to, float frac) {
  11. return {
  12. .r = linearLine(from.r, to.r, frac),
  13. .g = linearLine(from.g, to.g, frac),
  14. .b = linearLine(from.b, to.b, frac),
  15. .a = linearLine(from.a, to.a, frac),
  16. };
  17. }
  18. SDL_Color linearGradient(
  19. float val,
  20. std::initializer_list<std::pair<float, SDL_Color>> colors) {
  21. const std::pair<float, SDL_Color> *arr = colors.begin();
  22. size_t size = colors.size();
  23. if (val < arr[0].first)
  24. return arr[0].second;
  25. for (size_t i = 1; i < size; ++i) {
  26. if (arr[i].first < val)
  27. continue;
  28. auto [fromv, fromc] = arr[i - 1];
  29. auto [tov, toc] = arr[i];
  30. float frac = (val - fromv) / (tov - fromv);
  31. return linearColor(fromc, toc, frac);
  32. }
  33. return arr[size - 1].second;
  34. }
  35. void parallaxBackground(
  36. Win &win, SDL_Texture *tex,
  37. std::optional<SDL_Rect> srcrect, std::optional<SDL_Rect> destrect,
  38. float x, float y, float factor) {
  39. SDL_Renderer *rnd = win.renderer_;
  40. // We only need to set a clip rect if we have a destrect
  41. std::optional<RenderClipRect> clip;
  42. if (!srcrect) {
  43. Uint32 fmt;
  44. int access, w, h;
  45. SDL_QueryTexture(tex, &fmt, &access, &w, &h);
  46. srcrect = SDL_Rect{ 0, 0, w, h };
  47. }
  48. if (destrect) {
  49. clip.emplace(rnd, &*destrect);
  50. } else {
  51. int w, h;
  52. SDL_RenderGetLogicalSize(rnd, &w, &h);
  53. destrect = SDL_Rect{ 0, 0, w, h };
  54. }
  55. x = (x * win.zoom_) * -factor;
  56. y = (y * win.zoom_) * -factor;
  57. SDL_Rect rect{
  58. 0, 0,
  59. (int)((float)srcrect->w * win.zoom_),
  60. (int)((float)srcrect->h * win.zoom_),
  61. };
  62. rect.x = (int)std::floor((int)x % rect.w);
  63. if (rect.x > 0) rect.x -= rect.w;
  64. rect.y = (int)std::floor((int)y % rect.h);
  65. if (rect.y > 0) rect.y -= rect.h;
  66. int numx = destrect->w / rect.w + 2;
  67. int numy = destrect->h / rect.h + 2;
  68. for (int x = 0; x < numx; ++x) {
  69. for (int y = 0; y < numy; ++y) {
  70. SDL_Rect r{ rect.x + x * rect.w, rect.y + y * rect.h, rect.w, rect.h };
  71. SDL_RenderCopy(rnd, tex, &*srcrect, &r);
  72. }
  73. }
  74. }
  75. }
  76. }