forked from 0ad/0ad
# Enhanced unit movement smoothness and multiplayer speed.
- Decreased MP turn length to 150 ms. - Let units move along multiple steps of a path per turn. This means they no longer "hesitate" between tiles. Especially noticeable in MP games or at low framerates. - Joined segments of paths generated by the pathfinder into linear pieces for better repathing. This was SVN commit r5224.
This commit is contained in:
parent
1b25d94183
commit
bb517e3daf
@ -67,8 +67,8 @@ CNetServer::CNetServer(CGame *pGame, CGameAttributes *pGameAttribs):
|
||||
m_pGame->GetSimulation()->SetTurnManager(this);
|
||||
|
||||
// Set an incredibly long turn length for debugging - less command batch spam that way
|
||||
for (int i=0;i<3;i++)
|
||||
CTurnManager::SetTurnLength(i, 1000);
|
||||
for (int i=0; i<3; i++)
|
||||
CTurnManager::SetTurnLength(i, 150);
|
||||
|
||||
g_ScriptingHost.SetGlobal("g_NetServer", OBJECT_TO_JSVAL(GetScript()));
|
||||
}
|
||||
|
@ -224,21 +224,21 @@ public:
|
||||
private:
|
||||
CEntity( CEntityTemplate* base, CVector3D position, float orientation, const std::set<CStr8>& actorSelections, const CStrW* building = 0 );
|
||||
|
||||
uint ProcessGotoHelper( CEntityOrder* current, size_t timestep_milli, HEntity& collide );
|
||||
uint ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis, HEntity& collide, float& timeLeft );
|
||||
|
||||
bool ProcessContactAction( CEntityOrder* current, size_t timestep_millis, CEntityOrder::EOrderType transition, SEntityAction* action );
|
||||
bool ProcessContactActionNoPathing( CEntityOrder* current, size_t timestep_millis, const CStr& animation, CScriptEvent* contactEvent, SEntityAction* action );
|
||||
|
||||
bool ProcessGeneric( CEntityOrder* current, size_t timestep_milli );
|
||||
bool ProcessGenericNoPathing( CEntityOrder* current, size_t timestep_milli );
|
||||
bool ProcessGeneric( CEntityOrder* current, size_t timestep_millis );
|
||||
bool ProcessGenericNoPathing( CEntityOrder* current, size_t timestep_millis );
|
||||
|
||||
bool ProcessProduce( CEntityOrder* order );
|
||||
|
||||
bool ProcessGotoNoPathing( CEntityOrder* current, size_t timestep_milli );
|
||||
bool ProcessGoto( CEntityOrder* current, size_t timestep_milli );
|
||||
bool ProcessGotoWaypoint( CEntityOrder* current, size_t timestep_milli, bool contact );
|
||||
bool ProcessGotoNoPathing( CEntityOrder* current, size_t timestep_millis );
|
||||
bool ProcessGoto( CEntityOrder* current, size_t timestep_millis );
|
||||
bool ProcessGotoWaypoint( CEntityOrder* current, size_t timestep_millis, bool contact );
|
||||
|
||||
bool ProcessPatrol( CEntityOrder* current, size_t timestep_milli );
|
||||
bool ProcessPatrol( CEntityOrder* current, size_t timestep_millis );
|
||||
|
||||
float ChooseMovementSpeed( float distance );
|
||||
|
||||
|
@ -85,7 +85,7 @@ float CEntity::ChooseMovementSpeed( float distance )
|
||||
|
||||
// Does all the shared processing for line-of-sight gotos
|
||||
|
||||
uint CEntity::ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis, HEntity& collide )
|
||||
uint CEntity::ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis, HEntity& collide, float& timeLeft )
|
||||
{
|
||||
float timestep=timestep_millis/1000.0f;
|
||||
|
||||
@ -101,7 +101,8 @@ uint CEntity::ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
// Curve smoothing.
|
||||
// Here there be trig.
|
||||
|
||||
float scale = ChooseMovementSpeed( len ) * timestep;
|
||||
float speed = ChooseMovementSpeed( len );
|
||||
float scale = speed * timestep;
|
||||
|
||||
// Note: Easy optimization: flag somewhere that this unit
|
||||
// is already pointing the way, and don't do this
|
||||
@ -116,7 +117,7 @@ uint CEntity::ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
{
|
||||
if ( m_turningRadius != 0 )
|
||||
{
|
||||
float maxTurningSpeed = ( m_speed / m_turningRadius ) * timestep;
|
||||
float maxTurningSpeed = ( speed / m_turningRadius ) * timestep;
|
||||
deltatheta = clamp( deltatheta, -maxTurningSpeed, maxTurningSpeed );
|
||||
}
|
||||
m_orientation.Y = m_orientation.Y + deltatheta;
|
||||
@ -152,13 +153,15 @@ uint CEntity::ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
UpdateXZOrientation();
|
||||
|
||||
if( m_bounds && m_bounds->m_type == CBoundingObject::BOUND_OABB )
|
||||
((CBoundingBox*)m_bounds)->SetOrientation( m_ahead );
|
||||
((CBoundingBox*) m_bounds)->SetOrientation( m_ahead );
|
||||
|
||||
EGotoSituation rc = NORMAL;
|
||||
|
||||
if( scale > len )
|
||||
{
|
||||
// Reached destination. Calculate how much time we have left for the next order.
|
||||
scale = len;
|
||||
timeLeft = timestep - (len / speed);
|
||||
rc = REACHED_DESTINATION;
|
||||
}
|
||||
|
||||
@ -218,7 +221,6 @@ uint CEntity::ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
|
||||
// No?
|
||||
return( COLLISION_OTHER );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,30 +260,46 @@ uint CEntity::ProcessGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
bool CEntity::ProcessGotoNoPathing( CEntityOrder* current, size_t timestep_millis )
|
||||
{
|
||||
HEntity collide;
|
||||
switch( ProcessGotoHelper( current, timestep_millis, collide ) )
|
||||
float timeLeft;
|
||||
switch( ProcessGotoHelper( current, timestep_millis, collide, timeLeft ) )
|
||||
{
|
||||
case ALREADY_AT_DESTINATION:
|
||||
{
|
||||
case ALREADY_AT_DESTINATION:
|
||||
// If on a collision path; decide where to go next. Otherwise, proceed to the next waypoint.
|
||||
if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
|
||||
{
|
||||
Repath();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_orderQueue.pop_front();
|
||||
//entf_clear(ENTF_IS_RUNNING);
|
||||
//entf_clear(ENTF_SHOULD_RUN);
|
||||
return( false );
|
||||
}
|
||||
case REACHED_DESTINATION:
|
||||
{
|
||||
// Start along the next segment of the path, if one exists
|
||||
m_orderQueue.pop_front();
|
||||
if( !m_orderQueue.empty() )
|
||||
{
|
||||
CEntityOrder* newOrder = &m_orderQueue.front();
|
||||
switch( newOrder->m_type )
|
||||
{
|
||||
case CEntityOrder::ORDER_GOTO_NOPATHING:
|
||||
case CEntityOrder::ORDER_GOTO_COLLISION:
|
||||
case CEntityOrder::ORDER_GOTO_SMOOTHED:
|
||||
size_t newTimestep = cpu_i32FromFloat(timeLeft * 1000.0f);
|
||||
return( ProcessGotoNoPathing( current, newTimestep ) );
|
||||
}
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
case COLLISION_OVERLAPPING_OBJECTS:
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
case COLLISION_WITH_DESTINATION:
|
||||
{
|
||||
// We're as close as we can get...
|
||||
m_orderQueue.pop_front();
|
||||
//entf_clear(ENTF_IS_RUNNING);
|
||||
//entf_clear(ENTF_SHOULD_RUN);
|
||||
|
||||
return( false );
|
||||
}
|
||||
case COLLISION_NEAR_DESTINATION:
|
||||
{
|
||||
// Here's a weird idea: (I hope it works)
|
||||
@ -340,16 +358,14 @@ bool CEntity::ProcessGotoNoPathing( CEntityOrder* current, size_t timestep_milli
|
||||
return( false );
|
||||
}
|
||||
case WOULD_LEAVE_MAP:
|
||||
{
|
||||
// Just stop here, Repath if necessary.
|
||||
m_orderQueue.pop_front();
|
||||
//entf_clear(ENTF_IS_RUNNING);
|
||||
//entf_clear(ENTF_SHOULD_RUN);
|
||||
return( false );
|
||||
}
|
||||
case STANCE_DISALLOWS:
|
||||
return( false ); // The stance will have cleared our order queue already
|
||||
|
||||
default:
|
||||
|
||||
default:
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
@ -511,11 +527,12 @@ bool CEntity::ProcessContactActionNoPathing( CEntityOrder* current, size_t times
|
||||
|
||||
current->m_target_location = (CVector2D)target->m_position - delta;
|
||||
|
||||
HEntity collide;
|
||||
switch( ProcessGotoHelper( current, timestep_millis, collide ) )
|
||||
HEntity collide;
|
||||
float timeLeft;
|
||||
switch( ProcessGotoHelper( current, timestep_millis, collide, timeLeft ) )
|
||||
{
|
||||
case ALREADY_AT_DESTINATION:
|
||||
case REACHED_DESTINATION:
|
||||
case ALREADY_AT_DESTINATION:
|
||||
case COLLISION_WITH_DESTINATION:
|
||||
case WOULD_LEAVE_MAP:
|
||||
case STANCE_DISALLOWS:
|
||||
@ -530,8 +547,7 @@ bool CEntity::ProcessContactActionNoPathing( CEntityOrder* current, size_t times
|
||||
// Otherwise, continue chasing
|
||||
return( false );
|
||||
default:
|
||||
// Path around it.
|
||||
|
||||
// We have a collision. Path around it.
|
||||
CEntityOrder avoidance;
|
||||
avoidance.m_type = CEntityOrder::ORDER_GOTO_COLLISION;
|
||||
CVector2D right;
|
||||
|
@ -38,7 +38,23 @@ void CPathfindEngine::RequestLowLevelPath( HEntity entity, const CVector2D& dest
|
||||
|
||||
if ( mLowPathfinder.FindPath(source, destination, entity, radius) )
|
||||
{
|
||||
std::vector<CVector2D> path = mLowPathfinder.GetLastPath();
|
||||
std::vector<CVector2D> stepwisePath = mLowPathfinder.GetLastPath();
|
||||
|
||||
// Make the path take as few steps as possible by collapsing steps in the same direction together.
|
||||
std::vector<CVector2D> path;
|
||||
CVector2D lastDir(0, 0);
|
||||
for(size_t i=0; i < stepwisePath.size(); i++)
|
||||
{
|
||||
if(i >= 2 && stepwisePath[i]-stepwisePath[i-1] == lastDir)
|
||||
// We're in a colinear range; just update last point
|
||||
path[path.size()-1] = stepwisePath[i];
|
||||
else
|
||||
path.push_back(stepwisePath[i]);
|
||||
|
||||
if(i >= 1)
|
||||
lastDir = stepwisePath[i] - stepwisePath[i-1];
|
||||
}
|
||||
|
||||
if( path.size() > 0 )
|
||||
{
|
||||
// Push the path onto the front of our order queue in reverse order,
|
||||
|
Loading…
Reference in New Issue
Block a user