# 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:
parent
802e099e35
commit
e2add58410
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user