Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Units::generateLOSLineSegments(Unit* unit, sf::VertexArray* vertices)
- {
- vector<f2> linesFinal;
- f2 position = unit->offCenter();
- f2 textureCenter = VALUES.getf2("visionCircleCenter");
- f2 center = unit->offCenter();
- for (auto const& element : walls_)
- {
- Wall* wall = element.second;
- if (!wall->canBeSeenThrough_)
- {
- if (wall->contains(position))
- {
- vertices->append(sf::Vertex(center, textureCenter));
- vertices->append(sf::Vertex(wall->topLeft(), textureCenter + f2(50, 0)));
- vertices->append(sf::Vertex(wall->topRight(), textureCenter + f2(0, 50)));
- vertices->append(sf::Vertex(center, textureCenter));
- vertices->append(sf::Vertex(wall->topLeft(), textureCenter + f2(50, 0)));
- vertices->append(sf::Vertex(wall->bottomLeft(), textureCenter + f2(0, 50)));
- vertices->append(sf::Vertex(center, textureCenter));
- vertices->append(sf::Vertex(wall->bottomRight(), textureCenter + f2(50, 0)));
- vertices->append(sf::Vertex(wall->topRight(), textureCenter + f2(0, 50)));
- vertices->append(sf::Vertex(center, textureCenter));
- vertices->append(sf::Vertex(wall->bottomLeft(), textureCenter + f2(50, 0)));
- vertices->append(sf::Vertex(wall->bottomRight(), textureCenter + f2(0, 50)));
- return;
- }
- vector<vector<float>> lines = {{wall->topLeft().x, wall->topLeft().y, wall->topRight().x, wall->topRight().y},
- {wall->topLeft().x, wall->topLeft().y, wall->bottomLeft().x, wall->bottomLeft().y},
- {wall->bottomRight().x, wall->bottomRight().y, wall->bottomLeft().x, wall->bottomLeft().y},
- {wall->bottomRight().x, wall->bottomRight().y, wall->topRight().x, wall->topRight().y}};
- vector<vector<float>> linesWithDistance;
- // calculate and sort based on shortest distance from the line to the point
- for (int i = 0; i < lines.size(); ++i)
- {
- float distance = position.distanceToLine({lines[i][0], lines[i][1]}, {lines[i][2], lines[i][3]});
- if (distance < unit->sightRange_)
- {
- linesWithDistance.push_back({distance, lines[i][0], lines[i][1], lines[i][2], lines[i][3]});
- }
- }
- std::sort(linesWithDistance.begin(), linesWithDistance.end(), [](auto a, auto b) {return a.at(0) < b.at(0);});
- int amount = 0;
- // set amount of relevant lines in range for each wall
- if (linesWithDistance.size() >= 1)
- {
- // if the distance to two lines of 1 wall are the same that means the shortest distance is to the endpoint of those lines
- // or the point is inside the wall which should never happen.
- if (linesWithDistance.size() != 1 && linesWithDistance[0][0] == linesWithDistance[1][0])
- {
- amount = 2;
- }
- else
- {
- amount = 1;
- }
- }
- // amount is the amount of line segments of the wall will block vision. kinda like backface culling?
- for (int i = 0; i < amount; ++i)
- {
- vector<f2> intersectionPoints = position.circleIntersectsLine(unit->sightRange_,
- {linesWithDistance[i][1], linesWithDistance[i][2]}, {linesWithDistance[i][3], linesWithDistance[i][4]});
- if (intersectionPoints.size() == 2)
- {
- linesFinal.push_back(intersectionPoints[0]);
- linesFinal.push_back(intersectionPoints[1]);
- }
- else if (intersectionPoints.size() == 1)
- {
- if (f2(linesWithDistance[i][1], linesWithDistance[i][2]).insideCircle(position, unit->sightRange_))
- {
- linesFinal.push_back(intersectionPoints[0]);
- linesFinal.push_back({linesWithDistance[i][1], linesWithDistance[i][2]});
- }
- else if (f2(linesWithDistance[i][3], linesWithDistance[i][4]).insideCircle(position, unit->sightRange_))
- {
- linesFinal.push_back(intersectionPoints[0]);
- linesFinal.push_back({linesWithDistance[i][3], linesWithDistance[i][4]});
- }
- }
- else
- {
- linesFinal.push_back({linesWithDistance[i][1], linesWithDistance[i][2]});
- linesFinal.push_back({linesWithDistance[i][3], linesWithDistance[i][4]});
- }
- }
- }
- }
- // calculate starting and ending angles and sort based on starting angles and calculate the size of the angle
- vector<vector<float>> anglesSet;
- for (int i = 0; i + 1 < linesFinal.size(); i += 2)
- {
- float angle1 = atan2f((linesFinal[i].y - center.y), (linesFinal[i].x - center.x));
- float angle2 = atan2f((linesFinal[i + 1].y - center.y), (linesFinal[i + 1].x - center.x));
- // generate the linesegment angle data
- // this splits angles that go a across the angle boundary from PI to -PI
- if (angle1 - angle2 > PI)
- {
- f2 intersection = center.linesIntersect(center + f2( - unit->sightRange_, 0), linesFinal[i], linesFinal[i + 1]);
- anglesSet.push_back({angle1, float(PI), linesFinal[i].x, linesFinal[i].y, intersection.x, intersection.y});
- anglesSet.push_back({ float(- PI), angle2, intersection.x, intersection.y, linesFinal[i + 1].x, linesFinal[i + 1].y});
- }
- else if (angle1 - angle2 < - PI)
- {
- f2 intersection = center.linesIntersect(center + f2( - unit->sightRange_, 0), linesFinal[i], linesFinal[i + 1]);
- anglesSet.push_back({angle2, float(PI), linesFinal[i + 1].x, linesFinal[i + 1].y, intersection.x, intersection.y});
- anglesSet.push_back({ float(- PI), angle1, intersection.x, intersection.y, linesFinal[i].x, linesFinal[i].y});
- }
- else if (angle1 > angle2)
- {
- anglesSet.push_back({angle2, angle1, linesFinal[i + 1].x, linesFinal[i + 1].y, linesFinal[i].x, linesFinal[i].y});
- }
- else if (angle2 > angle1)
- {
- anglesSet.push_back({angle1, angle2, linesFinal[i].x, linesFinal[i].y, linesFinal[i + 1].x, linesFinal[i + 1].y});
- }
- }
- // split intersecting lines into seperate lines.
- splitIntersectingLines(&anglesSet, center);
- // sort based on starting angle going clockwise.
- std::sort(anglesSet.begin(), anglesSet.end(), [](auto a, auto b)
- {
- if (a.at(0) == b.at(0))
- {
- return a.at(1) > b.at(1);
- }
- return a.at(0) < b.at(0);
- });
- setFogTries(center, unit->sightRange_, anglesSet, vertices);
- }
Add Comment
Please, Sign In to add comment