From 2aedf48304afbdf830914efed2ec9fb614016948 Mon Sep 17 00:00:00 2001 From: Chakakhan Date: Sun, 26 Jun 2011 07:03:08 +0000 Subject: [PATCH] #788 Eliminate delay in path finding (and therefore moving) This was SVN commit r9665. --- .../public/simulation/data/pathfinder.xml | 19 +++++ source/simulation2/Simulation2.cpp | 14 ++++ .../simulation2/components/CCmpPathfinder.cpp | 77 +++++++++++++++++++ .../components/CCmpPathfinder_Common.h | 13 ++++ .../simulation2/components/ICmpPathfinder.h | 5 ++ 5 files changed, 128 insertions(+) diff --git a/binaries/data/mods/public/simulation/data/pathfinder.xml b/binaries/data/mods/public/simulation/data/pathfinder.xml index bebef737d5..7abfc2140d 100644 --- a/binaries/data/mods/public/simulation/data/pathfinder.xml +++ b/binaries/data/mods/public/simulation/data/pathfinder.xml @@ -1,6 +1,25 @@ + + 64 + diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index a66474ddbe..fb8bcf67c7 100644 --- a/source/simulation2/Simulation2.cpp +++ b/source/simulation2/Simulation2.cpp @@ -229,6 +229,10 @@ bool CSimulation2Impl::Update(int turnLength, const std::vectorFlushTurn(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::vectorProcessSameTurnMoves(); + { CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed); m_ComponentManager.BroadcastMessage(msgUpdate); @@ -247,6 +256,11 @@ bool CSimulation2Impl::Update(int turnLength, const std::vectorProcessSameTurnMoves(); + + // Clean up any entities destroyed during the simulation update m_ComponentManager.FlushDestroyedComponents(); diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp index fe511a9ad8..ef7ab10dc7 100644 --- a/source/simulation2/components/CCmpPathfinder.cpp +++ b/source/simulation2/components/CCmpPathfinder.cpp @@ -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& 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& 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 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 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; + } +} + diff --git a/source/simulation2/components/CCmpPathfinder_Common.h b/source/simulation2/components/CCmpPathfinder_Common.h index 607db1e5d9..c3daaebf4f 100644 --- a/source/simulation2/components/CCmpPathfinder_Common.h +++ b/source/simulation2/components/CCmpPathfinder_Common.h @@ -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* m_Grid; // terrain/passability information Grid* 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& longRequests); + + virtual void ProcessShortRequests(const std::vector& shortRequests); + + virtual void ProcessSameTurnMoves(); + /** * Returns the tile containing the given position */ diff --git a/source/simulation2/components/ICmpPathfinder.h b/source/simulation2/components/ICmpPathfinder.h index c6ea9589b0..48bca1f96f 100644 --- a/source/simulation2/components/ICmpPathfinder.h +++ b/source/simulation2/components/ICmpPathfinder.h @@ -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) };