drag_and_wrap.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // based on: https://www.khanacademy.org/computer-programming/asteroid-game/1486828627
  2. // I, J, K, L to move, mouse to aim and shoot.
  3. #include "common/sketchbook.hpp"
  4. constexpr float light_speed = 40;
  5. constexpr float drag_factor = 0.1;
  6. float2 drag(float2 velocity, float max_speed = light_speed, float factor = drag_factor)
  7. {
  8. return factor * velocity/max_speed;
  9. }
  10. struct projectile
  11. {
  12. float2 position = float2::zero();
  13. float2 velocity = float2::zero();
  14. float2 acceleration = float2::zero();
  15. void move(Program::duration)
  16. {
  17. velocity += acceleration;
  18. position += velocity;
  19. }
  20. };
  21. struct line : public projectile
  22. {
  23. float width = 1;
  24. rgb color = rgb(0xff00ff_rgb);
  25. void draw(vg::frame& frame)
  26. {
  27. frame.begin_sketch()
  28. .line(position - velocity, position)
  29. .line_width(width)
  30. .outline(color)
  31. ;
  32. }
  33. };
  34. struct circle : public projectile
  35. {
  36. float radius = 10;
  37. rgb color = rgb(0xff00ff_rgb);
  38. void draw(vg::frame& frame)
  39. {
  40. frame.begin_sketch()
  41. .ellipse(rect{radius * float2::one(), position, float2::one(0.5)})
  42. .fill(color)
  43. ;
  44. }
  45. };
  46. using body = std::variant<line, circle>;
  47. std::vector<body> bodies;
  48. circle* crc = nullptr;
  49. void start(Program& program)
  50. {
  51. program.frametime = framerate<60>::frametime;
  52. if(program.argc > 2)
  53. {
  54. using support::ston;
  55. using seed_t = decltype(tiny_rand());
  56. tiny_rand.seed({ ston<seed_t>(program.argv[1]), ston<seed_t>(program.argv[2]) });
  57. }
  58. std::cout << "seed: " << std::hex << std::showbase << tiny_rand << '\n';
  59. bodies.push_back(circle{float2(program.size/2)});
  60. bodies.reserve(10000);
  61. crc = &std::get<circle>(bodies.back());
  62. program.key_up = [&](scancode code, keycode)
  63. {
  64. switch(code)
  65. {
  66. case scancode::leftbracket:
  67. case scancode::c:
  68. if(pressed(scancode::rctrl) || pressed(scancode::lctrl))
  69. case scancode::escape:
  70. program.end();
  71. break;
  72. default: break;
  73. }
  74. };
  75. program.key_down = [&](scancode code, keycode)
  76. {
  77. switch(code)
  78. {
  79. case scancode::i:
  80. break;
  81. case scancode::j:
  82. break;
  83. case scancode::k:
  84. break;
  85. case scancode::l:
  86. break;
  87. default: break;
  88. }
  89. };
  90. program.mouse_down = [&](float2 position, auto)
  91. {
  92. if(bodies.size() < bodies.capacity())
  93. bodies.push_back(line{crc->position, (position - crc->position) * 0.1f});
  94. };
  95. program.draw_loop = [&](auto frame, auto delta_time)
  96. {
  97. frame.begin_sketch()
  98. .rectangle(rect{frame.size})
  99. .fill(rgb::white(0))
  100. ;
  101. crc->acceleration = float2::zero();
  102. if(pressed(scancode::i))
  103. crc->acceleration -= float2::j(0.1);
  104. if(pressed(scancode::k))
  105. crc->acceleration += float2::j(0.1);
  106. if(pressed(scancode::j))
  107. crc->acceleration -= float2::i(0.1);
  108. if(pressed(scancode::l))
  109. crc->acceleration += float2::i(0.1);
  110. for(auto&& body : bodies)
  111. {
  112. std::visit( [&frame, &delta_time] (auto& body)
  113. {
  114. body.move(delta_time);
  115. body.draw(frame);
  116. body.velocity -= drag(body.velocity);
  117. constexpr float padding = 5;
  118. auto fullsize = frame.size + 2 * padding;
  119. body.position = ((fullsize + (body.position + padding)) % fullsize) - padding;
  120. }, body);
  121. }
  122. std::cout << std::dec << "Size: " << bodies.size() << " FPS: " << 1/delta_time.count() << '\n';
  123. };
  124. }