|
|
|
@ -44,16 +44,15 @@ INCLUDE_game |
|
|
|
|
void Pathfinding::Initialize(){ |
|
|
|
|
nodes.clear(); |
|
|
|
|
sNode*lastNodeAdded=nullptr; |
|
|
|
|
for (int x = 0; x < game->GetCurrentMapData().width; x++) |
|
|
|
|
for (int y = 0; y < game->GetCurrentMapData().height; y++) |
|
|
|
|
for (int x = 0; x < game->GetCurrentMapData().width; x+=gridSpacing.x) |
|
|
|
|
for (int y = 0; y < game->GetCurrentMapData().height; y+=gridSpacing.y) |
|
|
|
|
{ |
|
|
|
|
nodes.insert({x,y}); |
|
|
|
|
sNode node=*nodes.find({x,y}); |
|
|
|
|
sNode&node=nodes[{x,y}]; |
|
|
|
|
node.x = x; // ...because we give each node its own coordinates
|
|
|
|
|
node.y = y; // ...because we give each node its own coordinates
|
|
|
|
|
geom2d::rect<int>tile=game->GetTileCollision(game->GetCurrentLevel(),{float(x*game->GetCurrentMapData().tilewidth),float(y*game->GetCurrentMapData().tilewidth)}); |
|
|
|
|
geom2d::rect<int>tile=game->GetTileCollision(game->GetCurrentLevel(),{float(x*gridSpacing.x),float(y*gridSpacing.y)}); |
|
|
|
|
node.bObstacle = tile.pos!=game->NO_COLLISION.pos||tile.size!=game->NO_COLLISION.size; |
|
|
|
|
tile=game->GetTileCollision(game->GetCurrentLevel(),{float(x*game->GetCurrentMapData().tilewidth),float(y*game->GetCurrentMapData().tilewidth)},true); |
|
|
|
|
tile=game->GetTileCollision(game->GetCurrentLevel(),{float(x*gridSpacing.x),float(y*gridSpacing.y)},true); |
|
|
|
|
node.bObstacleUpper = tile.pos!=game->NO_COLLISION.pos||tile.size!=game->NO_COLLISION.size; |
|
|
|
|
node.parent = nullptr; |
|
|
|
|
node.bVisited = false; |
|
|
|
@ -63,58 +62,44 @@ void Pathfinding::Initialize(){ |
|
|
|
|
nodeEnd=&node; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int x = 0; x < game->GetCurrentMapData().width; x++) |
|
|
|
|
for (int y = 0; y < game->GetCurrentMapData().height; y++) |
|
|
|
|
{ |
|
|
|
|
sNode&node=const_cast<sNode&>(*nodes.find({x,y})); |
|
|
|
|
if(y>0){ |
|
|
|
|
if(nodes.find({x,y-1})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&*nodes.find({x,y-1})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(y<game->GetCurrentMapData().height-1){ |
|
|
|
|
if(nodes.find({x,y+1})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&*nodes.find({x,y+1})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(x>0){ |
|
|
|
|
if(nodes.find({x-1,y})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&*nodes.find({x-1,y})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(x<game->GetCurrentMapData().width-1){ |
|
|
|
|
if(nodes.find({x+1,y})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&*nodes.find({x+1,y})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (auto&[key,node]:nodes){ |
|
|
|
|
if(nodes.find({node.x,node.y-1})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&node); |
|
|
|
|
} |
|
|
|
|
if(nodes.find({node.x,node.y+1})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&node); |
|
|
|
|
} |
|
|
|
|
if(nodes.find({node.x-1,node.y})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&node); |
|
|
|
|
} |
|
|
|
|
if(nodes.find({node.x+1,node.y})!=nodes.end()){ |
|
|
|
|
node.vecNeighbours.push_back(&node); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<vf2d> Pathfinding::Solve_AStar(vf2d startPos,vf2d endPos,float maxRange,bool upperLevel){ |
|
|
|
|
float dist=float(sqrt(pow(endPos.x-startPos.x,2)+pow(endPos.y-startPos.y,2))); |
|
|
|
|
if(dist>maxRange*game->GetCurrentMapData().tilewidth)return {}; |
|
|
|
|
if(nodes.find(sNode{int(startPos.x),int(startPos.y)})==nodes.end())return{}; |
|
|
|
|
if(nodes.find(sNode{int(endPos.x),int(endPos.y)})==nodes.end())return{}; |
|
|
|
|
|
|
|
|
|
nodeStart=const_cast<sNode*>(&*nodes.find(sNode{int(startPos.x),int(startPos.y)})); |
|
|
|
|
nodeEnd=const_cast<sNode*>(&*nodes.find(sNode{int(endPos.x),int(endPos.y)})); |
|
|
|
|
if(nodes.find(startPos)==nodes.end())return{}; |
|
|
|
|
if(nodes.find(endPos)==nodes.end())return{}; |
|
|
|
|
|
|
|
|
|
nodeStart=&nodes[startPos]; |
|
|
|
|
nodeEnd=&nodes[endPos]; |
|
|
|
|
|
|
|
|
|
geom2d::rect<int>posPerimeter{{int(std::min(startPos.x,endPos.x)),int(std::min(startPos.y,endPos.y))},{int(abs(endPos.x-startPos.x)),int(abs(endPos.y-startPos.y))}}; |
|
|
|
|
posPerimeter.pos={int(std::clamp(posPerimeter.pos.x-maxRange*game->GetCurrentMapData().tilewidth,0.f,game->GetCurrentMapData().width*float(game->GetCurrentMapData().tilewidth))),int(std::clamp(posPerimeter.pos.y-maxRange*game->GetCurrentMapData().tilewidth,0.f,game->GetCurrentMapData().height*float(game->GetCurrentMapData().tilewidth)))}; |
|
|
|
|
posPerimeter.size={int(std::clamp(posPerimeter.size.x+maxRange*game->GetCurrentMapData().tilewidth*2,0.f,game->GetCurrentMapData().width*float(game->GetCurrentMapData().tilewidth)-posPerimeter.pos.x)),int(std::clamp(posPerimeter.size.y+maxRange*game->GetCurrentMapData().tilewidth*2,0.f,game->GetCurrentMapData().height*float(game->GetCurrentMapData().tilewidth)-posPerimeter.pos.y))}; |
|
|
|
|
|
|
|
|
|
for (int x = 0; x < game->GetCurrentMapData().width; x++){ |
|
|
|
|
for (int y = 0; y < game->GetCurrentMapData().height; y++){ |
|
|
|
|
if(geom2d::overlaps(posPerimeter,vi2d{x*game->GetCurrentMapData().tilewidth,y*game->GetCurrentMapData().tilewidth})){ |
|
|
|
|
nodes[y*game->GetCurrentMapData().width + x].bVisited = false; |
|
|
|
|
} else { |
|
|
|
|
nodes[y*game->GetCurrentMapData().width + x].bVisited = true; |
|
|
|
|
} |
|
|
|
|
nodes[y*game->GetCurrentMapData().width + x].fGlobalGoal = INFINITY; |
|
|
|
|
nodes[y*game->GetCurrentMapData().width + x].fLocalGoal = INFINITY; |
|
|
|
|
nodes[y*game->GetCurrentMapData().width + x].parent = nullptr; // No parents
|
|
|
|
|
|
|
|
|
|
for (auto&[key,node]:nodes){ |
|
|
|
|
if(geom2d::overlaps(posPerimeter,vi2d{node.x,node.y})){ |
|
|
|
|
node.bVisited = false; |
|
|
|
|
}else{ |
|
|
|
|
node.bVisited = true; |
|
|
|
|
} |
|
|
|
|
node.fGlobalGoal = INFINITY; |
|
|
|
|
node.fLocalGoal = INFINITY; |
|
|
|
|
node.parent = nullptr; // No parents
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto distance = [](sNode* a, sNode* b) // For convenience
|
|
|
|
@ -299,9 +284,4 @@ float Pathfinding::sSpline::GetNormalisedOffset(float p){ |
|
|
|
|
|
|
|
|
|
// The fractional is the offset
|
|
|
|
|
return (float)i + (p / points[i].length); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline bool operator < (const Pathfinding::sNode& lhs, const Pathfinding::sNode& rhs) |
|
|
|
|
{ return lhs.y < rhs.y || (lhs.y == rhs.y && lhs.x < rhs.x); } |
|
|
|
|
inline bool operator > (const Pathfinding::sNode& lhs, const Pathfinding::sNode& rhs) |
|
|
|
|
{ return lhs.y > rhs.y || (lhs.y == rhs.y && lhs.x > rhs.x); } |
|
|
|
|
} |