PathFinder.cpp
//==========================================================================// // Ogre A* Example - December 2009 // // // // Author: Daniel Soltyka // // E-Mail: dsoltyka [at] gmail [dot] com // // // // This example demonstrates the A* pathfinding algorithm in a 3D // // environment. // // // // Modified A* routines based off of A* Algorithm Implementation using STL // // by Justin Heyes-Jones. // // // // Original Routines can be found at http://www.heyes-jones.com/astar.html // //==========================================================================// #include "PathFinder.h" using namespace std; PathFinder::PathFinder(WorldMap* map):mMap(map) { // seed random number gen srand(time(0)); mStartNode = MapSearchNode(mMap); mEndNode = MapSearchNode(mMap); mSearchCount = 0; // set start and end nodes SetStartEndNodes(); } PathFinder::PathFinder(WorldMap *map, Ogre::Vector3 *startingPoint) : mMap(map) { // seed random number gen srand(time(0)); mStartNode = MapSearchNode(mMap); mEndNode = MapSearchNode(mMap); mSearchCount = 0; SetStartEndNodes(startingPoint); } PathFinder::~PathFinder() { // Once you're done with the solution you can free the nodes up mAStarSearch.FreeSolutionNodes(); // free memory mAStarSearch.EnsureMemoryFreed(); } // Run the path finder void PathFinder::Run() { // set flag mFoundSolution = false; // try new paths until we have a solution do { // try and find a path FindPath(); // if we haven't found a solution, we will reset everything // before the loop tries again if (!mFoundSolution) { // create a new end point and reset GetNewEndNode(); ResetSearch(); } } while (!mFoundSolution); } // Convert nodes into Ogre::Vector3 objects and fill // the deque passed to this function with those Vectors void PathFinder::GetResults(deque* waypoints) { MapSearchNode* node = mAStarSearch.GetSolutionStart(); Ogre::Vector3 waypointStart = Ogre::Vector3((Ogre::Real)(node->x * 64.0f), 0.0f, (Ogre::Real)(node->y * 64.0f)); waypoints->push_back(waypointStart); int steps = 0; for( ;; ) { node = mAStarSearch.GetSolutionNext(); if( !node ) { break; } else { Ogre::Vector3 waypoint = Ogre::Vector3((Ogre::Real)(node->x * 64.0f), 0.0f, (Ogre::Real)(node->y * 64.0f)); waypoints->push_back(waypoint); } steps ++; }; } void PathFinder::FindPath() { while(mSearchCount < NUM_SEARCHES) { // Set Start and goal states mAStarSearch.SetStartAndGoalStates( mStartNode, mEndNode ); unsigned int SearchState; unsigned int SearchSteps = 0; // step through our path and find a solution do { SearchState = mAStarSearch.SearchStep(); SearchSteps++; } while( SearchState == AStarSearch::SEARCH_STATE_SEARCHING ); if( SearchState == AStarSearch::SEARCH_STATE_SUCCEEDED ) { // search succeeded mFoundSolution = true; } else if( SearchState == AStarSearch::SEARCH_STATE_FAILED ) { // search failed mFoundSolution = false; } mSearchCount++; } } // Generate random start and end nodes void PathFinder::SetStartEndNodes() { // define start state do { mStartNode = MapSearchNode(mMap); mStartNode.x = rand()%mMap->GetWidth(); mStartNode.y = rand()%mMap->GetHeight(); } while( mMap->GetTile(mStartNode.x, mStartNode.y) == 9); // define the goal state do { mEndNode = MapSearchNode(mMap); mEndNode.x = rand()%mMap->GetWidth(); mEndNode.y = rand()%mMap->GetHeight(); } while( (mMap->GetTile(mEndNode.x, mEndNode.y) == 9) || (mStartNode == mEndNode) ); } // Generate a random end node, using a known vector as a starting location void PathFinder::SetStartEndNodes(Ogre::Vector3* startingPoint) { mStartNode.x = (int)(startingPoint->x / 64); mStartNode.y = (int)(startingPoint->z / 64); // define the goal state do { mEndNode.x = rand()%mMap->GetWidth(); mEndNode.y = rand()%mMap->GetHeight(); } while( (mMap->GetTile(mEndNode.x, mEndNode.y) == 9) || (mStartNode == mEndNode) ); } // Generate a new random end node void PathFinder::GetNewEndNode() { // define the goal state do { mEndNode.x = rand()%mMap->GetWidth(); mEndNode.y = rand()%mMap->GetHeight(); } while( (mMap->GetTile(mEndNode.x, mEndNode.y) == 9) || (mStartNode == mEndNode) ); } // Reset the search void PathFinder::ResetSearch() { mSearchCount = 0; mAStarSearch.FreeSolutionNodes(); }