diff --git a/engine/Game/GameObject.cpp b/engine/Game/GameObject.cpp index 0c133b95..b8c852fe 100644 --- a/engine/Game/GameObject.cpp +++ b/engine/Game/GameObject.cpp @@ -69,7 +69,7 @@ GameObject::SetSize(const glm::vec2& newSize) m_sprite.SetSize(newSize); m_currentGameObjectState.m_occupiedNodes = m_appHandle.GetLevel().GameObjectMoved( - m_sprite.GetTransformedRectangle(), m_currentGameObjectState.m_occupiedNodes); + m_sprite.GetTransformedRectangle(), m_currentGameObjectState.m_occupiedNodes, m_id); } void @@ -145,7 +145,7 @@ GameObject::SetHasCollision(bool hasCollision) { for (auto& node : m_currentGameObjectState.m_occupiedNodes) { - m_appHandle.GetLevel().GetPathfinder().SetNodeFreed(node); + m_appHandle.GetLevel().GetPathfinder().SetNodeFreed(node, m_id); } } else @@ -178,7 +178,7 @@ GameObject::UpdateCollision() if (m_hasCollision) { m_currentGameObjectState.m_occupiedNodes = m_appHandle.GetLevel().GameObjectMoved( - m_sprite.GetTransformedRectangle(), m_currentGameObjectState.m_occupiedNodes); + m_sprite.GetTransformedRectangle(), m_currentGameObjectState.m_occupiedNodes, m_id); } } diff --git a/engine/Game/Level.cpp b/engine/Game/Level.cpp index d3f1989f..5186fe9c 100644 --- a/engine/Game/Level.cpp +++ b/engine/Game/Level.cpp @@ -52,7 +52,9 @@ Level::Load(Application* context, const std::string& pathToLevel) nodeJson["id"], std::vector< Node::NodeID >(nodeJson["connected to"].begin(), nodeJson["connected to"].end()), - nodeJson["occupied"])); + nodeJson["occupied"], + std::vector< Object::ID >(nodeJson["nodesOccupying"].begin(), + nodeJson["nodesOccupying"].end()))); } m_pathFinder.SetInitialized(); @@ -153,6 +155,7 @@ Level::Save(const std::string& pathToLevel) nodeJson["position"] = {node.m_position.x, node.m_position.y}; nodeJson["connected to"] = node.m_connectedNodes; nodeJson["occupied"] = node.m_occupied; + nodeJson["nodesOccupying"] = node.m_objectsOccupyingThisNode; json["PATHFINDER"]["nodes"].emplace_back(nodeJson); } @@ -311,7 +314,7 @@ Level::AddGameObject(GameObject::TYPE objectType) std::vector< Tile_t > Level::GameObjectMoved(const std::array< glm::vec2, 4 >& box, - const std::vector< Tile_t >& currentTiles) + const std::vector< Tile_t >& currentTiles, Object::ID objectID) { auto new_tiles = GetTilesFromBoundingBox(box); @@ -319,12 +322,12 @@ Level::GameObjectMoved(const std::array< glm::vec2, 4 >& box, { for (auto tileID : currentTiles) { - m_pathFinder.SetNodeFreed(tileID); + m_pathFinder.SetNodeFreed(tileID, objectID); } for (auto tileID : new_tiles) { - m_pathFinder.SetNodeOccupied(tileID); + m_pathFinder.SetNodeOccupied(tileID, objectID); } } diff --git a/engine/Game/Level.hpp b/engine/Game/Level.hpp index 342f69ae..0369d539 100644 --- a/engine/Game/Level.hpp +++ b/engine/Game/Level.hpp @@ -32,9 +32,19 @@ class Level void MoveObjs(const glm::vec2& moveBy); + /** + * \brief Called whenever an ombject with collision is moved. Generates the vector of + * occupied tiles/nodes, based on \c box + * + * \param[in] box Object's bounding box, needed to calculate collision + * \param[in] currentTiles Tiles occupied by the object, up to this point + * \param[in] objectID ID of the object that was moved + * + * \return Vector of tiles/nodes occupied by given object + */ std::vector< Tile_t > - GameObjectMoved(const std::array< glm::vec2, 4 >& box, - const std::vector< Tile_t >& currentTiles); + GameObjectMoved(const std::array< glm::vec2, 4 >& box, const std::vector< Tile_t >& currentTiles, + Object::ID objectID); void Create(Application* context, const glm::ivec2& size); diff --git a/engine/Game/PathFinder.cpp b/engine/Game/PathFinder.cpp index f3fcb761..b2221335 100644 --- a/engine/Game/PathFinder.cpp +++ b/engine/Game/PathFinder.cpp @@ -257,7 +257,7 @@ PathFinder::GetPath(const glm::vec2& source, const glm::vec2& destination) } void -PathFinder::SetNodeOccupied(const Tile_t& nodeCoords) +PathFinder::SetNodeOccupied(const Tile_t& nodeCoords, Object::ID objectID) { if (nodeCoords != Tile_t{-1, -1}) { @@ -268,11 +268,12 @@ PathFinder::SetNodeOccupied(const Tile_t& nodeCoords) assert(node != m_nodes.end()); node->m_occupied = true; + node->m_objectsOccupyingThisNode.push_back(objectID); } } void -PathFinder::SetNodeFreed(const Tile_t& nodeCoords) +PathFinder::SetNodeFreed(const Tile_t& nodeCoords, Object::ID objectID) { if (nodeCoords != Tile_t{-1, -1}) { @@ -282,7 +283,14 @@ PathFinder::SetNodeFreed(const Tile_t& nodeCoords) assert(node != m_nodes.end()); - node->m_occupied = false; + node->m_objectsOccupyingThisNode.erase(std::find(node->m_objectsOccupyingThisNode.begin(), + node->m_objectsOccupyingThisNode.end(), + objectID)); + + if (node->m_objectsOccupyingThisNode.empty()) + { + node->m_occupied = false; + } } } diff --git a/engine/Game/PathFinder.hpp b/engine/Game/PathFinder.hpp index b76adf03..e9f551cc 100644 --- a/engine/Game/PathFinder.hpp +++ b/engine/Game/PathFinder.hpp @@ -18,14 +18,16 @@ struct Node : public Object } Node(const glm::ivec2& coords, const glm::vec2& posOnMap, NodeID ID, - const std::vector< NodeID >& connectedTo, bool occupied = false) + const std::vector< NodeID >& connectedTo = {}, bool occupied = false, + const std::vector< Object::ID >& objectOccupying = {}) : Object(Object::TYPE::PATHFINDER_NODE), m_xPos(coords.x), m_yPos(coords.y), m_position(posOnMap), m_occupied(occupied), m_ID(ID), - m_connectedNodes(connectedTo) + m_connectedNodes(connectedTo), + m_objectsOccupyingThisNode(objectOccupying) { } @@ -43,6 +45,7 @@ struct Node : public Object NodeID m_parentNode = -1; std::vector< NodeID > m_connectedNodes = {}; + std::vector< Object::ID > m_objectsOccupyingThisNode = {}; bool m_visited = false; int32_t m_localCost = std::numeric_limits< int32_t >::max(); @@ -180,17 +183,19 @@ class PathFinder * \brief Set node (on the given tile) occupied * * \param[in] nodeCoords Tile on the map + * \param[in] objectID Object that occupies this node/tile */ void - SetNodeOccupied(const Tile_t& nodeCoords); + SetNodeOccupied(const Tile_t& nodeCoords, Object::ID objectID); /** * \brief Set node (on the given tile) freed * * \param[in] nodeCoords Tile on the map + * \param[in] objectID Object that no longer occupies this node/tile */ void - SetNodeFreed(const Tile_t& nodeCoords); + SetNodeFreed(const Tile_t& nodeCoords, Object::ID objectID); private: bool m_initialized = false;