#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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Pathfinder>
|
<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>
|
<PassabilityClasses>
|
||||||
|
|
||||||
<!-- Unit pathfinding classes: -->
|
<!-- Unit pathfinding classes: -->
|
||||||
|
@ -229,6 +229,10 @@ bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
|
|||||||
if (!cmpCommandQueue.null())
|
if (!cmpCommandQueue.null())
|
||||||
cmpCommandQueue->FlushTurn(commands);
|
cmpCommandQueue->FlushTurn(commands);
|
||||||
|
|
||||||
|
// Process newly generated move commands so the UI feels snappy
|
||||||
|
if (!cmpPathfinder.null())
|
||||||
|
cmpPathfinder->ProcessSameTurnMoves();
|
||||||
|
|
||||||
// Send all the update phases
|
// Send all the update phases
|
||||||
{
|
{
|
||||||
CMessageUpdate msgUpdate(turnLengthFixed);
|
CMessageUpdate msgUpdate(turnLengthFixed);
|
||||||
@ -238,6 +242,11 @@ bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
|
|||||||
CMessageUpdate_MotionFormation msgUpdate(turnLengthFixed);
|
CMessageUpdate_MotionFormation msgUpdate(turnLengthFixed);
|
||||||
m_ComponentManager.BroadcastMessage(msgUpdate);
|
m_ComponentManager.BroadcastMessage(msgUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process move commands for formations (group proxy)
|
||||||
|
if (!cmpPathfinder.null())
|
||||||
|
cmpPathfinder->ProcessSameTurnMoves();
|
||||||
|
|
||||||
{
|
{
|
||||||
CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed);
|
CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed);
|
||||||
m_ComponentManager.BroadcastMessage(msgUpdate);
|
m_ComponentManager.BroadcastMessage(msgUpdate);
|
||||||
@ -247,6 +256,11 @@ bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
|
|||||||
m_ComponentManager.BroadcastMessage(msgUpdate);
|
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
|
// Clean up any entities destroyed during the simulation update
|
||||||
m_ComponentManager.FlushDestroyedComponents();
|
m_ComponentManager.FlushDestroyedComponents();
|
||||||
|
|
||||||
|
@ -58,6 +58,9 @@ void CCmpPathfinder::Init(const CParamNode& UNUSED(paramNode))
|
|||||||
CParamNode externalParamNode;
|
CParamNode externalParamNode;
|
||||||
CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml");
|
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();
|
const CParamNode::ChildrenMap& passClasses = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses").GetChildren();
|
||||||
for (CParamNode::ChildrenMap::const_iterator it = passClasses.begin(); it != passClasses.end(); ++it)
|
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;
|
m_TerrainDirty = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MT_TurnStart:
|
||||||
|
{
|
||||||
|
m_SameTurnMovesCount = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,6 +443,12 @@ void CCmpPathfinder::FinishAsyncRequests()
|
|||||||
// TODO: this computation should be done incrementally, spread
|
// TODO: this computation should be done incrementally, spread
|
||||||
// across multiple frames (or even multiple turns)
|
// 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)
|
for (size_t i = 0; i < longRequests.size(); ++i)
|
||||||
{
|
{
|
||||||
const AsyncLongPathRequest& req = longRequests[i];
|
const AsyncLongPathRequest& req = longRequests[i];
|
||||||
@ -443,7 +457,10 @@ void CCmpPathfinder::FinishAsyncRequests()
|
|||||||
CMessagePathResult msg(req.ticket, path);
|
CMessagePathResult msg(req.ticket, path);
|
||||||
GetSimContext().GetComponentManager().PostMessage(req.notify, msg);
|
GetSimContext().GetComponentManager().PostMessage(req.notify, msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCmpPathfinder::ProcessShortRequests(const std::vector<AsyncShortPathRequest>& shortRequests)
|
||||||
|
{
|
||||||
for (size_t i = 0; i < shortRequests.size(); ++i)
|
for (size_t i = 0; i < shortRequests.size(); ++i)
|
||||||
{
|
{
|
||||||
const AsyncShortPathRequest& req = shortRequests[i];
|
const AsyncShortPathRequest& req = shortRequests[i];
|
||||||
@ -454,3 +471,63 @@ void CCmpPathfinder::FinishAsyncRequests()
|
|||||||
GetSimContext().GetComponentManager().PostMessage(req.notify, msg);
|
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_Update);
|
||||||
componentManager.SubscribeToMessageType(MT_RenderSubmit); // for debug overlays
|
componentManager.SubscribeToMessageType(MT_RenderSubmit); // for debug overlays
|
||||||
componentManager.SubscribeToMessageType(MT_TerrainChanged);
|
componentManager.SubscribeToMessageType(MT_TerrainChanged);
|
||||||
|
componentManager.SubscribeToMessageType(MT_TurnStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_COMPONENT_ALLOCATOR(Pathfinder)
|
DEFAULT_COMPONENT_ALLOCATOR(Pathfinder)
|
||||||
@ -187,8 +188,14 @@ public:
|
|||||||
Grid<TerrainTile>* m_Grid; // terrain/passability information
|
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)
|
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
|
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:
|
// Debugging - output from last pathfind operation:
|
||||||
|
|
||||||
PathfindTileGrid* m_DebugGrid;
|
PathfindTileGrid* m_DebugGrid;
|
||||||
u32 m_DebugSteps;
|
u32 m_DebugSteps;
|
||||||
Path* m_DebugPath;
|
Path* m_DebugPath;
|
||||||
@ -242,6 +249,12 @@ public:
|
|||||||
|
|
||||||
virtual void FinishAsyncRequests();
|
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
|
* Returns the tile containing the given position
|
||||||
*/
|
*/
|
||||||
|
@ -159,6 +159,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void FinishAsyncRequests() = 0;
|
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)
|
DECLARE_INTERFACE_TYPE(Pathfinder)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user