|
@@ -1,37 +1,229 @@
|
|
|
#include <GL/glew.h>
|
|
|
#include <GLFW/glfw3.h>
|
|
|
#include <iostream>
|
|
|
+#include <algorithm>
|
|
|
|
|
|
#include "Game.h"
|
|
|
#include "utils/Random.h"
|
|
|
|
|
|
-Game::Game(Keys& keys) : keys(keys) {
|
|
|
+bool Game::Point::operator<(const Point& other) {
|
|
|
+ return x < other.x;
|
|
|
+}
|
|
|
+
|
|
|
+Game::Game(Keys& keys) : keys(keys), keyNext(keys.add(GLFW_KEY_N)), active(0) {
|
|
|
std::cout << "register on " << keys.add(GLFW_KEY_W) << "\n";
|
|
|
+
|
|
|
+ Random r(6476);
|
|
|
+ for(int i = 0; i < 1000; i++) {
|
|
|
+ data.push_back({r.nextFloat() * 1.9f - 0.95f, r.nextFloat() * 1.9f - 0.95f});
|
|
|
+ }
|
|
|
+
|
|
|
+ std::cout << data.size() << "\n";
|
|
|
+
|
|
|
+ split();
|
|
|
+}
|
|
|
+
|
|
|
+void Game::merge() {
|
|
|
+ auto start = groups[active].begin();
|
|
|
+ auto end = groups[active].end();
|
|
|
+ if(start == end) {
|
|
|
+ if(groups[1 - active].begin() + 1 == groups[1 - active].end()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ active = 1 - active;
|
|
|
+ } else if(start + 1 == end) {
|
|
|
+ std::vector<Point> group = groups[active].front();
|
|
|
+ groups[active].pop_front();
|
|
|
+ groups[1 - active].push_back(group);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::vector<Point> hullA = groups[active].front();
|
|
|
+ groups[active].pop_front();
|
|
|
+ std::vector<Point> hullB = groups[active].front();
|
|
|
+ groups[active].pop_front();
|
|
|
+
|
|
|
+ std::vector<Point> mergedHull;
|
|
|
+ mergedHull.reserve(hullA.size() + hullB.size());
|
|
|
+
|
|
|
+ int lowerIndexA;
|
|
|
+ int lowerIndexB;
|
|
|
+ findLowerTangent(hullA, hullB, lowerIndexA, lowerIndexB);
|
|
|
+
|
|
|
+ int upperIndexA;
|
|
|
+ int upperIndexB;
|
|
|
+ findUpperTangent(hullA, hullB, upperIndexA, upperIndexB);
|
|
|
+
|
|
|
+ while(lowerIndexA != upperIndexA) {
|
|
|
+ mergedHull.push_back(hullA[lowerIndexA]);
|
|
|
+ lowerIndexA = (lowerIndexA + 1) % hullA.size();
|
|
|
+ }
|
|
|
+ mergedHull.push_back(hullA[upperIndexA]);
|
|
|
+
|
|
|
+ while(upperIndexB != lowerIndexB) {
|
|
|
+ mergedHull.push_back(hullB[upperIndexB]);
|
|
|
+ upperIndexB = (upperIndexB + 1) % hullB.size();
|
|
|
+ }
|
|
|
+ mergedHull.push_back(hullB[lowerIndexB]);
|
|
|
+
|
|
|
+ groups[1 - active].push_back(mergedHull);
|
|
|
+}
|
|
|
+
|
|
|
+void Game::split() {
|
|
|
+ std::sort(data.begin(), data.end());
|
|
|
+
|
|
|
+ int index = 0;
|
|
|
+ while(index + 2 < static_cast<int> (data.size())) {
|
|
|
+ groups[active].push_back(std::vector<Point>());
|
|
|
+ std::vector<Point>& v = groups[active].back();
|
|
|
+ v.push_back(data[index++]);
|
|
|
+ v.push_back(data[index++]);
|
|
|
+ v.push_back(data[index++]);
|
|
|
+ float f = det(groups[active].back()[0], groups[active].back()[1], groups[active].back()[2]);
|
|
|
+ if(std::abs(f) < 0.0001f) {
|
|
|
+ float minX = v[0].x;
|
|
|
+ float maxX = v[2].x;
|
|
|
+ if(std::abs(minX - maxX) < 0.0001f) {
|
|
|
+ float minY = std::min(v[0].y, std::min(v[1].y, v[2].y));
|
|
|
+ float maxY = std::max(v[0].y, std::max(v[1].y, v[2].y));
|
|
|
+ if(minY < v[0].y && v[0].y < maxY) {
|
|
|
+ v.erase(v.begin());
|
|
|
+ } else if(minY < v[1].y && v[1].y < maxY) {
|
|
|
+ v.erase(v.begin() + 1);
|
|
|
+ } else {
|
|
|
+ v.pop_back();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ v.erase(v.begin() + 1);
|
|
|
+ }
|
|
|
+ } else if(f > 0.0f) {
|
|
|
+ std::swap(groups[active].back()[1], groups[active].back()[2]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ int diff = data.size() - index;
|
|
|
+ if(diff > 0) {
|
|
|
+ groups[active].push_back(std::vector<Point>());
|
|
|
+ std::vector<Point>& v = groups[active].back();
|
|
|
+ while(index < static_cast<int> (data.size())) {
|
|
|
+ v.push_back(data[index++]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool Game::isLowerTangent(const Point& a, const Point& b, const std::vector<Point>& hull) const {
|
|
|
+ for(const Point& p : hull) {
|
|
|
+ float det = (a.x - p.x) * (b.y - p.y) - (b.x - p.x) * (a.y - p.y);
|
|
|
+ if(det < 0.0f) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+bool Game::isUpperTangent(const Point& a, const Point& b, const std::vector<Point>& hull) const {
|
|
|
+ for(const Point& p : hull) {
|
|
|
+ float det = (a.x - p.x) * (b.y - p.y) - (b.x - p.x) * (a.y - p.y);
|
|
|
+ if(det > 0.0f) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+void Game::findLowerTangent(const std::vector<Point>& hullA, const std::vector<Point>& hullB, int& a, int& b) const {
|
|
|
+ a = findMaxX(hullA);
|
|
|
+ b = findMinX(hullB);
|
|
|
+
|
|
|
+ while(!isLowerTangent(hullA[a], hullB[b], hullA) || !isLowerTangent(hullA[a], hullB[b], hullB)) {
|
|
|
+ while(!isLowerTangent(hullA[a], hullB[b], hullA)) {
|
|
|
+ a = (a + 1) % hullA.size();
|
|
|
+ }
|
|
|
+ while(!isLowerTangent(hullA[a], hullB[b], hullB)) {
|
|
|
+ b = (b == 0) ? hullB.size() - 1 : b - 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Game::findUpperTangent(const std::vector<Point>& hullA, const std::vector<Point>& hullB, int& a, int& b) const {
|
|
|
+ a = findMaxX(hullA);
|
|
|
+ b = findMinX(hullB);
|
|
|
+ while(!isUpperTangent(hullA[a], hullB[b], hullA) || !isUpperTangent(hullA[a], hullB[b], hullB)) {
|
|
|
+ while(!isUpperTangent(hullA[a], hullB[b], hullA)) {
|
|
|
+ a = (a == 0) ? hullA.size() - 1 : a - 1;
|
|
|
+ }
|
|
|
+ while(!isUpperTangent(hullA[a], hullB[b], hullB)) {
|
|
|
+ b = (b + 1) % hullB.size();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int Game::findMaxX(const std::vector<Point>& hull) const {
|
|
|
+ if(hull.size() == 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ int index = 0;
|
|
|
+ for(int i = 1; i < static_cast<int> (hull.size()); i++) {
|
|
|
+ if(hull[i].x > hull[index].x) {
|
|
|
+ index = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return index;
|
|
|
+}
|
|
|
+
|
|
|
+int Game::findMinX(const std::vector<Point>& hull) const {
|
|
|
+ if(hull.size() == 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ int index = 0;
|
|
|
+ for(int i = 1; i < static_cast<int> (hull.size()); i++) {
|
|
|
+ if(hull[i].x < hull[index].x) {
|
|
|
+ index = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return index;
|
|
|
}
|
|
|
|
|
|
void Game::tick() {
|
|
|
- std::cout << keys.getDownTime(0) << " - 0 \n";
|
|
|
- std::cout << keys.getDownTime(1) << " - 1 \n";
|
|
|
- std::cout << keys.getDownTime(5335) << " - 5335\n";
|
|
|
+ if(keys.getDownTime(keyNext) == 1) {
|
|
|
+ merge();
|
|
|
+ }
|
|
|
+ if(keys.getDownTime(keyNext) >= 40) {
|
|
|
+ merge();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void Game::render(float lag, Renderer& renderer) const {
|
|
|
(void) lag;
|
|
|
- renderer.setPointSize(4);
|
|
|
- renderer.drawPoint(0.5f, 0.5f, 0xFF0000);
|
|
|
- renderer.drawPoint(0.0f, 0.5f, 0x00FF00);
|
|
|
- renderer.drawPoint(0.5f, 0.0f, 0x0000FF);
|
|
|
- renderer.drawLine(0.5f, 0.0f, 1.0f, 1.0f, 0xFFFF00);
|
|
|
+ renderer.setPointSize(7);
|
|
|
+ for(const Point& p : data) {
|
|
|
+ renderer.drawPoint(p.x, p.y, 0x707070);
|
|
|
+ }
|
|
|
|
|
|
- Random r(0);
|
|
|
- for(uint i = 0; i < 1000; i++) {
|
|
|
- renderer.drawPoint(
|
|
|
- r.nextFloat() * 2.0f - 1.0f,
|
|
|
- r.nextFloat() * 2.0f - 1.0f,
|
|
|
- 0xFF0000);
|
|
|
+ static unsigned int color[] = {
|
|
|
+ 0xFF0000, 0x00FF00, 0x0000FF
|
|
|
+ };
|
|
|
+ for(int k = 0; k < 2; k++) {
|
|
|
+ for(const std::vector<Point> group : groups[k]) {
|
|
|
+ for(int i = 0; i < static_cast<int> (group.size()); i++) {
|
|
|
+ int next = (i + 1) % group.size();
|
|
|
+ renderer.drawLine(
|
|
|
+ group[i].x,
|
|
|
+ group[i].y,
|
|
|
+ group[next].x,
|
|
|
+ group[next].y,
|
|
|
+ 0xFFFFFF);
|
|
|
+ }
|
|
|
+ for(int i = 0; i < static_cast<int> (group.size()); i++) {
|
|
|
+ renderer.drawPoint(group[i].x, group[i].y, color[i % 3]);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool Game::isRunning() const {
|
|
|
return true;
|
|
|
+}
|
|
|
+
|
|
|
+float Game::det(const Point& a, const Point& b, const Point& c) const {
|
|
|
+ return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
|
|
|
}
|