void Face::tryGoUp(queue<Vertex> &queue, Vertex &v) { Vertex next = v; switch(orientation) { case zFace: y(next)++; if(squares.count(next)) return; if(crossesBorder(v, next, upDir)) return; break; case xFace: case yFace: z(next)++; if(squares.count(next)) return; if(crossesBorder(v, next, frontDir)) return; break; } squares.insert(next); queue.push(next); }
void Face::tryGoLeft(queue<Vertex> &queue, Vertex &v) { Vertex next = v; switch(orientation) { case zFace: case yFace: x(next)--; if(squares.count(next)) return; if(crossesBorder(v, next, leftDir)) return; break; case xFace: y(next)--; if(squares.count(next)) return; if(crossesBorder(v, next, downDir)) return; break; } squares.insert(next); queue.push(next); }
void HexMap::generateMountainRange(mt19937& urng) { static sf::Color mt(128, 88, 44); static vector<VectorSet> splat = { { { 1, -1 }, { 2, -1 }, { 0, 0 }, { 1, 0 }, { -1, 1 }, { 0, 1 }, { -2, 2 }, { -1, 2 }, { 0, 2 } }, { { 1, -2 }, { 0, -1 }, { 1, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { -1, 1 }, { 0, 1 }, { -1, 2 }, { 0, 2 } }, { { 0, -1 }, { 1, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { -1, 1 }, { 0, 1 } }, { { 0, -1 }, { 1, -1 }, { 2, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 } }, { { 0, -2 }, { 1, -2 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { -1, 1 } }, { { -1, -1 }, { 0, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { -2, 1 }, { -1, 1 }, { 0, 1 } }, { { -1, 0 }, { 1, 0 }, { 0, 0 }, { -2, 1 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { -2, 2 }, { -1, 2 }, { 0, 2 } }, { { 0, -2 }, { 1, -2 }, { 0, -1 }, { 1, -1 }, { 2, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 } } }; sf::VertexArray va; static sf::Vector2f w[4]; sf::Vector2f offset = { (float)rng::getInt(2, 85, urng), (float)rng::getInt(2, 85, urng) }; for (int a = 0; a < 100; a++) { w[0] = { (float)xRange(urng), (float)yRange(urng) }; if (isAxialInBounds((sf::Vector2i)w[0]) && getAxial((int)w[0].x, (int)w[0].y).hts->FLAGS[HexTileS::WALKABLE]) { break; } } w[3] = { (float)rng::radians(urng), (float)rng::getInt(10, 40, urng) }; polarToCartesian(w[3]); w[3] = roundvf(w[0] + w[3]); sf::Vector2f avg = { (w[3] + w[0]) / 2.0f }; // sqrt(a^2 + b^2) int dist = (int)sqrtf(powf(abs(w[3].x - w[0].x), 2.0f) + powf(abs(w[3].x - w[0].x), 2.0f)); for (int a = 1; a < 3; a++) { // Distance between the middle points and the endpoint average cannot be greater // than the distance between the endpoints, to prevent any super-sharp curves w[a] = { (float)rng::radians(urng), (float)rng::getInt(10, clamp(dist, 10, 40), urng) }; polarToCartesian(w[a]); w[a] = roundvf(w[a] + avg); } float advance = 1.0f / Bezier::lengthCubic(w); VectorSet h; sf::Vector2f p; for (float f = 0.0f; f < 1.0f; f += advance) { Bezier::curveCubic(p, f, w); if (!isAxialInBounds((sf::Vector2i)p) || !getAxial((int)p.x, (int)p.y).hts->FLAGS[HexTileS::WALKABLE]) { break; } VectorSet& s = splat[rng::getInt(0, splat.size() - 1, urng)]; for (auto r : s) { h.insert((sf::Vector2i)axialToOffset(roundHex((sf::Vector2f)r + p))); } p = { 0.0f, 0.0f }; } HexTile* cTile = nullptr; for (auto& l : h) { cTile = &getOffset(l.x, l.y); if (!isOffsetInBounds((sf::Vector2i)l) || !cTile->hts->FLAGS[HexTileS::WALKABLE]) { continue; } //pushTileColor((sf::Vector2i)l, sf::Color::White); setTileFeature((sf::Vector2i)l, TileFeatureS::get(TileFeatureS::MOUNTAIN), urng); cTile->FLAGS[HexTile::MOUNTAINS] = true; } }
void solve() { borderSquares[xFace]->clear(); borderSquares[yFace]->clear(); borderSquares[zFace]->clear(); for (vector<Face*>::iterator iter = faces.begin(); iter != faces.end(); iter++) { // derive all Squares of this face Face* f = *iter; // unsigned int startTime = getMicroSecs(); // cout << "deriveSquares: "; f->deriveSquares(); // cout << (getMicroSecs() - startTime) << endl; // put all squares of faces with the same orientation together VectorSet* squares = borderSquares[f->orientation]; for(VectorSet::iterator iter = f->squares.begin(); iter != f->squares.end(); iter++) { Vertex v = *iter; squares->insert(v); } } VectorSet::iterator iter = borderSquares[zFace]->begin(); Vertex min = *iter; while(iter != borderSquares[zFace]->end()) { if(*iter < min) min = *iter; iter++; } blocks.clear(); blocks.insert(min); // unsigned int startTime = getMicroSecs(); // cout << "collectBlocks: "; collectBlocks(min); // cout << (getMicroSecs() - startTime) << endl; cout << "The bulk is composed of " << blocks.size() << " units.\n"; }
void tryGoUp(queue<Vertex> &queue, Vertex v) { y(v)++; if(borderSquares[yFace]->count(v)) return; if(blocks.count(v)) return; blocks.insert(v); queue.push(v); }
void tryGoDown(queue<Vertex> &queue, Vertex v) { if(borderSquares[yFace]->count(v)) return; y(v)--; if(blocks.count(v)) return; blocks.insert(v); queue.push(v); }
void collectBlocks(Vertex start) { queue<Vertex> queue; blocks.insert(start); queue.push(start); while(!queue.empty()) { Vertex v = queue.front(); tryGoLeft(queue, v); tryGoRight(queue, v); tryGoDown(queue, v); tryGoUp(queue, v); tryGoBack(queue, v); tryGoFront(queue, v); queue.pop(); } }
void Face::deriveSquares() { squares.clear(); determineOrientation(); vector<Vertex>::iterator iter = cornerVertices.begin(); Vertex min = *iter; while(iter != cornerVertices.end()) { if(*iter < min) min = *iter; iter++; } // min = starting point squares.insert(min); collectSquares(min); }