1
0

Changed cPath to have a reset method.

Also reverts "Changed raw cPath to an unique_ptr, fixes memory leak"

This reverts commit 1515d37684.
This commit is contained in:
tycho 2015-12-15 10:46:32 +00:00
parent 0fb8646198
commit 2c0ca0b4c3
4 changed files with 103 additions and 38 deletions

View File

@ -39,34 +39,7 @@ cPath::cPath(
m_Chunk(&a_Chunk), m_Chunk(&a_Chunk),
m_BadChunkFound(false) m_BadChunkFound(false)
{ {
// TODO: if src not walkable OR dest not walkable, then abort. ResetImpl(a_StartingPoint, a_EndingPoint, a_BoundingBoxWidth, a_BoundingBoxHeight);
// Borrow a new "isWalkable" from ProcessIfWalkable, make ProcessIfWalkable also call isWalkable
a_BoundingBoxWidth = 1; // Until we improve physics, if ever.
m_BoundingBoxWidth = CeilC(a_BoundingBoxWidth);
m_BoundingBoxHeight = CeilC(a_BoundingBoxHeight);
m_HalfWidth = a_BoundingBoxWidth / 2;
int HalfWidthInt = FloorC(a_BoundingBoxWidth / 2);
m_Source.x = FloorC(a_StartingPoint.x - HalfWidthInt);
m_Source.y = FloorC(a_StartingPoint.y);
m_Source.z = FloorC(a_StartingPoint.z - HalfWidthInt);
m_Destination.x = FloorC(a_EndingPoint.x - HalfWidthInt);
m_Destination.y = FloorC(a_EndingPoint.y);
m_Destination.z = FloorC(a_EndingPoint.z - HalfWidthInt);
if (GetCell(m_Source)->m_IsSolid || GetCell(m_Destination)->m_IsSolid)
{
m_Status = ePathFinderStatus::PATH_NOT_FOUND;
return;
}
m_NearestPointToTarget = GetCell(m_Source);
m_Status = ePathFinderStatus::CALCULATING;
ProcessCell(GetCell(m_Source), nullptr, 0);
} }
cPath::cPath() : m_IsValid(false) cPath::cPath() : m_IsValid(false)
@ -497,3 +470,64 @@ cPathCell * cPath::GetCell(const Vector3i & a_Location)
return &m_Map[a_Location]; return &m_Map[a_Location];
} }
} }
void cPath::ResetImpl(
const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint,
double a_BoundingBoxWidth, double a_BoundingBoxHeight
)
{
// TODO: if src not walkable OR dest not walkable, then abort.
// Borrow a new "isWalkable" from ProcessIfWalkable, make ProcessIfWalkable also call isWalkable
a_BoundingBoxWidth = 1; // Until we improve physics, if ever.
m_BoundingBoxWidth = CeilC(a_BoundingBoxWidth);
m_BoundingBoxHeight = CeilC(a_BoundingBoxHeight);
m_HalfWidth = a_BoundingBoxWidth / 2;
int HalfWidthInt = FloorC(a_BoundingBoxWidth / 2);
m_Source.x = FloorC(a_StartingPoint.x - HalfWidthInt);
m_Source.y = FloorC(a_StartingPoint.y);
m_Source.z = FloorC(a_StartingPoint.z - HalfWidthInt);
m_Destination.x = FloorC(a_EndingPoint.x - HalfWidthInt);
m_Destination.y = FloorC(a_EndingPoint.y);
m_Destination.z = FloorC(a_EndingPoint.z - HalfWidthInt);
if (GetCell(m_Source)->m_IsSolid || GetCell(m_Destination)->m_IsSolid)
{
m_Status = ePathFinderStatus::PATH_NOT_FOUND;
return;
}
m_NearestPointToTarget = GetCell(m_Source);
m_Status = ePathFinderStatus::CALCULATING;
ProcessCell(GetCell(m_Source), nullptr, 0);
}
void cPath::Reset(
cChunk & a_Chunk,
const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps,
double a_BoundingBoxWidth, double a_BoundingBoxHeight,
int a_MaxUp, int a_MaxDown
)
{
m_Map.clear();
m_OpenList = decltype(m_OpenList){};
m_StepsLeft = a_MaxSteps;
m_IsValid = true;
m_CurrentPoint = 0; // GetNextPoint increments this to 1, but that's fine, since the first cell is always a_StartingPoint
m_Chunk = &a_Chunk;
m_BadChunkFound = false;
ResetImpl(a_StartingPoint, a_EndingPoint, a_BoundingBoxWidth, a_BoundingBoxHeight);
}

View File

@ -80,6 +80,7 @@ public:
cPath(const cPath & a_other) = delete; cPath(const cPath & a_other) = delete;
cPath(cPath && a_other) = delete; cPath(cPath && a_other) = delete;
/** delete default assignment operators */
cPath & operator=(const cPath & a_other) = delete; cPath & operator=(const cPath & a_other) = delete;
cPath & operator=(cPath && a_other) = delete; cPath & operator=(cPath && a_other) = delete;
@ -136,6 +137,31 @@ public:
return m_PathPoints.size() - m_CurrentPoint; return m_PathPoints.size() - m_CurrentPoint;
} }
/** Recreates a pathfinder instance. A Mob will probably need a single pathfinder instance for its entire life.
Note that if you have a man-sized mob (1x1x2, zombies, etc), you are advised to call this function without parameters
because the declaration might change in later version of the pathFinder, and a parameter-less call always assumes a man-sized mob.
If your mob is not man-sized, you are advised to use cPath(width, height), this would be compatible with future versions,
but please be aware that as of now those parameters will be ignored and your mob will be assumed to be man sized.
@param a_BoundingBoxWidth the character's boundingbox width in blocks. Currently the parameter is ignored and 1 is assumed.
@param a_BoundingBoxHeight the character's boundingbox width in blocks. Currently the parameter is ignored and 2 is assumed.
@param a_MaxUp the character's max jump height in blocks. Currently the parameter is ignored and 1 is assumed.
@param a_MaxDown How far is the character willing to fall? Currently the parameter is ignored and 1 is assumed. */
/** Attempts to find a path starting from source to destination.
After calling this, you are expected to call Step() once per tick or once per several ticks until it returns true. You should then call getPath() to obtain the path.
Calling this before a path is found resets the current path and starts another search.
@param a_StartingPoint The function expects this position to be the lowest block the mob is in, a rule of thumb: "The block where the Zombie's knees are at".
@param a_EndingPoint "The block where the Zombie's knees want to be".
@param a_MaxSteps The maximum steps before giving up. */
void Reset(
cChunk & a_Chunk,
const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps,
double a_BoundingBoxWidth, double a_BoundingBoxHeight,
int a_MaxUp = 1, int a_MaxDown = 1
);
@ -148,6 +174,11 @@ private:
void FinishCalculation(ePathFinderStatus a_NewStatus); // Clears the memory used for calculating the path and changes the status. void FinishCalculation(ePathFinderStatus a_NewStatus); // Clears the memory used for calculating the path and changes the status.
void AttemptToFindAlternative(); void AttemptToFindAlternative();
void BuildPath(); void BuildPath();
/** Handles all logic associated with reseting the path to a clean state */
void ResetImpl(
const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint,
double a_BoundingBoxWidth, double a_BoundingBoxHeight
);
/* Openlist and closedlist management */ /* Openlist and closedlist management */
void OpenListAdd(cPathCell * a_Cell); void OpenListAdd(cPathCell * a_Cell);

View File

@ -46,17 +46,17 @@ ePathFinderStatus cPathFinder::GetNextWayPoint(cChunk & a_Chunk, const Vector3d
} }
// If m_Path has not been initialized yet, initialize it. // If m_Path has not been initialized yet, initialize it.
if (!m_Path->IsValid()) if (!m_Path.IsValid())
{ {
ResetPathFinding(a_Chunk); ResetPathFinding(a_Chunk);
} }
switch (m_Path->CalculationStep(a_Chunk)) switch (m_Path.CalculationStep(a_Chunk))
{ {
case ePathFinderStatus::NEARBY_FOUND: case ePathFinderStatus::NEARBY_FOUND:
{ {
m_NoPathToTarget = true; m_NoPathToTarget = true;
m_PathDestination = m_Path->AcceptNearbyPath(); m_PathDestination = m_Path.AcceptNearbyPath();
if (a_DontCare) if (a_DontCare)
{ {
m_FinalDestination = m_PathDestination; m_FinalDestination = m_PathDestination;
@ -89,7 +89,7 @@ ePathFinderStatus cPathFinder::GetNextWayPoint(cChunk & a_Chunk, const Vector3d
return ePathFinderStatus::CALCULATING; return ePathFinderStatus::CALCULATING;
} }
if (m_Path->NoMoreWayPoints()) if (m_Path.NoMoreWayPoints())
{ {
// We're always heading towards m_PathDestination. // We're always heading towards m_PathDestination.
// If m_PathDestination is exactly m_FinalDestination, then we're about to reach the destination. // If m_PathDestination is exactly m_FinalDestination, then we're about to reach the destination.
@ -108,10 +108,10 @@ ePathFinderStatus cPathFinder::GetNextWayPoint(cChunk & a_Chunk, const Vector3d
} }
if (m_Path->IsFirstPoint() || ((m_WayPoint - m_Source).SqrLength() < WAYPOINT_RADIUS)) if (m_Path.IsFirstPoint() || ((m_WayPoint - m_Source).SqrLength() < WAYPOINT_RADIUS))
{ {
// if the mob has just started or if the mob reached a waypoint, give them a new waypoint. // if the mob has just started or if the mob reached a waypoint, give them a new waypoint.
m_WayPoint = m_Path->GetNextPoint(); m_WayPoint = m_Path.GetNextPoint();
m_GiveUpCounter = 40; m_GiveUpCounter = 40;
return ePathFinderStatus::PATH_FOUND; return ePathFinderStatus::PATH_FOUND;
} }
@ -142,7 +142,7 @@ void cPathFinder::ResetPathFinding(cChunk &a_Chunk)
m_NoPathToTarget = false; m_NoPathToTarget = false;
m_PathDestination = m_FinalDestination; m_PathDestination = m_FinalDestination;
m_DeviationOrigin = m_PathDestination; m_DeviationOrigin = m_PathDestination;
m_Path.reset(new cPath(a_Chunk, m_Source, m_PathDestination, 20, m_Width, m_Height)); m_Path.Reset(a_Chunk, m_Source, m_PathDestination, 20, m_Width, m_Height);
} }
@ -248,7 +248,7 @@ bool cPathFinder::EnsureProperDestination(cChunk & a_Chunk)
bool cPathFinder::PathIsTooOld() const bool cPathFinder::PathIsTooOld() const
{ {
size_t acceptableDeviation = m_Path->WayPointsLeft() / 2; size_t acceptableDeviation = m_Path.WayPointsLeft() / 2;
if (acceptableDeviation == 0) if (acceptableDeviation == 0)
{ {
acceptableDeviation = 1; acceptableDeviation = 1;

View File

@ -52,7 +52,7 @@ private:
double m_Height; double m_Height;
/** The current cPath instance we have. This is discarded and recreated when a path recalculation is needed. */ /** The current cPath instance we have. This is discarded and recreated when a path recalculation is needed. */
std::unique_ptr<cPath> m_Path; cPath m_Path;
/** If 0, will give up reaching the next m_WayPoint and will recalculate path. */ /** If 0, will give up reaching the next m_WayPoint and will recalculate path. */
int m_GiveUpCounter; int m_GiveUpCounter;