/// <summary> /// Initializes a new instance of the <see cref="Map"/> class. /// </summary> /// <param name="tileset"> The tileset to create the map from. </param> /// <param name="layer"> The layer to create the map from. </param> public Map(Tileset tileset, MapLayer layer) { this.tilesets = new List<Tileset>(); this.tilesets.Add(tileset); this.mapLayers = new List<MapLayer>(); this.mapLayers.Add(layer); mapWidth = this.mapLayers[0].Width; mapHeight = this.mapLayers[0].Height; this.dataMap = new MapData(this.MapHeight, this.MapWidth); this.dataMap.AddCollision(this.mapLayers, this.tilesets); }
/// <summary> /// Finds the shortest path between the start vector and the goal vector, /// taking into account whether the unit can actually get there or not. /// A* pathfinding. /// </summary> /// <param name="start"> The vector to start the search from. </param> /// <param name="goal"> The vector to end the search at. </param> /// <param name="unit"> The unit that is trying to find the route. </param> /// <param name="dataMap"> The data map. </param> /// <returns> /// A list representing the shortest path. /// </returns> public static List<Vector> FindShortestPathWithinReach(Vector start, Vector goal, Unit unit, MapData dataMap) { // Set stuff up var closedList = new List<Vector>(); var openList = new List<Vector>(); var openListQueue = new PriorityQueue<Vector, int>(); var newStart = start; newStart.CameFrom = null; newStart.GScore = 0; newStart.FScore = newStart.GScore + CostEstimate(newStart, goal); openList.Add(newStart); openListQueue.Enqueue(newStart); if (newStart.Equals(goal)) { return openList; } // While the queue isn't empty ... while (!openListQueue.Empty) { // ... get highest prioritied point var current = openListQueue.Dequeue(); openList.Remove(current); if (current.Equals(goal)) { return RetracePath(current); } closedList.Add(current); // Iterates over nearby points foreach (var neighbor in NeighborNodes(current)) { // If the point has been visited, ignore it if (closedList.Contains(neighbor)) { continue; } // If it hasn't been visited and the unit can reach it, add it // to the list. if (!openList.Contains(neighbor) && dataMap.WithinMapAndCanTraverse(neighbor.X, neighbor.Y, unit) && CostEstimate(unit.Location, neighbor) <= unit.MoveRange) { neighbor.CameFrom = current; neighbor.GScore = current.GScore + 1; neighbor.FScore = newStart.GScore + CostEstimate(neighbor, goal); openList.Add(neighbor); openListQueue.Enqueue(neighbor); } } } return openList; }
/// <summary> /// Initializes a new instance of the <see cref="Map"/> class. /// </summary> /// <param name="tilesets"> The tilesets to create the map from. </param> /// <param name="layers"> The layers to create the map from. </param> public Map(List<Tileset> tilesets, List<MapLayer> layers) { this.tilesets = tilesets; this.mapLayers = layers; mapWidth = this.mapLayers[0].Width; mapHeight = this.mapLayers[0].Height; // Makes sure that all layers are of the same size. for (int i = 1; i < layers.Count; i++) { if (mapWidth != this.mapLayers[i].Width || mapHeight != this.mapLayers[i].Height) { throw new Exception("MapData layer size exception"); } } this.dataMap = new MapData(this.MapHeight, this.MapWidth); this.dataMap.AddCollision(this.mapLayers, this.tilesets); }
/// <summary> /// Finds the areas the unit can move to. /// </summary> /// <param name="unit"> The unit. </param> /// <param name="dataMapData"> The datamap. </param> /// <returns> /// The list of vectors. /// </returns> public static List<Vector> MarkValidMoves(Unit unit, MapData dataMapData) { var startVector = new Vector(unit.Location.X, unit.Location.Y); var validMovesList = new List<Vector>(); var validMoves = new LinkedList<Vector>(); validMovesList.Add(startVector); validMoves.AddFirst(startVector); // While there are places left to check ... while (validMoves.Count > 0) { // ... get the first move var moveNode = validMoves.First.Value; validMoves.RemoveFirst(); // Find further possible moves foreach (var neighborNode in NeighborNodes(moveNode)) { var tempVector = new Vector(neighborNode.X, neighborNode.Y); // If the point has been visited, ignore it if (validMovesList.Contains(tempVector) || !unit.PointWithinMoveRange(tempVector)) { continue; } // If the unit can move there ... if (dataMapData.WithinMapMoveRangeAndCanTraverse(tempVector.X, tempVector.Y, unit)) { // ... add it to the list. validMoves.AddLast(tempVector); validMovesList.Add(tempVector); } } } return validMovesList; }