public bool containsTile(Tile inputTile) { bool containsTileReturn = false; int index = this.AllMoveableTiles.FindIndex(tile => (tile.xPos == inputTile.xPos && tile.yPos == inputTile.yPos)); if (index != -1) containsTileReturn = true; return containsTileReturn; }
public const int baseCost = 1; //the cost of moving to any node. Set to 1 to make this simple for now. #endregion Fields #region Constructors public Node(Tile tile) { nodeTile = tile; }
private static List<Node> getAdjacentNodes(Tile startingTile, Map map, List<Node> closedList, Node destinationNode) { List<Node> adjacentNodes = new List<Node>(); List<Tile> tilesToCheck = new List<Tile>(); Node startingNode = new Node(startingTile); int startingX = startingTile.xPos; int startingY = startingTile.yPos; if (map.coordinatesOnMap(startingX, startingY + 1)) tilesToCheck.Add(map.tiles[startingX, startingY + 1]); if (map.coordinatesOnMap(startingX, startingY - 1)) tilesToCheck.Add(map.tiles[startingX, startingY - 1]); if (map.coordinatesOnMap(startingX + 1, startingY)) tilesToCheck.Add(map.tiles[startingX + 1, startingY]); if (map.coordinatesOnMap(startingX - 1, startingY)) tilesToCheck.Add(map.tiles[startingX - 1, startingY]); foreach (Tile tile in tilesToCheck) { //make sure the tile isnt occupied and isnt in the checked list. if (!tile.isOccupied && !(closedList.FindIndex(node => node.nodeTile == tile) >= 0)) { Node newNode = new Node(tile); newNode.FValue = calculateFValue(newNode, destinationNode); newNode.parentNode = startingNode; adjacentNodes.Add(newNode); } } return adjacentNodes; }
public static List<Tile> shortestPath(Map map, Tile startingTile, Tile destinationTile) { List<Tile> path = new List<Tile>(); List<Node> openNodes = new List<Node>(); List<Node> closedNodes = new List<Node>(); List<Node> adjacentNodes = new List<Node>(); bool reachedDestination = false; //initialize. Set starting tile to be the first open node. Node startingNode = new Node(startingTile); Node destinationNode = new Node(destinationTile); startingNode.FValue = calculateFValue(startingNode, destinationNode); openNodes.Add(startingNode); Node nodeToEval = startingNode; while (openNodes.Count > 0) // while nodeToEval != destinationNode ? { //get adjacent nodes and add them to openNodes adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); openNodes.AddRange(adjacentNodes); openNodes.Remove(nodeToEval); closedNodes.Add(nodeToEval); //remove nodeToEval from open list, add to closed list if (nodeToEval.nodeTile.xPos == destinationNode.nodeTile.xPos && nodeToEval.nodeTile.yPos == destinationNode.nodeTile.yPos) { reachedDestination = true; break; } //Now we find the NEXT node to evaluate //We search for the lowest F value in the whole open list after adding the ajacent nodes above int lowestFValue = openNodes.Min(node => node.FValue); //Now get the node with that lowest value - thats our next node to examine. Node nextNodeToEval = openNodes.Find(node => node.FValue == lowestFValue); nodeToEval = nextNodeToEval; } if (reachedDestination == true) { //done! collect the destination and all parent nodes in a list path.Add(nodeToEval.nodeTile); Node nextParentNode = nodeToEval.parentNode; while (nextParentNode != null) { path.Add(nextParentNode.nodeTile); //find parent node in the closed list Node currentParentNode = closedNodes.Find(node => node.nodeTile.xPos == nextParentNode.nodeTile.xPos && node.nodeTile.yPos == nextParentNode.nodeTile.yPos); nextParentNode = currentParentNode.parentNode; } } // find adjacent available nodes and add nodeToEval to the closed list afterwards. //adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); //openNodes.Remove(nodeToEval); // openNodes.AddRange(adjacentNodes); return path; }
public static List<Tile> getAdjacentUncheckedTiles(Tile StartingTile, Map map, List<Tile> checkedTiles) { List<Tile> AdjacentTiles = new List<Tile>(); List<Tile> TilesToCheck = new List<Tile>(); int startingTileX = StartingTile.xPos; int startingTileY = StartingTile.yPos; //check if the tiles passed in here resolve to null if (map.coordinatesOnMap(startingTileX, startingTileY + 1) ) TilesToCheck.Add(map.tiles[startingTileX, startingTileY + 1]); if (map.coordinatesOnMap(startingTileX, startingTileY - 1)) TilesToCheck.Add(map.tiles[startingTileX, startingTileY - 1]); if (map.coordinatesOnMap(startingTileX + 1, startingTileY)) TilesToCheck.Add(map.tiles[startingTileX + 1, startingTileY]); if (map.coordinatesOnMap(startingTileX - 1, startingTileY)) TilesToCheck.Add(map.tiles[startingTileX - 1, startingTileY]); if (TilesToCheck.Count > 0) { foreach (Tile currentTile in TilesToCheck) { if (!currentTile.Equals(null)) // if the current tile is off the map, ie (1,0), the current tile will be null. { if (!currentTile.isOccupied && !checkedTiles.Contains(currentTile)) { AdjacentTiles.Add(currentTile); } } } } return AdjacentTiles; }
public static List<Tile> shortestPath(Map map, Tile startingTile, Tile destinationTile) { List<Tile> path = new List<Tile>(); List<Node> openNodes = new List<Node>(); List<Node> closedNodes = new List<Node>(); List<Node> adjacentNodes = new List<Node>(); bool reachedDestination = false; //initialize. Set starting tile to be the first open node. Node startingNode = new Node(startingTile); Node destinationNode = new Node(destinationTile); startingNode.FValue = calculateFValue(startingNode, destinationNode); openNodes.Add(startingNode); Node nodeToEval = startingNode; while (openNodes.Count > 0) // while nodeToEval != destinationNode ? { //get adjacent nodes and add them to openNodes adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); openNodes.AddRange(adjacentNodes); openNodes.Remove(nodeToEval); closedNodes.Add(nodeToEval); //remove nodeToEval from open list, add to closed list if (nodeToEval.nodeTile.xPos == destinationNode.nodeTile.xPos && nodeToEval.nodeTile.yPos == destinationNode.nodeTile.yPos) { reachedDestination = true; break; } //Now we find the NEXT node to evaluate //We search for the lowest F value in the whole open list after adding the ajacent nodes above int lowestFValue = openNodes.Min(node => node.FValue); //Now get the node with that lowest value - thats our next node to examine. Node nextNodeToEval = openNodes.Find(node => node.FValue == lowestFValue); //this method will give us boring L-shaped paths if two adjacent nodes have the same F value. //lets try forcing the game to prioritize the one that indicates a change in direction! if((openNodes.FindAll(node => node.FValue == lowestFValue).Count > 1)) { List<Node> potentialNextNodesToEval = openNodes.FindAll(node => node.FValue == lowestFValue); foreach(Node node in potentialNextNodesToEval) { if (nodeToEval.parentNode != null){ if (nodeToEval.parentNode.nodeTile.xPos == nodeToEval.nodeTile.xPos && nodeToEval.nodeTile.xPos != node.nodeTile.xPos) { //change of direction in x, prioritize this node and exit nextNodeToEval = node; break; } else if (nodeToEval.parentNode.nodeTile.yPos == nodeToEval.nodeTile.yPos && nodeToEval.nodeTile.yPos != node.nodeTile.yPos) { //change of direction in y, prioritize this node and exit nextNodeToEval = node; break; } } } } nodeToEval = nextNodeToEval; } if (reachedDestination == true) { //done! collect the destination and all parent nodes in a list path.Add(nodeToEval.nodeTile); Node nextParentNode = nodeToEval.parentNode; while (nextParentNode != null) { path.Add(nextParentNode.nodeTile); //find parent node in the closed list Node currentParentNode = closedNodes.Find(node => node.nodeTile.xPos == nextParentNode.nodeTile.xPos && node.nodeTile.yPos == nextParentNode.nodeTile.yPos); nextParentNode = currentParentNode.parentNode; } } // find adjacent available nodes and add nodeToEval to the closed list afterwards. //adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); //openNodes.Remove(nodeToEval); // openNodes.AddRange(adjacentNodes); return path; }
public static Tile getCursorCurrentTile(Tile tile, Map map, Point cursorPoint, Rectangle tileRect) { //when the cursor is over a tile's rectangle, We need to find the space we're actually selecting. The rectangular sprite just containst the diamond //So the tile you pass in, is not necessarily the tile youre hovering over - it may be the edge, and therefore, in another tile. //We want to keep this general in case we chnge tile/asset sizes later. We can use the symmetry in iso art to our advantage. //Whatever the tile size, the angles will be the same, so the math will scale. //We have to go through each of the 5 possible areas designated by the given area. The center diamond, and the four sorrounding triangles. We'll do the center diamond first //if the point isnt in the center diamond, we can use a quick+dirty method of figuring out which triangle its in, and therefore which tile to return. //first get an array of points that make up the inner diamond Point[] polygon = new Point[4]; polygon[0] = new Point(tileRect.X + Tile.width / 2, tileRect.Y); polygon[1] = new Point(tileRect.X, tileRect.Y + Tile.height / 2); polygon[2] = new Point(tileRect.X + Tile.width / 2, tileRect.Y + Tile.height); polygon[3] = new Point(tileRect.X + Tile.width, tileRect.Y + Tile.height / 2); bool insideDiamond = false; for (int i = 0, j = polygon.Length - 1; i < polygon.Length; j = i++) { if ((polygon[i].Y > cursorPoint.Y) != (polygon[j].Y > cursorPoint.Y) && cursorPoint.X < (polygon[j].X - polygon[i].X) * (cursorPoint.Y - polygon[i].Y) / (polygon[j].Y - polygon[i].Y) + polygon[i].X) { insideDiamond = !insideDiamond; } } if (insideDiamond == true) { return tile; } else { //Ok, point is not in the diamond, so let's see which triangle it's in. Keep in mind that a tile adjacent to the given tile may be off the map. //Lets create bounding rectangles that contain the triangles in the corner, Then test if the point is in those rectangles. Since its not in the center diamond, //a hit here means the point is int the correponding triangle. Rectangle upperLeft = new Rectangle(tileRect.X, tileRect.Y, Tile.width/2, Tile.height/2); Rectangle upperRight = new Rectangle(tileRect.X + Tile.width / 2, tileRect.Y, Tile.width / 2, Tile.height / 2); Rectangle lowerLeft = new Rectangle(tileRect.X, tileRect.Y + Tile.height / 2, Tile.width / 2, Tile.height / 2); Rectangle lowerRight = new Rectangle(tileRect.X + Tile.width / 2, tileRect.Y + Tile.height / 2, Tile.width / 2, Tile.height / 2); if (upperLeft.Contains(cursorPoint)) { if (map.coordinatesOnMap(tile.xPos, tile.yPos - 1)) return map.tiles[tile.xPos, tile.yPos - 1]; } else if (upperRight.Contains(cursorPoint)) { if (map.coordinatesOnMap(tile.xPos + 1, tile.yPos)) return map.tiles[tile.xPos + 1, tile.yPos]; } else if (lowerLeft.Contains(cursorPoint)) { if (map.coordinatesOnMap(tile.xPos - 1, tile.yPos)) return map.tiles[tile.xPos - 1, tile.yPos]; } else { //only one left is bottom right: if (map.coordinatesOnMap(tile.xPos, tile.yPos + 1)) return map.tiles[tile.xPos, tile.yPos + 1]; } } return null; }