123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- #include <cmath>
- #include <cstdio>
- #include "data/Array.h"
- #include "data/ArrayList.h"
- #include "data/List.h"
- #include "math/Vector.h"
- #include "rendering/Shader.h"
- #include "rendering/VertexBuffer.h"
- #include "rendering/Window.h"
- #include "utils/Color.h"
- #include "utils/Logger.h"
- #include "utils/Random.h"
- static Shader shader;
- static Buffer buffer;
- static VertexBuffer vertexBuffer;
- enum class Resource { NOTHING, CLAY, ORE, WHEAT, SHEEP, WOOD };
- static const Color4 RESOURCE_COLOR[] = {
- Color4(160, 120, 0, 255), Color4(220, 96, 0, 255),
- Color4(128, 128, 128, 255), Color4(255, 200, 0, 255),
- Color4(40, 200, 40, 255), Color4(0, 120, 0, 255)};
- static const Vector2 MIN_BORDER(-0.9f, -0.9f);
- static const Vector2 MAX_BORDER(0.9f, 0.9f);
- static const Vector2 AREA = MAX_BORDER - MIN_BORDER;
- static const float RADIUS =
- AREA[0] / (5.0f * 2.0f * cosf(30.0f * static_cast<float>(M_PI) / 180.0f));
- static const float LINE_LENGTH =
- RADIUS * sinf(30.0f * static_cast<float>(M_PI) / 180.0f) * 2.0f;
- static const float WIDTH = AREA[0] / 5.0f;
- static void addTriangle(const Vector2 a, const Vector2 b, const Vector2 c,
- const Color4& color) {
- buffer.add(a).add(color);
- buffer.add(b).add(color);
- buffer.add(c).add(color);
- }
- static void addSquare(const Vector2 mid, float size, const Color4& color) {
- size *= 0.5f;
- Vector2 a = mid + Vector2(-size, size);
- Vector2 b = mid + Vector2(size, size);
- Vector2 c = mid + Vector2(-size, -size);
- Vector2 d = mid + Vector2(size, -size);
- addTriangle(a, b, c, color);
- addTriangle(b, d, c, color);
- }
- struct Hexagon {
- Resource resource = Resource::NOTHING;
- Vector2 mid;
- Array<int, 6> corners;
- Hexagon() : corners(-1) {
- }
- void addToBuffer() const {
- Color4 color = RESOURCE_COLOR[static_cast<int>(resource)];
- float angle = 2.0f * static_cast<float>(M_PI) / 6.0f;
- for(int i = 0; i < 6; i++) {
- Vector2 a(sinf(angle * static_cast<float>(i)) * RADIUS,
- cosf(angle * static_cast<float>(i)) * RADIUS);
- Vector2 b(sinf(angle * static_cast<float>(i + 1)) * RADIUS,
- cosf(angle * static_cast<float>(i + 1)) * RADIUS);
- addTriangle(a + mid, b + mid, mid, color);
- }
- }
- Vector2 getTopCorner() const {
- return mid + Vector2(0.0f, RADIUS);
- }
- Vector2 getBottomCorner() const {
- return mid - Vector2(0.0f, RADIUS);
- }
- Vector2 getLeftTopCorner() const {
- return mid - Vector2(WIDTH, -LINE_LENGTH) * 0.5f;
- }
- Vector2 getLeftBottomCorner() const {
- return mid - Vector2(WIDTH, LINE_LENGTH) * 0.5f;
- }
- Vector2 getRightTopCorner() const {
- return mid + Vector2(WIDTH, LINE_LENGTH) * 0.5f;
- }
- Vector2 getRightBottomCorner() const {
- return mid + Vector2(WIDTH, -LINE_LENGTH) * 0.5f;
- }
- };
- static Array<Hexagon, 19> hexagons;
- struct Corner {
- int player = -1;
- Vector2 mid;
- ArrayList<int, 3> hexagons;
- ArrayList<int, 3> paths;
- void addToBuffer() const {
- addSquare(mid, 0.05f, Color4(255, 255, 255, 255));
- }
- };
- static Array<Corner, 54> corners;
- struct Path {
- int player = -1;
- Vector2 from;
- Vector2 to;
- int cornerA = -1;
- int cornerB = -1;
- void addToBuffer() const {
- Vector2 diff = to - from;
- Vector2 normal(diff[1], -diff[0]);
- normal.normalize();
- normal *= 0.01f;
- Vector2 a = from + normal;
- Vector2 b = from - normal;
- Vector2 c = to + normal;
- Vector2 d = to - normal;
- addTriangle(a, c, b, Color4(255, 255, 255, 255));
- addTriangle(c, d, b, Color4(255, 255, 255, 255));
- }
- Vector2 getMid() const {
- return (to + from) * 0.5f;
- }
- };
- static List<Path> paths;
- static void initResources() {
- for(int i = 0; i < 4; i++) {
- hexagons[i].resource = Resource::WHEAT;
- hexagons[i + 4].resource = Resource::WOOD;
- hexagons[i + 8].resource = Resource::SHEEP;
- }
- for(int i = 0; i < 3; i++) {
- hexagons[i + 12].resource = Resource::ORE;
- hexagons[i + 15].resource = Resource::CLAY;
- }
- hexagons[18].resource = Resource::NOTHING;
- Random r(0);
- for(int i = 0; i < hexagons.getLength(); i++) {
- std::swap(hexagons[i], hexagons[r.next(i, hexagons.getLength() - 1)]);
- }
- }
- static void initHexagonMid() {
- Vector2 mid = MIN_BORDER + AREA * 0.5f;
- for(int i = 0; i < 3; i++) {
- hexagons[i].mid = mid - Vector2(WIDTH * static_cast<float>(i - 1),
- -RADIUS * 2.0f - LINE_LENGTH);
- hexagons[i + 16].mid = mid - Vector2(WIDTH * static_cast<float>(i - 1),
- RADIUS * 2.0f + LINE_LENGTH);
- }
- for(int i = 3; i < 7; i++) {
- hexagons[i].mid = mid - Vector2(WIDTH * (static_cast<float>(i) - 4.5f),
- -RADIUS - LINE_LENGTH * 0.5f);
- hexagons[i + 9].mid =
- mid - Vector2(WIDTH * (static_cast<float>(i) - 4.5f),
- RADIUS + LINE_LENGTH * 0.5f);
- }
- for(int i = 7; i < 12; i++) {
- hexagons[i].mid =
- mid - Vector2(WIDTH * static_cast<float>(i - 9), 0.0f);
- }
- }
- static void initCornerMid() {
- for(int i = 0; i < hexagons.getLength(); i++) {
- corners[i].mid = hexagons[i].getLeftTopCorner();
- corners[i + 19].mid = hexagons[i].getLeftBottomCorner();
- }
- corners[38].mid = hexagons[0].getTopCorner();
- corners[39].mid = hexagons[1].getTopCorner();
- corners[40].mid = hexagons[2].getTopCorner();
- corners[41].mid = hexagons[16].getBottomCorner();
- corners[42].mid = hexagons[17].getBottomCorner();
- corners[43].mid = hexagons[18].getBottomCorner();
- corners[44].mid = hexagons[0].getRightTopCorner();
- corners[45].mid = hexagons[0].getRightBottomCorner();
- corners[46].mid = hexagons[3].getRightTopCorner();
- corners[47].mid = hexagons[3].getRightBottomCorner();
- corners[48].mid = hexagons[7].getRightTopCorner();
- corners[49].mid = hexagons[7].getRightBottomCorner();
- corners[50].mid = hexagons[12].getRightTopCorner();
- corners[51].mid = hexagons[12].getRightBottomCorner();
- corners[52].mid = hexagons[16].getRightTopCorner();
- corners[53].mid = hexagons[16].getRightBottomCorner();
- }
- static int findCorner(const Vector2& mid) {
- for(int i = 0; i < corners.getLength(); i++) {
- if((mid - corners[i].mid).squareLength() < 0.00001f) {
- return i;
- }
- }
- return -1;
- }
- static void initHexagonCorners() {
- for(Hexagon& h : hexagons) {
- h.corners[0] = findCorner(h.getTopCorner());
- h.corners[1] = findCorner(h.getBottomCorner());
- h.corners[2] = findCorner(h.getLeftTopCorner());
- h.corners[3] = findCorner(h.getLeftBottomCorner());
- h.corners[4] = findCorner(h.getRightTopCorner());
- h.corners[5] = findCorner(h.getRightBottomCorner());
- }
- for(int i = 0; i < hexagons.getLength(); i++) {
- for(int c = 0; c < hexagons[c].corners.getLength(); c++) {
- if(hexagons[i].corners[c] == -1) {
- LOG_WARNING("Could not find a hexagon corner");
- } else {
- if(corners[hexagons[i].corners[c]].hexagons.add(i)) {
- LOG_WARNING("Corner hexagon overflow");
- }
- }
- }
- }
- }
- static bool doesPathExist(const Path& p) {
- Vector2 mid = p.getMid();
- for(const Path& po : paths) {
- if((mid - po.getMid()).squareLength() < 0.0001f) {
- return true;
- }
- }
- return false;
- }
- static void initPaths() {
- for(int i = 0; i < corners.getLength(); i++) {
- for(int k = 0; k < corners.getLength(); k++) {
- if(i == k || (corners[i].mid - corners[k].mid).length() >=
- LINE_LENGTH * 1.01f) {
- continue;
- }
- Path p;
- p.from = corners[i].mid;
- p.to = corners[k].mid;
- if(doesPathExist(p)) {
- continue;
- }
- paths.add(p);
- }
- }
- LOG_INFO(
- StringBuffer<256>("Got ").append(paths.getLength()).append(" paths"));
- }
- static void initCornerPaths() {
- for(int c = 0; c < corners.getLength(); c++) {
- for(int i = 0; i < paths.getLength(); i++) {
- Vector2 mid = paths[i].getMid();
- if((corners[c].mid - mid).length() >= RADIUS) {
- continue;
- }
- if(corners[c].paths.add(i)) {
- LOG_WARNING("Corner path overflow");
- }
- if(paths[i].cornerA == -1) {
- paths[i].cornerA = c;
- } else if(paths[i].cornerB == -1) {
- paths[i].cornerB = c;
- } else {
- LOG_WARNING("Path got too much corners");
- }
- }
- }
- for(const Path& p : paths) {
- if(p.cornerA == -1 || p.cornerB == -1) {
- LOG_WARNING("Path is missing corners");
- }
- }
- }
- static void init() {
- initResources();
- initHexagonMid();
- initCornerMid();
- initHexagonCorners();
- initPaths();
- initCornerPaths();
- }
- static void buildBuffer() {
- buffer.clear();
- for(const Hexagon& h : hexagons) {
- h.addToBuffer();
- }
- for(const Corner& c : corners) {
- c.addToBuffer();
- }
- for(const Path& p : paths) {
- p.addToBuffer();
- }
- vertexBuffer.setData(buffer, GL::BufferUsage::STATIC);
- }
- static void tick() {
- }
- static void render(float lag) {
- GL::setViewport(Window::getSize()[0], Window::getSize()[1]);
- shader.use();
- vertexBuffer.draw(vertexBuffer.getSize() /
- static_cast<int>(sizeof(Vector2) + sizeof(Color4)));
- (void)lag;
- }
- static bool shouldRun() {
- return !Window::shouldClose();
- }
- int main() {
- Error e = Window::open(
- Window::Options(4, 6, IntVector2(400, 300), false, "Catan Simulator"));
- if(e.has()) {
- e.message.printLine();
- return 0;
- }
- e = shader.compile("resources/vertex.vs", "resources/fragment.fs");
- if(e.has()) {
- e.message.printLine();
- return 0;
- }
- vertexBuffer.init(VertexBuffer::Attributes().addFloat(2).addColor4());
- init();
- buildBuffer();
- Window::show();
- Window::run<shouldRun, tick, render>(10'000'000);
- return 0;
- }
|