private void DebugDrawTestVisibility() { int characterID = _gameWorldController.Model.CurrentCharacterID; RoomKey roomKey = _gameWorldController.Model.CurrentGame.CurrentRoomKey; CharacterEntity entity = _gameWorldController.Model.GetCharacterEntity(characterID); if (entity != null) { Point3d startWorldPos = entity.Position; Point2d endPixelPos = GetMousePixelPosition(); Point3d endWorldPos = GameConstants.ConvertPixelPositionToRoomPosition(endPixelPos); // Draw the target nav cell AsyncRPGSharedLib.Navigation.NavMesh navMesh = PathfindingSystem.GetNavMesh(roomKey); if (navMesh != null) { NavRef startNavRef = navMesh.ComputeNavRefAtPoint(startWorldPos); NavRef endNavRef = navMesh.ComputeNavRefAtPoint(endWorldPos); if (startNavRef.IsValid && endNavRef.IsValid) { bool canSee = navMesh.NavRefCanSeeOtherNavRef(startNavRef, endNavRef); Color debugColor = canSee ? Color.green : Color.red; // Draw a box around the nav cell { Point3d endCenterWorldPos = navMesh.ComputeNavCellCenter((uint)endNavRef.NavCellIndex); Point2d endCenterPixelPos = GameConstants.ConvertRoomPositionToPixelPosition(endCenterWorldPos); float halfWidth = (float)GameConstants.NAV_MESH_PIXEL_SIZE / 2.0f; Vector3 boxUL = ClientGameConstants.ConvertPixelPositionToVertexPosition( endCenterPixelPos.x - halfWidth, endCenterPixelPos.y - halfWidth, 0.0f); Vector3 boxUR = ClientGameConstants.ConvertPixelPositionToVertexPosition( endCenterPixelPos.x + halfWidth, endCenterPixelPos.y - halfWidth, 0.0f); Vector3 boxLR = ClientGameConstants.ConvertPixelPositionToVertexPosition( endCenterPixelPos.x + halfWidth, endCenterPixelPos.y + halfWidth, 0.0f); Vector3 boxLL = ClientGameConstants.ConvertPixelPositionToVertexPosition( endCenterPixelPos.x - halfWidth, endCenterPixelPos.y + halfWidth, 0.0f); Debug.DrawLine(boxUL, boxUR, debugColor); Debug.DrawLine(boxUR, boxLR, debugColor); Debug.DrawLine(boxLR, boxLL, debugColor); Debug.DrawLine(boxLL, boxUL, debugColor); } // Update the visibility status label _visibilityStatusLabel.Text = canSee ? "VISIBLE" : "INVISIBLE"; _visibilityStatusLabel.SetLocalPosition(endPixelPos.x, endPixelPos.y); _visibilityStatusLabel.Color = debugColor; _visibilityStatusLabel.Visible = true; // Render the ray-cast line { Vector3 startVertex = ClientGameConstants.ConvertRoomPositionToVertexPosition(startWorldPos); Vector3 endVertex = ClientGameConstants.ConvertRoomPositionToVertexPosition(endWorldPos); Debug.DrawLine(startVertex, endVertex, debugColor); } } } } }
private void ComputeRawPath() { int nodesSearchedThisUpdate = 0; // Keep searching until we either find the end // or we're not allowed to search anymore while (!m_nodeHeap.Empty() && m_totalNodesSearched < MAX_TOTAL_NODES_SEARCHED_ALLOWED && (m_maxNodesSearchedPerUpdate == 0 || (m_maxNodesSearchedPerUpdate > 0 && nodesSearchedThisUpdate < m_maxNodesSearchedPerUpdate))) { PathNode currentNode = m_nodeHeap.Top(); // Keep track of how many nodes total we have visited so far m_totalNodesSearched++; // Keep track of how many nodes were searched this update nodesSearchedThisUpdate++; // Make sure we haven't hit the destination if (currentNode.NavCellIndex != m_endNavRef.NavCellIndex) { // Remove the current node from the heap now that we're investigating it m_nodeHeap.Pop(); // Add the current nav-cell to the closed set // (since we just visited it and don't want to visit it again) currentNode.MarkAsInClosedSet(); // See which neighbor, if any, looks best at this moment to search from for (NavCellNeighborIterator iterator = new NavCellNeighborIterator(m_navMesh, currentNode.NavCellIndex); iterator.Valid(); iterator.Next()) { // See if we already have a search node for the neighbor nav-cell uint neighborNavCellIndex = iterator.NeighborNavCellIndex; PathNode neighborNode = null; bool hasNeighbor = m_navCellToNodeMap.TryGetValue(neighborNavCellIndex, out neighborNode); // Skip this neighbor if we already put it in the closed set if (!hasNeighbor || !neighborNode.InClosedSet) { // Compute G(x): The path cost from the start to this neighbor float netTraversalCostToNeighbor = currentNode.Cost + ComputeTraversalCost(currentNode.NavCellIndex, neighborNavCellIndex); // Add this neighbor into consideration if: // A) We haven't seen it before (i.e. not in the open set) // B) We have seen it before, but the net traversal cost to the neighbor // from the start through the current node is cheaper than some previous // traversal to the neighbor. if (neighborNode == null || netTraversalCostToNeighbor < neighborNode.Cost) { // Compute F(x)= G(x) + H(x): The past cost to the neighbor plus the estimated distance to the end Point3d neighborCenter = m_navMesh.ComputeNavCellCenter(neighborNavCellIndex); float netTraversalPlusHeuristicCost = netTraversalCostToNeighbor + ComputeHeuristicCostEstimate(neighborCenter, m_endPosition); // Make sure to add the neighbor to the open set if not already added if (neighborNode == null) { neighborNode = new PathNode( (int)m_nextPathNodeID, currentNode, neighborNavCellIndex, netTraversalCostToNeighbor, netTraversalPlusHeuristicCost); m_nextPathNodeID++; m_navCellToNodeMap[neighborNavCellIndex] = neighborNode; } else { neighborNode.ParentNode = currentNode; neighborNode.Cost = netTraversalCostToNeighbor; neighborNode.Total = netTraversalPlusHeuristicCost; } // Add the neighbor into the heap for future consideration m_nodeHeap.Push(neighborNode); } } } } else { // Stop searching and compute the raw path from the search nodes m_state = eState.finalize_raw_path; break; } } // Sanity check to make sure we never get in an infinite loop if (m_nodeHeap.Empty()) { m_resultCode = eResult.failed_raw_path_search; m_state = eState.complete; } else if (m_totalNodesSearched >= MAX_TOTAL_NODES_SEARCHED_ALLOWED) { //Debug.log("PathComputer: Ran out of search node!", Debug.RED); m_resultCode = eResult.failed_raw_path_search; m_state = eState.complete; } }
private void DebugDrawTestPath() { int characterID = _gameWorldController.Model.CurrentCharacterID; RoomKey roomKey = _gameWorldController.Model.CurrentGame.CurrentRoomKey; CharacterEntity entity = _gameWorldController.Model.GetCharacterEntity(characterID); if (entity != null) { Point2d mousePixelPos = GetMousePixelPosition(); Point3d mouseWorldPos = GameConstants.ConvertPixelPositionToRoomPosition(mousePixelPos); // Draw the target nav cell string targetLabel = ""; AsyncRPGSharedLib.Navigation.NavMesh navMesh = PathfindingSystem.GetNavMesh(roomKey); if (navMesh != null) { NavRef navRef = navMesh.ComputeNavRefAtPoint(mouseWorldPos); if (navRef.IsValid) { Point3d centerWorldPos = navMesh.ComputeNavCellCenter((uint)navRef.NavCellIndex); Point2d centerPixelPos = GameConstants.ConvertRoomPositionToPixelPosition(centerWorldPos); float halfWidth = (float)GameConstants.NAV_MESH_PIXEL_SIZE / 2.0f; Vector3 boxUL = ClientGameConstants.ConvertPixelPositionToVertexPosition( centerPixelPos.x - halfWidth, centerPixelPos.y - halfWidth, 0.0f); Vector3 boxUR = ClientGameConstants.ConvertPixelPositionToVertexPosition( centerPixelPos.x + halfWidth, centerPixelPos.y - halfWidth, 0.0f); Vector3 boxLR = ClientGameConstants.ConvertPixelPositionToVertexPosition( centerPixelPos.x + halfWidth, centerPixelPos.y + halfWidth, 0.0f); Vector3 boxLL = ClientGameConstants.ConvertPixelPositionToVertexPosition( centerPixelPos.x - halfWidth, centerPixelPos.y + halfWidth, 0.0f); Debug.DrawLine(boxUL, boxUR, Color.blue); Debug.DrawLine(boxUR, boxLR, Color.blue); Debug.DrawLine(boxLR, boxLL, Color.blue); Debug.DrawLine(boxLL, boxUL, Color.blue); targetLabel = "\nNavCell=" + navRef.NavCellIndex.ToString(); } // Attempt to compute a path from the active player to the mouse _pathComputer.BlockingPathRequest(navMesh, roomKey, entity.Position, mouseWorldPos); // Update the path status label { if (_pathComputer.ResultCode == PathComputer.eResult.success) { _pathStatusLabel.Text = "VALID" + targetLabel; _pathStatusLabel.Color = Color.green; } else { _pathStatusLabel.Text = _pathComputer.ResultCode + targetLabel; _pathStatusLabel.Color = Color.red; } _pathStatusLabel.SetLocalPosition(mousePixelPos.x, mousePixelPos.y); _pathStatusLabel.Visible = true; } // Render the raw path for (int stepIndex = 1; stepIndex < _pathComputer.FinalPath.Count; stepIndex++) { Point3d previousPoint = _pathComputer.FinalPath[stepIndex - 1].StepPoint; Point3d currentPoint = _pathComputer.FinalPath[stepIndex].StepPoint; Vector3 previousPixelPoint = ClientGameConstants.ConvertRoomPositionToVertexPosition(previousPoint); Vector3 currentPixelPoint = ClientGameConstants.ConvertRoomPositionToVertexPosition(currentPoint); Debug.DrawLine(previousPixelPoint, currentPixelPoint, Color.green); } } } }