# Improved pathfinder precision.

Added code to requestLowLevelPath that modifies the final waypoint to
use exactly the coordinates where the player clicked, instead of the
rounded-to-nearest-tile coordinates from the A* pathfinder. A more
complete fix required eventually might be to make the A* engine itself
aware of fractional locations within a tile but for now this seemed like
a simple thing to do.

Also fixed a bug that was causing the final step of the path not to be
added: the code was adding an ORDER_PATH_END_MARKER but no
ORDER_GOTO_NOPATHING for the final point. The ORDER_PATH_END_MARKER
doesn't seem to do anything useful here so the unit never went that last
step.

Also fixed a bug with "pass-through-allies" that was causing units to
avoid allies anyway: although the pathfinder assumed you could pass
through allies, when you actually bumped into one while executing a goto
instruction, the collision test used did not check for
pass-through-allies so you ended up avoiding allies anyway. This might
not be too horrible if it works in practice (since the avoidance was
done using simple local work, not a full repath) but I've removed it for
now since it might cause problems with formations, when avoidance will
not be trivial.

This was SVN commit r4226.
This commit is contained in:
Matei 2006-08-17 21:09:46 +00:00
parent 802e099e35
commit e2add58410
3 changed files with 33 additions and 6 deletions

View File

@ -115,6 +115,8 @@ HEntity getCollisionObject( CEntity* entity )
{
if( !(*it)->m_bounds ) continue;
if( (*it)->m_bounds == entity->m_bounds ) continue;
if( entity->m_base->m_passThroughAllies && (*it)->m_base->m_passThroughAllies
&& entity->m_player == (*it)->m_player ) continue;
if( entity->m_bounds->intersects( (*it)->m_bounds ) )
{
HEntity collisionObject = HEntity((*it)->me);

View File

@ -51,9 +51,30 @@ void CPathfindEngine::requestLowLevelPath( HEntity entity, const CVector2D& dest
node.m_data[0].location = *it;
entity->m_orderQueue.push_back(node);
}
node.m_type = CEntityOrder::ORDER_PATH_END_MARKER;
node.m_data[0].location = *it;
// Hack to make pathfinding slightly more precise:
// If the radius was 0, make the final node be exactly at the destination
// (otherwise, go to wherever the pathfinder tells us since we just want to be in range)
CVector2D finalDest = (radius==0 ? destination : (*it));
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
node.m_data[0].location = finalDest;
entity->m_orderQueue.push_back(node);
node.m_type = CEntityOrder::ORDER_PATH_END_MARKER;
node.m_data[0].location = finalDest;
entity->m_orderQueue.push_back(node);
}
else {
// Hack to make pathfinding slightly more precise:
// If radius = 0, we are still moving within the same tile, so add a GOTO order anyway
if(radius == 0)
{
CEntityOrder node;
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
node.m_data[0].location = destination;
entity->m_orderQueue.push_back(node);
node.m_type = CEntityOrder::ORDER_PATH_END_MARKER;
node.m_data[0].location = destination;
entity->m_orderQueue.push_back(node);
}
}
}
else

View File

@ -158,10 +158,11 @@ void RandomizeLocations(CEntityOrder order, const vector <HEntity> &entities, bo
float _x, _y;
CEntityOrder randomizedOrder = order;
CSimulation* sim = g_Game->GetSimulation();
do
{
_x = (float)( rand() % 20000 ) / 10000.0f - 1.0f;
_y = (float)( rand() % 20000 ) / 10000.0f - 1.0f;
_x = sim->RandFloat() * 2.0f - 1.0f;
_y = sim->RandFloat() * 2.0f - 1.0f;
}
while( ( _x * _x ) + ( _y * _y ) > 1.0f );
@ -402,6 +403,9 @@ int CSimulation::RandInt(int maxVal)
// Get a random float in [0, 1) from the simulation's random number generator
float CSimulation::RandFloat()
{
boost::uniform_01<boost::mt19937, float> distr(m_Random);
return distr();
// Cannot use uniform_01 here because it is not a real distribution, but rather an
// utility class that makes a copy of the generator, and therefore it would repeatedly
// return the same values because it never modifies our copy of the generator.
boost::uniform_real<float> distr(0.0f, 1.0f);
return distr(m_Random);
}