#788 Eliminate delay in path finding (and therefore moving)
This was SVN commit r9665.
This commit is contained in:
parent
5bc125a91f
commit
2aedf48304
@ -1,6 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Pathfinder>
|
||||
|
||||
<!--
|
||||
Previously all move commands during a turn were
|
||||
queued up and processed asynchronously at the start
|
||||
of the next turn. Now we are processing queued up
|
||||
events several times duing the turn. This improves
|
||||
responsiveness and units move more smoothly especially.
|
||||
when in formation. There is still a call at the
|
||||
beginning of a turn to process all outstanding moves -
|
||||
this will handle any moves above the MaxSameTurnMoves
|
||||
threshold.
|
||||
|
||||
TODO - The moves processed at the beginning of the
|
||||
turn do not count against the maximum moves per turn
|
||||
currently. The thinking is that this will eventually
|
||||
happen in another thread. Either way this probably
|
||||
will require some adjustment and rethinking.
|
||||
-->
|
||||
<MaxSameTurnMoves>64</MaxSameTurnMoves>
|
||||
|
||||
<PassabilityClasses>
|
||||
|
||||
<!-- Unit pathfinding classes: -->
|
||||
|
@ -229,6 +229,10 @@ bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
|
||||
if (!cmpCommandQueue.null())
|
||||
cmpCommandQueue->FlushTurn(commands);
|
||||
|
||||
// Process newly generated move commands so the UI feels snappy
|
||||
if (!cmpPathfinder.null())
|
||||
cmpPathfinder->ProcessSameTurnMoves();
|
||||
|
||||
// Send all the update phases
|
||||
{
|
||||
CMessageUpdate msgUpdate(turnLengthFixed);
|
||||
@ -238,6 +242,11 @@ bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
|
||||
CMessageUpdate_MotionFormation msgUpdate(turnLengthFixed);
|
||||
m_ComponentManager.BroadcastMessage(msgUpdate);
|
||||
}
|
||||
|
||||
// Process move commands for formations (group proxy)
|
||||
if (!cmpPathfinder.null())
|
||||
cmpPathfinder->ProcessSameTurnMoves();
|
||||
|
||||
{
|
||||
CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed);
|
||||
m_ComponentManager.BroadcastMessage(msgUpdate);
|
||||
@ -247,6 +256,11 @@ bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
|
||||
m_ComponentManager.BroadcastMessage(msgUpdate);
|
||||
}
|
||||
|
||||
// Process moves resulting from group proxy movement (unit needs to catch up or realign) and any others
|
||||
if (!cmpPathfinder.null())
|
||||
cmpPathfinder->ProcessSameTurnMoves();
|
||||
|
||||
|
||||
// Clean up any entities destroyed during the simulation update
|
||||
m_ComponentManager.FlushDestroyedComponents();
|
||||
|
||||
|
@ -58,6 +58,9 @@ void CCmpPathfinder::Init(const CParamNode& UNUSED(paramNode))
|
||||
CParamNode externalParamNode;
|
||||
CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml");
|
||||
|
||||
const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder");
|
||||
m_MaxSameTurnMoves = pathingSettings.GetChild("MaxSameTurnMoves").ToInt();
|
||||
|
||||
|
||||
const CParamNode::ChildrenMap& passClasses = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses").GetChildren();
|
||||
for (CParamNode::ChildrenMap::const_iterator it = passClasses.begin(); it != passClasses.end(); ++it)
|
||||
@ -199,6 +202,11 @@ void CCmpPathfinder::HandleMessage(const CMessage& msg, bool UNUSED(global))
|
||||
m_TerrainDirty = true;
|
||||
break;
|
||||
}
|
||||
case MT_TurnStart:
|
||||
{
|
||||
m_SameTurnMovesCount = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,6 +443,12 @@ void CCmpPathfinder::FinishAsyncRequests()
|
||||
// TODO: this computation should be done incrementally, spread
|
||||
// across multiple frames (or even multiple turns)
|
||||
|
||||
ProcessLongRequests(longRequests);
|
||||
ProcessShortRequests(shortRequests);
|
||||
}
|
||||
|
||||
void CCmpPathfinder::ProcessLongRequests(const std::vector<AsyncLongPathRequest>& longRequests)
|
||||
{
|
||||
for (size_t i = 0; i < longRequests.size(); ++i)
|
||||
{
|
||||
const AsyncLongPathRequest& req = longRequests[i];
|
||||
@ -443,7 +457,10 @@ void CCmpPathfinder::FinishAsyncRequests()
|
||||
CMessagePathResult msg(req.ticket, path);
|
||||
GetSimContext().GetComponentManager().PostMessage(req.notify, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CCmpPathfinder::ProcessShortRequests(const std::vector<AsyncShortPathRequest>& shortRequests)
|
||||
{
|
||||
for (size_t i = 0; i < shortRequests.size(); ++i)
|
||||
{
|
||||
const AsyncShortPathRequest& req = shortRequests[i];
|
||||
@ -454,3 +471,63 @@ void CCmpPathfinder::FinishAsyncRequests()
|
||||
GetSimContext().GetComponentManager().PostMessage(req.notify, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CCmpPathfinder::ProcessSameTurnMoves()
|
||||
{
|
||||
u32 moveCount;
|
||||
|
||||
if (m_AsyncLongPathRequests.size() > 0)
|
||||
{
|
||||
// Figure out how many moves we can do this time
|
||||
moveCount = m_MaxSameTurnMoves - m_SameTurnMovesCount;
|
||||
|
||||
if (moveCount <= 0)
|
||||
return;
|
||||
|
||||
// Copy the long request elements we are going to process into a new array
|
||||
std::vector<AsyncLongPathRequest> longRequests;
|
||||
if (m_AsyncLongPathRequests.size() <= moveCount)
|
||||
{
|
||||
m_AsyncLongPathRequests.swap(longRequests);
|
||||
moveCount = longRequests.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
longRequests.resize(moveCount);
|
||||
copy(m_AsyncLongPathRequests.begin(), m_AsyncLongPathRequests.begin() + moveCount, longRequests.begin());
|
||||
m_AsyncLongPathRequests.erase(m_AsyncLongPathRequests.begin(), m_AsyncLongPathRequests.begin() + moveCount);
|
||||
}
|
||||
|
||||
ProcessLongRequests(longRequests);
|
||||
|
||||
m_SameTurnMovesCount += moveCount;
|
||||
}
|
||||
|
||||
if (m_AsyncShortPathRequests.size() > 0)
|
||||
{
|
||||
// Figure out how many moves we can do now
|
||||
moveCount = m_MaxSameTurnMoves - m_SameTurnMovesCount;
|
||||
|
||||
if (moveCount <= 0)
|
||||
return;
|
||||
|
||||
// Copy the short request elements we are going to process into a new array
|
||||
std::vector<AsyncShortPathRequest> shortRequests;
|
||||
if (m_AsyncShortPathRequests.size() <= moveCount)
|
||||
{
|
||||
m_AsyncShortPathRequests.swap(shortRequests);
|
||||
moveCount = shortRequests.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
shortRequests.resize(moveCount);
|
||||
copy(m_AsyncShortPathRequests.begin(), m_AsyncShortPathRequests.begin() + moveCount, shortRequests.begin());
|
||||
m_AsyncShortPathRequests.erase(m_AsyncShortPathRequests.begin(), m_AsyncShortPathRequests.begin() + moveCount);
|
||||
}
|
||||
|
||||
ProcessShortRequests(shortRequests);
|
||||
|
||||
m_SameTurnMovesCount += moveCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,6 +161,7 @@ public:
|
||||
componentManager.SubscribeToMessageType(MT_Update);
|
||||
componentManager.SubscribeToMessageType(MT_RenderSubmit); // for debug overlays
|
||||
componentManager.SubscribeToMessageType(MT_TerrainChanged);
|
||||
componentManager.SubscribeToMessageType(MT_TurnStart);
|
||||
}
|
||||
|
||||
DEFAULT_COMPONENT_ALLOCATOR(Pathfinder)
|
||||
@ -187,8 +188,14 @@ public:
|
||||
Grid<TerrainTile>* m_Grid; // terrain/passability information
|
||||
Grid<u8>* m_ObstructionGrid; // cached obstruction information (TODO: we shouldn't bother storing this, it's redundant with LSBs of m_Grid)
|
||||
bool m_TerrainDirty; // indicates if m_Grid has been updated since terrain changed
|
||||
|
||||
// For responsiveness we will procees some moves in the same turn they were generated in
|
||||
|
||||
u16 m_MaxSameTurnMoves; // max number of moves that can be created and processed in the same turn
|
||||
u16 m_SameTurnMovesCount; // current number of same turn moves we have processed this turn
|
||||
|
||||
// Debugging - output from last pathfind operation:
|
||||
|
||||
PathfindTileGrid* m_DebugGrid;
|
||||
u32 m_DebugSteps;
|
||||
Path* m_DebugPath;
|
||||
@ -242,6 +249,12 @@ public:
|
||||
|
||||
virtual void FinishAsyncRequests();
|
||||
|
||||
virtual void ProcessLongRequests(const std::vector<AsyncLongPathRequest>& longRequests);
|
||||
|
||||
virtual void ProcessShortRequests(const std::vector<AsyncShortPathRequest>& shortRequests);
|
||||
|
||||
virtual void ProcessSameTurnMoves();
|
||||
|
||||
/**
|
||||
* Returns the tile containing the given position
|
||||
*/
|
||||
|
@ -159,6 +159,11 @@ public:
|
||||
*/
|
||||
virtual void FinishAsyncRequests() = 0;
|
||||
|
||||
/**
|
||||
* Process moves during the same turn they were created in to improve responsiveness.
|
||||
*/
|
||||
virtual void ProcessSameTurnMoves() = 0;
|
||||
|
||||
DECLARE_INTERFACE_TYPE(Pathfinder)
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user