Example #1
0
        public void SetNeighbors(List <DijkstraNode> nodes)
        {
            Point left = new Point(Position.X - 1, Position.Y);

            if (left.X >= 0)
            {
                int          pos          = left.Y * TileMap.Width + left.X;
                DijkstraNode leftNeighbor = nodes[pos];
                if (leftNeighbor != null)
                {
                    Neighbors.Add(leftNeighbor);
                }
            }

            Point right = new Point(Position.X + 1, Position.Y);

            if (right.X < TileMap.Width)
            {
                int          pos           = right.Y * TileMap.Width + right.X;
                DijkstraNode rightNeighbor = nodes[pos];
                if (rightNeighbor != null)
                {
                    Neighbors.Add(rightNeighbor);
                }
            }

            Point top = new Point(Position.X, Position.Y - 1);

            if (top.Y >= 0)
            {
                int          pos         = top.Y * TileMap.Width + top.X;
                DijkstraNode topNeighbor = nodes[pos];
                if (topNeighbor != null)
                {
                    Neighbors.Add(topNeighbor);
                }
            }


            Point bottom = new Point(Position.X, Position.Y + 1);

            if (bottom.Y < TileMap.Height)
            {
                int          pos            = bottom.Y * TileMap.Width + bottom.X;
                DijkstraNode bottomNeighbor = nodes[pos];
                if (bottomNeighbor != null)
                {
                    Neighbors.Add(bottomNeighbor);
                }
            }
        }
Example #2
0
        //Source : http://en.wikipedia.org/wiki/Pathfinding
        //TODO: Still needs improvement
        //A good way to improve both this algorithm and the a* one, would be to load the Nodes when the map is created,
        //and keep them either in TileMap or in each tile. Or something like that.

        /// <summary>
        /// Find the closest element or the chosen type from the from point.
        /// </summary>
        /// <typeparam name="T">Type of the object we are looking for.</typeparam>
        /// <param name="from">The position we're starting from.</param>
        /// <param name="validate">A lambda operation to validate if the object found is good. If the lamdba operation fails, the algorithm will look for another one. Note : Won't be tested if null.</param>
        /// <returns>Return the closest object found. If none are found, returns null.</returns>
        public static T FindClosest <T>(Point from, Func <T, bool> validate = null, bool includeChilds = false) where T : GameObject
        {
            int nbElements   = TileMap.Width * TileMap.Height;
            int nbSolidItems = 0;

            List <DijkstraNode> nodes = new List <DijkstraNode>();

            for (int i = 0; i < nbElements; i++)
            {
                int x = i % TileMap.Width;
                int y = (int)Math.Floor((double)(i / TileMap.Width));

                nodes.Add(new DijkstraNode()
                {
                    Distance = int.MaxValue,
                    Position = new Point(x, y)
                });

                if (!IsWalkable(new Point(x, y)))
                {
                    nbSolidItems++;
                }
            }

            DijkstraNode start = nodes.FirstOrDefault(x => x.Position == from);

            start.Distance = 0;

            List <DijkstraNode> Q = nodes.ToList();

            //We don't want to check the solid items in the path, but want to keep them
            //because we may be looking for them.
            while (Q.Count - nbSolidItems > 0)
            {
                //TODO : Improve it?
                //DijkstraNode u =
                //     Q.Where(x => IsWalkable(x.Position))   //Get all non-solid items
                //     .MinBy(o => o.Distance);
                //What is better : MinBy or Aggregate?
                //.Aggregate((curmin, x) => (curmin == null || x.Distance < curmin.Distance ? x : curmin));   //Get the one with the smallest value

                DijkstraNode u = Q[0];
                for (int i = 1; i < Q.Count; i++)
                {
                    DijkstraNode n = Q[i];
                    if (IsWalkable(n.Position) && n.Distance < u.Distance)
                    {
                        u = n;
                    }
                }

                Q.Remove(u);

                if (u.Distance == int.MaxValue)
                {
                    break;
                }

                u.SetNeighbors(nodes);

                foreach (DijkstraNode v in u.Neighbors)
                {
                    T obj = TileMap.Tiles[v.Position.X, v.Position.Y].GetFirstObject <T>(includeChilds);
                    if (obj != null)
                    {
                        if (validate == null ||
                            validate.Invoke(obj))
                        {
                            return(obj);
                        }
                    }

                    int alt = u.Distance + 1;
                    if (alt < v.Distance)
                    {
                        v.Distance = alt;
                        v.Previous = u;
                    }
                }
            }

            return(null);
        }