/// <summary> /// Removes the argument PositionedNode from the NodeNetwork. Also destroys any links /// pointing to the argument PositionedNode. /// </summary> /// <param name="nodeToRemove">The PositionedNode to remove from the network.</param> /// <param name="scanAndRemoveOneWayReferences">Scans the entire network and removes all links to this node. Used when not all link relationships are two way.</param> #endregion public virtual void Remove(PositionedNode nodeToRemove, bool scanAndRemoveOneWayReferences) { if (scanAndRemoveOneWayReferences) { foreach (PositionedNode node in mNodes) { if (node.IsLinkedTo(nodeToRemove)) { node.BreakLinkBetween(nodeToRemove); } } mNodes.Remove(nodeToRemove); } else { Remove(nodeToRemove); } }
/// <summary> /// Disconnects all Links between this and the argument node. /// </summary> /// <param name="node">The PositionedNode to break links between.</param> #endregion public void BreakLinkBetween(PositionedNode node) { for (int i = 0; i < node.mLinks.Count; i++) { if (node.mLinks[i].NodeLinkingTo == this) { node.mLinks.RemoveAt(i); break; } } for (int i = 0; i < mLinks.Count; i++) { if (mLinks[i].NodeLinkingTo == node) { mLinks.RemoveAt(i); break; } } }
/// <summary> /// Creates a new, empty TileNodeNetwork matching the arguments. /// </summary> /// <param name="xOrigin">The X position of the left-most nodes. This, along with the ySeed, define the bottom-left of the node network. /// For tile maps this should be the center X of the first tile column (typically TileWidth / 2).</param> /// <param name="yOrigin">The y position of the bottom-most nodes. This, along with xSeed, define the bottom-left of the node network. /// For tile maps this should be the center Y of the bottom tile row. /// If the top-left of the map is at 0,0, then this value would be (-EntireMapHeight + TileHeight/2)</param> /// <param name="gridSpacing">The X and Y distance between each node. That is, the X distance between two adjacent nodes (assumed to be equal to the Y distance). For a tile map this will equal the width of a tile.</param> /// <param name="numberOfXTiles">The number of nodes vertically.</param> /// <param name="numberOfYTiles">The number of nodes horizontally.</param> /// <param name="directionalType">Whether to create a Four-way or Eight-way node network. Eight creates diagonal links, enabling diagonal movement when following the node network.</param> public TileNodeNetwork(float xOrigin, float yOrigin, float gridSpacing, int numberOfXTiles, int numberOfYTiles, DirectionalType directionalType) { mCosts = new float[PropertyIndexSize]; // Maybe expand this to 64 if we ever move to a long bit field? OccupiedCircleRadius = .5f; mTiledNodes = new PositionedNode[numberOfXTiles][]; mNumberOfXTiles = numberOfXTiles; mNumberOfYTiles = numberOfYTiles; mDirectionalType = directionalType; mXSeed = xOrigin; mYSeed = yOrigin; mGridSpacing = gridSpacing; // Do an initial loop to create the arrays so that // linking works properly for (int x = 0; x < numberOfXTiles; x++) { mTiledNodes[x] = new PositionedNode[numberOfYTiles]; } }
/// <summary> /// Creates Links from this to the argument nodeToLinkTo, and another Link from the /// argument nodeToLinkTo back to this. /// </summary> /// <remarks> /// If either this or the argument nodeToLinkTo already contains a link to the other /// PositionedNode, then the cost of the link is set to the argument costTo or costFrom as appropriate. /// </remarks> /// <param name="nodeToLinkTo">The other PositionedNode to create the Links between.</param> /// <param name="costTo">The cost to travel from this to the argument nodeToLinkTo.</param> /// <param name="costFrom">The cost to travel from the nodeToLinkTo back to this.</param> #endregion public void LinkTo(PositionedNode nodeToLinkTo, float costTo, float costFrom) { #if DEBUG if (nodeToLinkTo == this) { throw new ArgumentException("Cannot have a node link to itself"); } #endif bool updated = false; for (int i = 0; i < mLinks.Count; i++) { if (mLinks[i].NodeLinkingTo == nodeToLinkTo) { mLinks[i].Cost = costTo; updated = true; break; } } if (!updated) { mLinks.Add(new Link(nodeToLinkTo, costTo)); } // Now do the same for the other node updated = false; for (int i = 0; i < nodeToLinkTo.mLinks.Count; i++) { if (nodeToLinkTo.mLinks[i].NodeLinkingTo == this) { nodeToLinkTo.mLinks[i].Cost = costFrom; updated = true; break; } } if (!updated) { nodeToLinkTo.mLinks.Add(new Link(this, costFrom)); } }
public float GetVisibleNodeRadius(Camera camera, PositionedNode positionedNode) { return(NodeVisualizationRadius / camera.PixelsPerUnitAt(positionedNode.Z)); }
/// <summary> /// Creates Links from this to the argument nodeToLinkTo, and another Link from the /// argument nodeToLinkTo back to this. /// </summary> /// <remarks> /// If either this or the argument nodeToLinkTo already contains a link to the other /// PositionedNode, then the cost of the link is set to the argument costTo. /// </remarks> /// <param name="nodeToLinkTo">The other PositionedNode to create Links between.</param> /// <param name="costTo">The cost to travel between this and the argument nodeToLinkTo.</param> #endregion public void LinkTo(PositionedNode nodeToLinkTo, float costTo) { LinkTo(nodeToLinkTo, costTo, costTo); }
public void LinkTo(PositionedNode nodeToLinkTo) { float distanceToTravel = (Position - nodeToLinkTo.Position).Length(); LinkTo(nodeToLinkTo, distanceToTravel); }
/// <summary> /// Creates a new Link. /// </summary> /// <param name="nodeLinkingTo">The node to link to.</param> /// <param name="cost">The cost to travel the link.</param> #endregion public Link(PositionedNode nodeLinkingTo, float cost) { mNodeLinkingTo = nodeLinkingTo; mCost = cost; mActive = true; }
public void RemoveAndUnlinkNode(ref Microsoft.Xna.Framework.Vector3 positionToRemoveNodeFrom) { PositionedNode nodeToRemove = GetClosestNodeTo(ref positionToRemoveNodeFrom); Remove(nodeToRemove); }
public PositionedNode GetClosestUnoccupiedNodeTo(ref Microsoft.Xna.Framework.Vector3 targetPosition, ref Microsoft.Xna.Framework.Vector3 startPosition, bool ignoreCorners) { PositionedNode nodeToReturn = null; int xTile, yTile; WorldToIndex(targetPosition.X, targetPosition.Y, out xTile, out yTile); if (IsTileOccupied(xTile, yTile) == false) { nodeToReturn = TiledNodeAt(xTile, yTile); } if (nodeToReturn == null) { int startXTile, startYTile, xTileCheck, yTileCheck, deltaX, deltaY; WorldToIndex(startPosition.X, startPosition.Y, out startXTile, out startYTile); float shortestDistanceSquared = 999; int finalTileX = -1, finalTileY = -1; //Get the "target" Node PositionedNode node = TiledNodeAt(xTile, yTile); PositionedNode startNode = TiledNodeAt(startXTile, startYTile); PositionedNode checkNode; if (node != null && startNode != null) { for (int i = 0; i < node.Links.Count; i++) { //skip any tile I am already on... checkNode = node.Links[i].NodeLinkingTo; if (checkNode == startNode) { continue; } WorldToIndex(checkNode.X, checkNode.Y, out xTileCheck, out yTileCheck); if (IsTileOccupied(xTileCheck, yTileCheck) == false) { deltaX = xTileCheck - xTile; deltaY = yTileCheck - yTile; if (ignoreCorners == false || (ignoreCorners == true && (deltaX == 0 || deltaY == 0))) { float distanceFromStartSquared = ((xTileCheck - startXTile) * (xTileCheck - startXTile)) + ((yTileCheck - startYTile) * (yTileCheck - startYTile)); if (distanceFromStartSquared < shortestDistanceSquared) { shortestDistanceSquared = distanceFromStartSquared; finalTileX = xTileCheck; finalTileY = yTileCheck; } } } } if (finalTileX != -1 && finalTileY != -1) { nodeToReturn = TiledNodeAt(finalTileX, finalTileY); } } } return(nodeToReturn); }
public float GetVisibleNodeRadius(Camera camera, PositionedNode positionedNode) { return(_visibleCoefficient / camera.PixelsPerUnitAt(positionedNode.Z)); }