Exemple #1
0
		/// <summary>
		/// Calculates a path from start to end. When no path can be found in
		/// reasonable time the search is aborted and an incomplete path is returned. 
		/// When refresh is not set to true a cached path is returned where possible.
		/// </summary>
		/// <param name="start">start position in 2d map space</param>
		/// <param name="end">end position in 2d map space</param>
		/// <param name="refresh">force to recalculate the path</param>
		/// <returns></returns>
		public TilePath CalculatePath(Point2D start, Point2D end, bool refresh) {
			// swap points to calculate the path backwards (from end to start)
			Point2D temp = end;
			end = start;
			start = temp;

			// Check whether the requested path is already known
			var request = new TilePathRequest(start, end);
			if (!refresh && mPathCache.ContainsKey(request)) {
				return mPathCache[request].Copy();
			}

			// priority queue of nodes that yet have to be explored sorted in 
			// ascending order by node costs (F)
			var open = new AutoPriorityQueue<TilePathNode>();

			// List of nodes that have already been explored
			var closed = new LinkedList<ITileCell>();

			// Start is to be explored first
			var startNode = new TilePathNode(null, mLayer.GetCell(start), end);
			open.Enqueue(startNode);

			var steps = 0;

			do {
				// Examine the cheapest node among the yet to be explored
				var current = open.Dequeue();

				// Finish?
				if (current.Cell.Matches(end) || ++steps > mStepLimit) {
					// Paths which lead to the requested goal are cached for reuse
					var path = new TilePath(current);

					if (mPathCache.ContainsKey(request)) {
						mPathCache[request] = path.Copy();
					} else {
						mPathCache.Add(request, path.Copy());
					}

					return path;
				}

				// Explore all neighbours of the current cell
				var neighbours = mLayer.GetNeighbourCells(current.Cell);

				foreach (var cell in neighbours) {
					// Discard nodes that are not of interest
					var flag = mCollisionLayer[cell.X, cell.Y];
					if (closed.Contains(cell) || (cell.Matches(end) == false && (flag & ECollisionType.NotMoveable) != ECollisionType.NotMoveable)) {
						continue;
					}

					// Successor is one of current's neighbours
					var successor = new TilePathNode(current, cell, end);
					var contained = open.Find(successor);

					if (contained != null && successor.CostTotal >= contained.CostTotal) {
						// This cell is already in the open list represented by
						// another node that is cheaper
						continue;
					}
					if (contained != null && successor.CostTotal < contained.CostTotal) {
						// This cell is already in the open list but on a more expensive
						// path -> "integrate" the node into the current path
						contained.Predecessor = current;
						contained.Update();
						open.Update(contained);
					} else {
						// The cell is not in the open list and therefore still has to
						// be explored
						open.Enqueue(successor);
					}
				}

				// Add current to the list of the already explored nodes
				closed.AddLast(current.Cell);

			} while (open.Peek() != null);

			return null;
		}
Exemple #2
0
        /// <summary>
        /// Calculates a path from start to end. When no path can be found in
        /// reasonable time the search is aborted and an incomplete path is returned.
        /// When refresh is not set to true a cached path is returned where possible.
        /// </summary>
        /// <param name="start">start position in 2d map space</param>
        /// <param name="end">end position in 2d map space</param>
        /// <param name="refresh">force to recalculate the path</param>
        /// <returns></returns>
        public TilePath CalculatePath(Point2D start, Point2D end, bool refresh)
        {
            // swap points to calculate the path backwards (from end to start)
            Point2D temp = end;

            end   = start;
            start = temp;

            // Check whether the requested path is already known
            var request = new TilePathRequest(start, end);

            if (!refresh && mPathCache.ContainsKey(request))
            {
                return(mPathCache[request].Copy());
            }

            // priority queue of nodes that yet have to be explored sorted in
            // ascending order by node costs (F)
            var open = new AutoPriorityQueue <TilePathNode>();

            // List of nodes that have already been explored
            var closed = new LinkedList <ITileCell>();

            // Start is to be explored first
            var startNode = new TilePathNode(null, mLayer.GetCell(start), end);

            open.Enqueue(startNode);

            var steps = 0;

            do
            {
                // Examine the cheapest node among the yet to be explored
                var current = open.Dequeue();

                // Finish?
                if (current.Cell.Matches(end) || ++steps > mStepLimit)
                {
                    // Paths which lead to the requested goal are cached for reuse
                    var path = new TilePath(current);

                    if (mPathCache.ContainsKey(request))
                    {
                        mPathCache[request] = path.Copy();
                    }
                    else
                    {
                        mPathCache.Add(request, path.Copy());
                    }

                    return(path);
                }

                // Explore all neighbours of the current cell
                var neighbours = mLayer.GetNeighbourCells(current.Cell);

                foreach (var cell in neighbours)
                {
                    // Discard nodes that are not of interest
                    var flag = mCollisionLayer[cell.X, cell.Y];
                    if (closed.Contains(cell) || (cell.Matches(end) == false && (flag & ECollisionType.NotMoveable) != ECollisionType.NotMoveable))
                    {
                        continue;
                    }

                    // Successor is one of current's neighbours
                    var successor = new TilePathNode(current, cell, end);
                    var contained = open.Find(successor);

                    if (contained != null && successor.CostTotal >= contained.CostTotal)
                    {
                        // This cell is already in the open list represented by
                        // another node that is cheaper
                        continue;
                    }
                    if (contained != null && successor.CostTotal < contained.CostTotal)
                    {
                        // This cell is already in the open list but on a more expensive
                        // path -> "integrate" the node into the current path
                        contained.Predecessor = current;
                        contained.Update();
                        open.Update(contained);
                    }
                    else
                    {
                        // The cell is not in the open list and therefore still has to
                        // be explored
                        open.Enqueue(successor);
                    }
                }

                // Add current to the list of the already explored nodes
                closed.AddLast(current.Cell);
            } while (open.Peek() != null);

            return(null);
        }
Exemple #3
0
        public override bool Equals(object obj)
        {
            TilePathRequest other = (TilePathRequest)obj;

            return(Start.Equals(other.Start) && End.Equals(other.End));
        }