bonus_01_starwind.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include <cstdio>
  2. #include <cerrno>
  3. #include <vector>
  4. #include <random>
  5. #include <chrono>
  6. #include <thread>
  7. #include "simple/graphical/initializer.h"
  8. #include "simple/graphical/software_window.h"
  9. #include "simple/graphical/algorithm/fill.h"
  10. #include "simple/support/algorithm.hpp"
  11. #include "simple/support/misc.hpp"
  12. using namespace simple::graphical;
  13. using simple::support::ston;
  14. using namespace std::chrono_literals;
  15. using namespace color_literals;
  16. using float3 = simple::geom::vector<float, 3>;
  17. using float2 = simple::geom::vector<float, 2>;
  18. using int2 = simple::geom::vector<int, 2>;
  19. void set_subpixel(const pixel_writer<rgba_pixel, pixel_byte>&, rgba_vector, float2);
  20. void set_pixel(const pixel_writer<rgba_pixel, pixel_byte>&, rgba_vector, float2);
  21. void set_radius(const pixel_writer<rgba_pixel, pixel_byte>&, rgba_vector, float2); // TODO
  22. int main(int argc, char const* argv[]) try
  23. {
  24. switch(argc)
  25. {
  26. case 0: std::puts("Command not specified??");
  27. case 1: std::puts("Distance not specified");
  28. case 2: std::puts("Count not specified");
  29. case 3: std::puts("Speed not specified");
  30. case 4: std::puts("Render mode not specified.");
  31. case 5: std::puts("Color not specified");
  32. return -1;
  33. }
  34. const auto distance = ston<float>(argv[1]);
  35. const auto count = ston<size_t>(argv[2]);
  36. const auto speed = ston<float>(argv[3]);
  37. const auto pixel_setter = strcmp("subpixel", argv[4]) == 0 ? set_subpixel : set_pixel;
  38. const rgb_vector color { rgb_pixel::from(ston<rgb_pixel::int_type>(argv[5])) };
  39. const auto frame_time = 16ms;
  40. std::minstd_rand rand(std::random_device{}());
  41. std::uniform_real_distribution<float> z_dist(.01f,1);
  42. std::uniform_real_distribution<float> xy_dist(-1,1);
  43. std::vector<float3> stars{count};
  44. for(auto&& star : stars)
  45. {
  46. for(auto&& coordinate : star)
  47. coordinate = xy_dist(rand);
  48. star.z() = z_dist(rand);
  49. }
  50. initializer init;
  51. software_window win("Starwind", {600,600}, window::flags::borderless);
  52. auto pixels = std::get<pixel_writer<rgba_pixel, pixel_byte>>(win.surface().pixels());
  53. auto win_size = float2(win.surface().size());
  54. auto half_size = win_size / 2;
  55. for
  56. (
  57. auto [position, next_frame_time] = std::tuple{0.f, std::chrono::high_resolution_clock::now()};
  58. position < distance;
  59. position += speed,
  60. next_frame_time += frame_time,
  61. std::this_thread::sleep_until(next_frame_time)
  62. )
  63. {
  64. fill(win.surface(), win.surface().format().color(0_rgb));
  65. for(auto&& star : stars)
  66. {
  67. star.z() -= speed;
  68. if(star.z() < .01f)
  69. star.z() = 1.f;
  70. const auto perspective_star = star.xy() / star.z();
  71. const auto position = half_size + perspective_star * half_size;
  72. if(float2::zero() <= position && position < win_size)
  73. pixel_setter(pixels, color * (-star.z() + 1), position);
  74. }
  75. win.update();
  76. }
  77. return 0;
  78. }
  79. catch(...)
  80. {
  81. if(errno)
  82. std::perror("ERROR");
  83. const char* sdl_error = SDL_GetError();
  84. if(*sdl_error)
  85. std::puts(sdl_error);
  86. throw;
  87. }
  88. void set_pixel(const pixel_writer<rgba_pixel, pixel_byte>& pixels, rgba_vector pixel, float2 position)
  89. {
  90. pixels.set(rgba_pixel(pixel), int2(position));
  91. }
  92. void set_subpixel(const pixel_writer<rgba_pixel, pixel_byte>& pixels, rgba_vector pixel, float2 position)
  93. {
  94. pixels.set(pixel, position);
  95. }