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();
}