Game.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include <GL/glew.h>
  2. #include <GLFW/glfw3.h>
  3. #include <iostream>
  4. #include <algorithm>
  5. #include "Game.h"
  6. #include "utils/Random.h"
  7. bool Game::Point::operator<(const Point& other) {
  8. if(std::abs(x - other.x) < 0.0001f) {
  9. return y < other.y;
  10. }
  11. return x < other.x;
  12. }
  13. Game::Game(Keys& keys) : keys(keys), keyNext(keys.add(GLFW_KEY_N)), active(0) {
  14. std::cout << "register on " << keys.add(GLFW_KEY_W) << "\n";
  15. Random r(6476);
  16. for(int i = 0; i < 25; i++) {
  17. data.push_back({r.nextFloat() * 1.9f - 0.95f, r.nextFloat() * 1.9f - 0.95f});
  18. //float f = r.nextFloat() * 1.9f - 0.95f;
  19. //data.push_back({f * 0.8f, f});
  20. //data.push_back({r.nextFloat() * 1.9f - 0.95f, 0});
  21. //data.push_back({0, r.nextFloat() * 1.9f - 0.95f});
  22. }
  23. std::cout << data.size() << "\n";
  24. split();
  25. }
  26. void Game::merge() {
  27. auto start = groups[active].begin();
  28. auto end = groups[active].end();
  29. if(start == end) {
  30. if(groups[1 - active].begin() + 1 == groups[1 - active].end()) {
  31. return;
  32. }
  33. active = 1 - active;
  34. } else if(start + 1 == end) {
  35. std::vector<Point> group = groups[active].front();
  36. groups[active].pop_front();
  37. groups[1 - active].push_back(group);
  38. return;
  39. }
  40. std::vector<Point> hullA = groups[active].front();
  41. groups[active].pop_front();
  42. std::vector<Point> hullB = groups[active].front();
  43. groups[active].pop_front();
  44. std::vector<Point> mergedHull;
  45. mergedHull.reserve(hullA.size() + hullB.size());
  46. int lowerIndexA;
  47. int lowerIndexB;
  48. findLowerTangent(hullA, hullB, lowerIndexA, lowerIndexB);
  49. int upperIndexA;
  50. int upperIndexB;
  51. findUpperTangent(hullA, hullB, upperIndexA, upperIndexB);
  52. while(lowerIndexA != upperIndexA) {
  53. mergedHull.push_back(hullA[lowerIndexA]);
  54. lowerIndexA = (lowerIndexA + 1) % hullA.size();
  55. }
  56. mergedHull.push_back(hullA[upperIndexA]);
  57. while(upperIndexB != lowerIndexB) {
  58. mergedHull.push_back(hullB[upperIndexB]);
  59. upperIndexB = (upperIndexB + 1) % hullB.size();
  60. }
  61. mergedHull.push_back(hullB[lowerIndexB]);
  62. groups[1 - active].push_back(mergedHull);
  63. }
  64. void Game::split() {
  65. std::sort(data.begin(), data.end());
  66. int index = 0;
  67. while(index + 2 < static_cast<int> (data.size())) {
  68. groups[active].push_back(std::vector<Point>());
  69. std::vector<Point>& v = groups[active].back();
  70. v.push_back(data[index++]);
  71. v.push_back(data[index++]);
  72. v.push_back(data[index++]);
  73. float f = det(groups[active].back()[0], groups[active].back()[1], groups[active].back()[2]);
  74. if(std::abs(f) < 0.0001f) {
  75. if(std::abs(v[0].y - v[1].y) > 0.0001f || std::abs(v[1].y - v[2].y) > 0.0001f) {
  76. v[0].x = (std::abs(v[0].x) < 0.0001f) ? 0.001f : v[0].x * 1.001f;
  77. } else {
  78. v[0].y = (std::abs(v[0].y) < 0.0001f) ? 0.001f : v[0].y * 1.001f;
  79. }
  80. f = det(groups[active].back()[0], groups[active].back()[1], groups[active].back()[2]);
  81. if(f > 0.0f) {
  82. std::swap(groups[active].back()[1], groups[active].back()[2]);
  83. }
  84. } else if(f > 0.0f) {
  85. std::swap(groups[active].back()[1], groups[active].back()[2]);
  86. }
  87. }
  88. int diff = data.size() - index;
  89. if(diff > 0) {
  90. groups[active].push_back(std::vector<Point>());
  91. std::vector<Point>& v = groups[active].back();
  92. while(index < static_cast<int> (data.size())) {
  93. v.push_back(data[index++]);
  94. }
  95. }
  96. }
  97. bool Game::isLowerTangent(const Point& a, const Point& b, const std::vector<Point>& hull) const {
  98. for(const Point& p : hull) {
  99. float det = (a.x - p.x) * (b.y - p.y) - (b.x - p.x) * (a.y - p.y);
  100. if(det < -0.00001f) {
  101. return false;
  102. }
  103. }
  104. return true;
  105. }
  106. bool Game::isUpperTangent(const Point& a, const Point& b, const std::vector<Point>& hull) const {
  107. for(const Point& p : hull) {
  108. float det = (a.x - p.x) * (b.y - p.y) - (b.x - p.x) * (a.y - p.y);
  109. if(det > 0.00001f) {
  110. return false;
  111. }
  112. }
  113. return true;
  114. }
  115. void Game::findLowerTangent(const std::vector<Point>& hullA, const std::vector<Point>& hullB, int& a, int& b) const {
  116. a = findMaxX(hullA);
  117. b = findMinX(hullB);
  118. while(!isLowerTangent(hullA[a], hullB[b], hullA) || !isLowerTangent(hullA[a], hullB[b], hullB)) {
  119. while(!isLowerTangent(hullA[a], hullB[b], hullA)) {
  120. a = (a + 1) % hullA.size();
  121. }
  122. while(!isLowerTangent(hullA[a], hullB[b], hullB)) {
  123. b = (b == 0) ? hullB.size() - 1 : b - 1;
  124. }
  125. }
  126. }
  127. void Game::findUpperTangent(const std::vector<Point>& hullA, const std::vector<Point>& hullB, int& a, int& b) const {
  128. a = findMaxX(hullA);
  129. b = findMinX(hullB);
  130. while(!isUpperTangent(hullA[a], hullB[b], hullA) || !isUpperTangent(hullA[a], hullB[b], hullB)) {
  131. while(!isUpperTangent(hullA[a], hullB[b], hullA)) {
  132. a = (a == 0) ? hullA.size() - 1 : a - 1;
  133. }
  134. while(!isUpperTangent(hullA[a], hullB[b], hullB)) {
  135. b = (b + 1) % hullB.size();
  136. }
  137. }
  138. }
  139. int Game::findMaxX(const std::vector<Point>& hull) const {
  140. if(hull.size() == 0) {
  141. return -1;
  142. }
  143. int index = 0;
  144. for(int i = 1; i < static_cast<int> (hull.size()); i++) {
  145. if(hull[i].x > hull[index].x) {
  146. index = i;
  147. }
  148. }
  149. return index;
  150. }
  151. int Game::findMinX(const std::vector<Point>& hull) const {
  152. if(hull.size() == 0) {
  153. return -1;
  154. }
  155. int index = 0;
  156. for(int i = 1; i < static_cast<int> (hull.size()); i++) {
  157. if(hull[i].x < hull[index].x) {
  158. index = i;
  159. }
  160. }
  161. return index;
  162. }
  163. void Game::tick() {
  164. if(keys.getDownTime(keyNext) == 1) {
  165. merge();
  166. }
  167. if(keys.getDownTime(keyNext) >= 40) {
  168. merge();
  169. }
  170. }
  171. void Game::render(float lag, Renderer& renderer) const {
  172. (void) lag;
  173. renderer.setPointSize(7);
  174. for(const Point& p : data) {
  175. renderer.drawPoint(p.x, p.y, 0x707070);
  176. }
  177. static unsigned int color[] = {
  178. 0xFF0000, 0x00FF00, 0x0000FF
  179. };
  180. for(int k = 0; k < 2; k++) {
  181. for(const std::vector<Point> group : groups[k]) {
  182. for(int i = 0; i < static_cast<int> (group.size()); i++) {
  183. int next = (i + 1) % group.size();
  184. renderer.drawLine(
  185. group[i].x,
  186. group[i].y,
  187. group[next].x,
  188. group[next].y,
  189. 0xFFFFFF);
  190. }
  191. for(int i = 0; i < static_cast<int> (group.size()); i++) {
  192. renderer.drawPoint(group[i].x, group[i].y, color[i % 3]);
  193. }
  194. }
  195. }
  196. }
  197. bool Game::isRunning() const {
  198. return true;
  199. }
  200. float Game::det(const Point& a, const Point& b, const Point& c) const {
  201. return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
  202. }