From 408c1d39502b9e9fda67cfa7beb1d70779d545e4 Mon Sep 17 00:00:00 2001 From: "sigonasr2, Sig, Sigo" Date: Wed, 5 Jul 2023 21:14:36 +0000 Subject: [PATCH] Pathfinding algorithm start. Currently freezes in pathfinding loop Co-authored-by: sigonasr2 --- Crawler/Class.cpp | 2 +- Crawler/Crawler.cpp | 6 +++ Crawler/Pathfinding.cpp | 109 ++++++++++++++++++++++++++++++++++++++++ Crawler/Pathfinding.h | 24 +++++++++ Crawler/Player.cpp | 4 ++ Crawler/Player.h | 3 ++ 6 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 Crawler/Pathfinding.cpp create mode 100644 Crawler/Pathfinding.h diff --git a/Crawler/Class.cpp b/Crawler/Class.cpp index ed61c071..64ae2e9e 100644 --- a/Crawler/Class.cpp +++ b/Crawler/Class.cpp @@ -309,7 +309,7 @@ bool Wizard::RightClickAbility(){ dist--; teleportPoint=p.GetPos()+pointTowardsMouse*dist; } - if(dist>0){ + if(dist>0&&p.CanPathfindTo(p.GetPos(),teleportPoint)){ p.SetState(State::TELEPORT); p.teleportAnimationTimer=0.35; p.teleportTarget=teleportPoint; diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index 4a22174e..3ff07b5d 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -30,6 +30,9 @@ Crawler::Crawler() } bool Crawler::OnUserCreate(){ + + ConsoleCaptureStdOut(true); + InitializeLevel("assets/maps/Level1.tmx",LEVEL1); InitializeLevel("assets/maps/Level2.tmx",LEVEL2); InitializeLevel("assets/Campaigns/1_1_test.tmx",CAMPAIGN_1_1); @@ -390,6 +393,9 @@ bool Crawler::DownReleased(){ void Crawler::HandleUserInput(float fElapsedTime){ bool setIdleAnimation=true; + if(GetKey(F1).bPressed){ + ConsoleShow(F1); + } if(GetMouseWheel()>0){ switch(player.cl){ case WARRIOR:{ diff --git a/Crawler/Pathfinding.cpp b/Crawler/Pathfinding.cpp new file mode 100644 index 00000000..313f4e08 --- /dev/null +++ b/Crawler/Pathfinding.cpp @@ -0,0 +1,109 @@ +#include "Pathfinding.h" +#include "DEFINES.h" +#include "Crawler.h" + +INCLUDE_game + +void Pathfinding::Initialize(){ + nodes = new sNode[game->WORLD_SIZE.x * game->WORLD_SIZE.y]; + for (int x = 0; x < game->WORLD_SIZE.x; x++) + for (int y = 0; y < game->WORLD_SIZE.y; y++) + { + nodes[y * game->WORLD_SIZE.x + x].x = x; // ...because we give each node its own coordinates + nodes[y * game->WORLD_SIZE.x + x].y = y; + geom2d::recttile=game->GetTileCollision(game->GetCurrentLevel(),{float(x),float(y)}); + nodes[y * game->WORLD_SIZE.x + x].bObstacle = tile.pos!=game->NO_COLLISION.pos||tile.size!=game->NO_COLLISION.size; + nodes[y * game->WORLD_SIZE.x + x].parent = nullptr; + nodes[y * game->WORLD_SIZE.x + x].bVisited = false; + } + + for (int x = 0; x < game->WORLD_SIZE.x; x++) + for (int y = 0; y < game->WORLD_SIZE.y; y++) + { + if(y>0) + nodes[y*game->WORLD_SIZE.x + x].vecNeighbours.push_back(&nodes[(y - 1) * game->WORLD_SIZE.x + (x + 0)]); + if(yWORLD_SIZE.y-1) + nodes[y*game->WORLD_SIZE.x + x].vecNeighbours.push_back(&nodes[(y + 1) * game->WORLD_SIZE.x + (x + 0)]); + if (x>0) + nodes[y*game->WORLD_SIZE.x + x].vecNeighbours.push_back(&nodes[(y + 0) * game->WORLD_SIZE.x + (x - 1)]); + if(xWORLD_SIZE.x-1) + nodes[y*game->WORLD_SIZE.x + x].vecNeighbours.push_back(&nodes[(y + 0) * game->WORLD_SIZE.x + (x + 1)]); + } + + // Manually positio the start and end markers so they are not nullptr + nodeStart = &nodes[(game->WORLD_SIZE.y / 2) * game->WORLD_SIZE.x + 1]; + nodeEnd = &nodes[(game->WORLD_SIZE.y / 2) * game->WORLD_SIZE.x + game->WORLD_SIZE.x-2]; +} + +int Pathfinding::Solve_AStar(vf2d startPos,vf2d endPos){ + nodeStart=&nodes[int(startPos.y/24)*game->WORLD_SIZE.x+int(startPos.x/24)]; + nodeEnd=&nodes[int(endPos.y/24)*game->WORLD_SIZE.x+int(endPos.x/24)]; + + std::cout<<"Path Start:"<WORLD_SIZE.x; x++){ + for (int y = 0; y < game->WORLD_SIZE.y; y++){ + nodes[y*game->WORLD_SIZE.x + x].bVisited = false; + nodes[y*game->WORLD_SIZE.x + x].fGlobalGoal = INFINITY; + nodes[y*game->WORLD_SIZE.x + x].fLocalGoal = INFINITY; + nodes[y*game->WORLD_SIZE.x + x].parent = nullptr; // No parents + } + } + + auto distance = [](sNode* a, sNode* b) // For convenience + { + return sqrtf((a->x - b->x)*(a->x - b->x) + (a->y - b->y)*(a->y - b->y)); + }; + + auto heuristic = [distance](sNode* a, sNode* b) + { + return distance(a, b); + }; + + sNode *nodeCurrent = nodeStart; + nodeStart->fLocalGoal = 0.0f; + nodeStart->fGlobalGoal = heuristic(nodeStart, nodeEnd); + + std::list listNotTestedNodes; + listNotTestedNodes.push_back(nodeStart); + + while (!listNotTestedNodes.empty() && nodeCurrent != nodeEnd) + { + listNotTestedNodes.sort([](const sNode* lhs, const sNode* rhs){ return lhs->fGlobalGoal < rhs->fGlobalGoal; } ); + + while(!listNotTestedNodes.empty() && listNotTestedNodes.front()->bVisited) + listNotTestedNodes.pop_front(); + if (listNotTestedNodes.empty()) + break; + + nodeCurrent = listNotTestedNodes.front(); + nodeCurrent->bVisited = true; + for (auto nodeNeighbour : nodeCurrent->vecNeighbours) + { + if (!nodeNeighbour->bVisited && nodeNeighbour->bObstacle == 0) + listNotTestedNodes.push_back(nodeNeighbour); + + float fPossiblyLowerGoal = nodeCurrent->fLocalGoal + distance(nodeCurrent, nodeNeighbour); + + if (fPossiblyLowerGoal < nodeNeighbour->fLocalGoal) + { + nodeNeighbour->parent = nodeCurrent; + nodeNeighbour->fLocalGoal = fPossiblyLowerGoal; + nodeNeighbour->fGlobalGoal = nodeNeighbour->fLocalGoal + heuristic(nodeNeighbour, nodeEnd); + } + } + } + + int pathLength=0; + if (nodeEnd != nullptr) + { + sNode *p = nodeEnd; + while (p->parent != nullptr) + { + pathLength++; + p = p->parent; + } + } + std::cout<<"Path Length:"< vecNeighbours; // Connections to neighbours + sNode* parent; // Node connecting to this node that offers shortest parent + }; + + sNode *nodes = nullptr; + + sNode *nodeStart = nullptr; + sNode *nodeEnd = nullptr; + + void Initialize(); + int Solve_AStar(vf2d startPos,vf2d endPos); +}; \ No newline at end of file diff --git a/Crawler/Player.cpp b/Crawler/Player.cpp index 92f6bfc0..596fdf14 100644 --- a/Crawler/Player.cpp +++ b/Crawler/Player.cpp @@ -432,4 +432,8 @@ std::vectorPlayer::GetBuffs(BuffType buff){ std::vectorfilteredBuffs; std::copy_if(buffList.begin(),buffList.end(),std::back_inserter(filteredBuffs),[buff](Buff&b){return b.type==buff;}); return filteredBuffs; +} + +bool Player::CanPathfindTo(vf2d pos,vf2d targetPos){ + return path.Solve_AStar(pos,targetPos)<8;//We'll say 7 tiles or less is close enough to 650 range. Have a little bit of wiggle room. } \ No newline at end of file diff --git a/Crawler/Player.h b/Crawler/Player.h index e465c4eb..ba00d800 100644 --- a/Crawler/Player.h +++ b/Crawler/Player.h @@ -6,6 +6,7 @@ #include "Ability.h" #include "Class.h" #include "Buff.h" +#include "Pathfinding.h" struct Player{ friend class Crawler; @@ -63,6 +64,7 @@ struct Player{ bool SetPos(vf2d pos); void SetClass(Class cl); std::vectorbuffList; + Pathfinding path; protected: public: Player(); @@ -86,6 +88,7 @@ struct Player{ bool HasIframes(); void UpdateWalkingAnimation(Key direction); void UpdateIdleAnimation(Key direction); + bool CanPathfindTo(vf2d pos,vf2d targetPos); void AddBuff(BuffType type,float duration,float intensity); std::vectorGetBuffs(BuffType buff);