bonus_02_floating_trixels.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include <cstdio>
  2. #include <thread>
  3. #include <random>
  4. #include <optional>
  5. #include <iostream>
  6. #include "simple/graphical/initializer.h"
  7. #include "simple/graphical/software_window.h"
  8. #include "simple/graphical/algorithm/blit.h"
  9. #include "simple/graphical/algorithm/fill.h"
  10. #include "simple/support/misc.hpp"
  11. #include "simple/support/random/distribution/diagonal.hpp"
  12. using namespace simple::graphical;
  13. using namespace color_literals;
  14. using namespace std::chrono_literals;
  15. using simple::geom::vector;
  16. using float2x2 = vector<float2, 2>;
  17. using namespace simple::support::random;
  18. struct triangle
  19. {
  20. float2 position;
  21. float2x2 transform;
  22. };
  23. struct floating_pixel
  24. {
  25. float2 position;
  26. float2 destination;
  27. };
  28. int main(int argc, char const* argv[]) try
  29. {
  30. const int zoom = argc > 1 ? simple::support::ston<int>(argv[1]) : 16;
  31. if(zoom <= 0)
  32. throw std::logic_error("zoom is not positive!");
  33. const unsigned waypoint_count = argc > 2 ? simple::support::ston<unsigned>(argv[2]) : 5;
  34. const float fastity = argc > 3 ? simple::support::ston<float>(argv[3]) : 0.1;
  35. const unsigned pixel_count = argc > 4 ? simple::support::ston<unsigned>(argv[4]) : 10000;
  36. initializer init;
  37. software_window win("Floating trixels", int2::one(400), window::flags::borderless);
  38. const auto logical_size = win.surface().size() / zoom;
  39. std::optional<surface> zoomed_canvas = std::nullopt;
  40. if(zoom > 1)
  41. zoomed_canvas = surface (logical_size, pixel_format(pixel_format::type::rgba8888));
  42. const surface& canvas = zoomed_canvas ? *zoomed_canvas : win.surface();
  43. std::default_random_engine gen(std::random_device{}());
  44. std::uniform_real_distribution<float> dist(0,logical_size.x());
  45. distribution::triangle<decltype(dist)> tri_dist(0,1);
  46. auto random_float2 = [&gen, &dist]()
  47. { return float2(dist(gen), dist(gen)); };
  48. auto random_float2_tri = [&gen, &tri_dist]()
  49. { return float2(tri_dist(gen), tri_dist(gen)); };
  50. std::vector<float2> waypoints(waypoint_count*3);
  51. std::generate(waypoints.begin(), waypoints.end(), random_float2);
  52. std::vector<triangle> triangles(waypoint_count);
  53. for(size_t i = 0; i < waypoint_count; ++i)
  54. {
  55. size_t j = i*3;
  56. auto& t = triangles[i];
  57. t.position = waypoints[j];
  58. t.transform[0] = waypoints[j+1] - t.position;
  59. t.transform[1] = waypoints[j+2] - t.position;
  60. }
  61. std::vector<floating_pixel> floaters(pixel_count);
  62. auto pixels = std::get<pixel_writer<rgba_pixel, surface::byte>>(canvas.pixels());
  63. for
  64. (
  65. auto target = triangles.begin();
  66. target != triangles.end();
  67. std::this_thread::sleep_for(16ms)
  68. )
  69. {
  70. fill(canvas, canvas.format().color(0x000000ff_rgba));
  71. for(auto&& pixel : floaters)
  72. pixels.set(0xff00ff55_rgba, pixel.position);
  73. if(canvas != win.surface())
  74. blit(canvas, win.surface(), rect{win.surface().size()});
  75. win.update();
  76. auto any_pixel = floaters[0];
  77. float2 diff = any_pixel.position - any_pixel.destination;
  78. if(diff(diff) < 0.01)
  79. {
  80. ++target;
  81. for(auto&& pixel : floaters)
  82. pixel.destination = target->position + target->transform(random_float2_tri());
  83. }
  84. else
  85. {
  86. for(auto&& pixel : floaters)
  87. pixel.position += (pixel.destination - pixel.position) * fastity;
  88. }
  89. }
  90. return 0;
  91. }
  92. catch(...)
  93. {
  94. if(errno)
  95. std::perror("ERROR");
  96. const char* sdl_error = SDL_GetError();
  97. if(*sdl_error)
  98. std::puts(sdl_error);
  99. throw;
  100. }