Main.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include <cmath>
  2. #include <cstdio>
  3. #include "data/Array.h"
  4. #include "data/ArrayList.h"
  5. #include "math/Vector.h"
  6. #include "rendering/Shader.h"
  7. #include "rendering/VertexBuffer.h"
  8. #include "rendering/Window.h"
  9. #include "utils/Color.h"
  10. #include "utils/Logger.h"
  11. #include "utils/Random.h"
  12. static Shader shader;
  13. static Buffer buffer;
  14. static VertexBuffer vertexBuffer;
  15. enum class Resource { NOTHING, CLAY, ORE, WHEAT, SHEEP, WOOD };
  16. static const Color4 RESOURCE_COLOR[] = {
  17. Color4(160, 120, 0, 255), Color4(220, 96, 0, 255),
  18. Color4(128, 128, 128, 255), Color4(255, 200, 0, 255),
  19. Color4(40, 200, 40, 255), Color4(0, 120, 0, 255)};
  20. static const Vector2 MIN_BORDER(-0.9f, -0.9f);
  21. static const Vector2 MAX_BORDER(0.9f, 0.9f);
  22. static const Vector2 AREA = MAX_BORDER - MIN_BORDER;
  23. static const float RADIUS =
  24. AREA[0] / (5.0f * 2.0f * cosf(30.0f * static_cast<float>(M_PI) / 180.0f));
  25. static const float LINE_LENGTH =
  26. RADIUS * sinf(30.0f * static_cast<float>(M_PI) / 180.0f) * 2.0f;
  27. static const float WIDTH = AREA[0] / 5.0f;
  28. static void addTriangle(const Vector2 a, const Vector2 b, const Vector2 c,
  29. const Color4& color) {
  30. buffer.add(a).add(color);
  31. buffer.add(b).add(color);
  32. buffer.add(c).add(color);
  33. }
  34. static void addSquare(const Vector2 mid, float size, const Color4& color) {
  35. size *= 0.5f;
  36. Vector2 a = mid + Vector2(-size, size);
  37. Vector2 b = mid + Vector2(size, size);
  38. Vector2 c = mid + Vector2(-size, -size);
  39. Vector2 d = mid + Vector2(size, -size);
  40. addTriangle(a, b, c, color);
  41. addTriangle(b, d, c, color);
  42. }
  43. struct Hexagon {
  44. Resource resource = Resource::NOTHING;
  45. Vector2 mid;
  46. Array<int, 6> corners;
  47. Hexagon() : corners(-1) {
  48. }
  49. void addToBuffer() const {
  50. Color4 color = RESOURCE_COLOR[static_cast<int>(resource)];
  51. float angle = 2.0f * static_cast<float>(M_PI) / 6.0f;
  52. for(int i = 0; i < 6; i++) {
  53. Vector2 a(sinf(angle * static_cast<float>(i)) * RADIUS,
  54. cosf(angle * static_cast<float>(i)) * RADIUS);
  55. Vector2 b(sinf(angle * static_cast<float>(i + 1)) * RADIUS,
  56. cosf(angle * static_cast<float>(i + 1)) * RADIUS);
  57. addTriangle(a + mid, b + mid, mid, color);
  58. }
  59. }
  60. Vector2 getTopCorner() {
  61. return mid + Vector2(0.0f, RADIUS);
  62. }
  63. Vector2 getBottomCorner() {
  64. return mid - Vector2(0.0f, RADIUS);
  65. }
  66. Vector2 getLeftTopCorner() {
  67. return mid - Vector2(WIDTH, -LINE_LENGTH) * 0.5f;
  68. }
  69. Vector2 getLeftBottomCorner() {
  70. return mid - Vector2(WIDTH, LINE_LENGTH) * 0.5f;
  71. }
  72. Vector2 getRightTopCorner() {
  73. return mid + Vector2(WIDTH, LINE_LENGTH) * 0.5f;
  74. }
  75. Vector2 getRightBottomCorner() {
  76. return mid + Vector2(WIDTH, -LINE_LENGTH) * 0.5f;
  77. }
  78. };
  79. static Array<Hexagon, 19> hexagons;
  80. struct Corner {
  81. int player = 0;
  82. Vector2 mid;
  83. ArrayList<int, 3> hexagons;
  84. void addToBuffer() const {
  85. addSquare(mid, 0.05f, Color4(255, 255, 255, 255));
  86. }
  87. };
  88. static Array<Corner, 54> corners;
  89. static void initResources() {
  90. for(int i = 0; i < 4; i++) {
  91. hexagons[i].resource = Resource::WHEAT;
  92. hexagons[i + 4].resource = Resource::WOOD;
  93. hexagons[i + 8].resource = Resource::SHEEP;
  94. }
  95. for(int i = 0; i < 3; i++) {
  96. hexagons[i + 12].resource = Resource::ORE;
  97. hexagons[i + 15].resource = Resource::CLAY;
  98. }
  99. hexagons[18].resource = Resource::NOTHING;
  100. Random r(0);
  101. for(int i = 0; i < hexagons.getLength(); i++) {
  102. std::swap(hexagons[i], hexagons[r.next(i, hexagons.getLength() - 1)]);
  103. }
  104. }
  105. static void initHexagonMid() {
  106. Vector2 mid = MIN_BORDER + AREA * 0.5f;
  107. for(int i = 0; i < 3; i++) {
  108. hexagons[i].mid = mid - Vector2(WIDTH * static_cast<float>(i - 1),
  109. -RADIUS * 2.0f - LINE_LENGTH);
  110. hexagons[i + 16].mid = mid - Vector2(WIDTH * static_cast<float>(i - 1),
  111. RADIUS * 2.0f + LINE_LENGTH);
  112. }
  113. for(int i = 3; i < 7; i++) {
  114. hexagons[i].mid = mid - Vector2(WIDTH * (static_cast<float>(i) - 4.5f),
  115. -RADIUS - LINE_LENGTH * 0.5f);
  116. hexagons[i + 9].mid =
  117. mid - Vector2(WIDTH * (static_cast<float>(i) - 4.5f),
  118. RADIUS + LINE_LENGTH * 0.5f);
  119. }
  120. for(int i = 7; i < 12; i++) {
  121. hexagons[i].mid =
  122. mid - Vector2(WIDTH * static_cast<float>(i - 9), 0.0f);
  123. }
  124. }
  125. static void initCornerMid() {
  126. for(int i = 0; i < hexagons.getLength(); i++) {
  127. corners[i].mid = hexagons[i].getLeftTopCorner();
  128. corners[i + 19].mid = hexagons[i].getLeftBottomCorner();
  129. }
  130. corners[38].mid = hexagons[0].getTopCorner();
  131. corners[39].mid = hexagons[1].getTopCorner();
  132. corners[40].mid = hexagons[2].getTopCorner();
  133. corners[41].mid = hexagons[16].getBottomCorner();
  134. corners[42].mid = hexagons[17].getBottomCorner();
  135. corners[43].mid = hexagons[18].getBottomCorner();
  136. corners[44].mid = hexagons[0].getRightTopCorner();
  137. corners[45].mid = hexagons[0].getRightBottomCorner();
  138. corners[46].mid = hexagons[3].getRightTopCorner();
  139. corners[47].mid = hexagons[3].getRightBottomCorner();
  140. corners[48].mid = hexagons[7].getRightTopCorner();
  141. corners[49].mid = hexagons[7].getRightBottomCorner();
  142. corners[50].mid = hexagons[12].getRightTopCorner();
  143. corners[51].mid = hexagons[12].getRightBottomCorner();
  144. corners[52].mid = hexagons[16].getRightTopCorner();
  145. corners[53].mid = hexagons[16].getRightBottomCorner();
  146. }
  147. static int findCorner(const Vector2& mid) {
  148. for(int i = 0; i < corners.getLength(); i++) {
  149. if((mid - corners[i].mid).squareLength() < 0.00001f) {
  150. return i;
  151. }
  152. }
  153. return -1;
  154. }
  155. static void initHexagonCorners() {
  156. for(Hexagon& h : hexagons) {
  157. h.corners[0] = findCorner(h.getTopCorner());
  158. h.corners[1] = findCorner(h.getBottomCorner());
  159. h.corners[2] = findCorner(h.getLeftTopCorner());
  160. h.corners[3] = findCorner(h.getLeftBottomCorner());
  161. h.corners[4] = findCorner(h.getRightTopCorner());
  162. h.corners[5] = findCorner(h.getRightBottomCorner());
  163. }
  164. for(int i = 0; i < hexagons.getLength(); i++) {
  165. for(int c = 0; c < hexagons[c].corners.getLength(); c++) {
  166. if(hexagons[i].corners[c] == -1) {
  167. LOG_WARNING("Could not find a hexagon corner");
  168. } else {
  169. if(corners[hexagons[i].corners[c]].hexagons.add(i)) {
  170. LOG_WARNING("Corner hexagon overflow");
  171. }
  172. }
  173. }
  174. }
  175. }
  176. static void init() {
  177. initResources();
  178. initHexagonMid();
  179. initCornerMid();
  180. initHexagonCorners();
  181. }
  182. static void buildBuffer() {
  183. buffer.clear();
  184. for(const Hexagon& h : hexagons) {
  185. h.addToBuffer();
  186. }
  187. for(const Corner& c : corners) {
  188. c.addToBuffer();
  189. }
  190. vertexBuffer.setData(buffer, GL::BufferUsage::STATIC);
  191. }
  192. static void tick() {
  193. }
  194. static void render(float lag) {
  195. GL::setViewport(Window::getSize()[0], Window::getSize()[1]);
  196. shader.use();
  197. vertexBuffer.draw(vertexBuffer.getSize() /
  198. static_cast<int>(sizeof(Vector2) + sizeof(Color4)));
  199. (void)lag;
  200. }
  201. static bool shouldRun() {
  202. return !Window::shouldClose();
  203. }
  204. int main() {
  205. Error e = Window::open(
  206. Window::Options(4, 6, IntVector2(400, 300), false, "Catan Simulator"));
  207. if(e.has()) {
  208. e.message.printLine();
  209. return 0;
  210. }
  211. e = shader.compile("resources/vertex.vs", "resources/fragment.fs");
  212. if(e.has()) {
  213. e.message.printLine();
  214. return 0;
  215. }
  216. vertexBuffer.init(VertexBuffer::Attributes().addFloat(2).addColor4());
  217. init();
  218. buildBuffer();
  219. Window::show();
  220. Window::run<shouldRun, tick, render>(10'000'000);
  221. return 0;
  222. }