Пример #1
0
        public List <PathCoordinate> CreatePathToCoordinate(EntityBase entityFrom, AbsWorldCoords coordinate, double maxDistance = 24.0)
        {
            PathCoordinate start = GetCoordinateFromCacheOrAdd(entityFrom.BlockPosition);
            PathCoordinate end   = GetCoordinateFromCacheOrAdd(UniversalCoords.FromAbsWorld(coordinate.X - (entityFrom.Width * 0.5), coordinate.Y, coordinate.Z - (entityFrom.Width * 0.5)));
            Size           size  = new Size((int)Math.Floor(entityFrom.Width + 1.0), (int)Math.Floor(entityFrom.Height + 1.0));

            return(GeneratePath(start, end, size, maxDistance));
        }
Пример #2
0
        public List <PathCoordinate> CreatePathToEntity(EntityBase entityFrom, EntityBase entityTo, double maxDistance = 24.0)
        {
            PathCoordinate start = GetCoordinateFromCacheOrAdd(entityFrom.BlockPosition);
            PathCoordinate end   = GetCoordinateFromCacheOrAdd(entityTo.BlockPosition);
            Size           size  = new Size((int)Math.Floor(entityFrom.Width + 1.0), (int)Math.Floor(entityFrom.Height + 1.0));

            return(GeneratePath(start, end, size, maxDistance));
        }
Пример #3
0
        private PathCoordinate GetCoordinateFromCacheOrAdd(UniversalCoords coordinate)
        {
            PathCoordinate result = null;

            if (!_coordinateCache.TryGetValue(coordinate, out result))
            {
                result = new PathCoordinate(coordinate);
                _coordinateCache[coordinate] = result;
            }

            return(result);
        }
Пример #4
0
        /// <summary>
        /// Returns an integer indicating if the
        /// </summary>
        /// <param name="startCoordinate"></param>
        /// <param name="sizeToCheck"></param>
        /// <param name="heightOffset"></param>
        /// <returns></returns>
        private PathCoordinate GetSafeCoordinate(UniversalCoords startCoordinate, Size sizeToCheck, int heightOffset)
        {
            // Given a coordinate, determine if it is safe to move to allowing Y +- 1 and taking into consideration size of space to check

            PathCoordinate result = null;

            if (heightOffset > 0 && CheckOffset(startCoordinate.Offset(0, heightOffset, 0), sizeToCheck) == 1)
            {
                startCoordinate = startCoordinate.Offset(0, heightOffset, 0);
            }

            result = GetCoordinateFromCacheOrAdd(startCoordinate);

            if (result != null)
            {
                // Check down the Y axis for unsafe blocks
                int checkOffsetResult = 0;
                int loopCount         = 0;

                while (startCoordinate.WorldY > 0 && (checkOffsetResult = CheckOffset(startCoordinate.Offset(0, -1, 0), sizeToCheck)) == 1)
                {
                    if (++loopCount >= 4)
                    {
                        return(null);
                    }

                    startCoordinate = startCoordinate.Offset(0, -1, 0);
                    if (startCoordinate.WorldY > 0)
                    {
                        result = GetCoordinateFromCacheOrAdd(startCoordinate);
                    }
                }
                if (checkOffsetResult == -2)
                {
                    return(null); // Lava
                }
            }

            return(result);
        }
Пример #5
0
        /// <summary>
        /// Returns an integer indicating if the
        /// </summary>
        /// <param name="startCoordinate"></param>
        /// <param name="sizeToCheck"></param>
        /// <param name="heightOffset"></param>
        /// <returns></returns>
        private PathCoordinate GetSafeCoordinate(UniversalCoords startCoordinate, Size sizeToCheck, int heightOffset)
        {
            PathCoordinate result = null;

            if (heightOffset > 0 && CheckOffset(startCoordinate.Offset(0, heightOffset, 0), sizeToCheck) == 1)
            {
                startCoordinate = startCoordinate.Offset(0, heightOffset, 0);
            }

            result = GetCoordinateFromCacheOrAdd(startCoordinate);

            if (result != null)
            {
                // Check down the Y axis for unsafe blocks
                int checkOffsetResult = 0;
                int loopCount         = 0;

                while (startCoordinate.WorldY > 0 && (checkOffsetResult = CheckOffset(startCoordinate.Offset(0, -1, 0), sizeToCheck)) == 1)
                {
                    if (++loopCount >= 4)
                    {
                        return(null);
                    }

                    startCoordinate = startCoordinate.Offset(0, -1, 0);
                    if (startCoordinate.WorldY > 0)
                    {
                        result = GetCoordinateFromCacheOrAdd(startCoordinate);
                    }
                }
                if (checkOffsetResult == -2)
                {
                    return(null); // Lava
                }
            }

            return(result);
        }
Пример #6
0
        /// <summary>
        /// Returns "safe" coordinates 1 block (NSEW) from <paramref name="start"/> where they are not the first point, and the distance to end is less than <paramref name="maxDistance"/>
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="size"></param>
        /// <param name="maxDistance"></param>
        /// <returns></returns>
        private PathCoordinate[] GetPathOptions(PathCoordinate start, PathCoordinate end, Size size, double maxDistance)
        {
            int height = 0;

            if (CheckOffset(start.Coordinate.Offset(0, 1, 0), size) == 1)
            {
                height = 1;
            }

            List <PathCoordinate> pathOptions = new List <PathCoordinate>();

            PathCoordinate eastPoint  = GetSafeCoordinate(start.Coordinate.Offset(0, 0, 1), size, height);
            PathCoordinate northPoint = GetSafeCoordinate(start.Coordinate.Offset(-1, 0, 0), size, height);
            PathCoordinate southPoint = GetSafeCoordinate(start.Coordinate.Offset(1, 0, 0), size, height);
            PathCoordinate westPoint  = GetSafeCoordinate(start.Coordinate.Offset(0, 0, -1), size, height);

            if (eastPoint != null && !eastPoint.Checked && eastPoint.DistanceTo(end) < maxDistance)
            {
                pathOptions.Add(eastPoint);
            }

            if (northPoint != null && !northPoint.Checked && northPoint.DistanceTo(end) < maxDistance)
            {
                pathOptions.Add(northPoint);
            }

            if (southPoint != null && !southPoint.Checked && southPoint.DistanceTo(end) < maxDistance)
            {
                pathOptions.Add(southPoint);
            }

            if (westPoint != null && !westPoint.Checked && westPoint.DistanceTo(end) < maxDistance)
            {
                pathOptions.Add(westPoint);
            }

            return(pathOptions.ToArray());
        }
Пример #7
0
        private List <PathCoordinate> GeneratePath(PathCoordinate start, PathCoordinate end, Size size, double maxDistance)
        {
            SortedSet <PathCoordinate> sortedPath = new SortedSet <PathCoordinate>(new PathCoordinateDistanceToTargetComparer());

            List <PathCoordinate> path = new List <PathCoordinate>();

            _firstCoordinate = start;
            _firstCoordinate.DistanceToTarget = _firstCoordinate.DistanceTo(end);

            PathCoordinate currentCoordinate = start;
            int            loopsLeft         = 1000;

            while (currentCoordinate != null && currentCoordinate != end && loopsLeft > 0)
            {
                currentCoordinate.Checked = true;
                loopsLeft--;
                PathCoordinate[] pathOptions = GetPathOptions(currentCoordinate, end, size, maxDistance);

                foreach (var option in pathOptions)
                {
                    double distance     = currentCoordinate.DistanceFromStart + currentCoordinate.DistanceTo(option);
                    bool   existsInPath = sortedPath.Contains(option);

                    if (!existsInPath || distance < option.DistanceFromStart)
                    {
                        option.PreviousCoordinate = currentCoordinate;

                        if (existsInPath)
                        {
                            sortedPath.Remove(option);
                            option.SetDistanceFromStartAndTarget(distance, option.DistanceTo(end));
                            sortedPath.Add(option);
                        }
                        else
                        {
                            option.SetDistanceFromStartAndTarget(distance, option.DistanceTo(end));
                            sortedPath.Add(option);
                        }
                    }
                }
                sortedPath.Remove(currentCoordinate);
                if (sortedPath.Count > 0)
                {
                    currentCoordinate = sortedPath.Min;
                }
                else
                {
                    break;
                }
            }

            if (currentCoordinate == null || currentCoordinate == _firstCoordinate)
            {
                return(null);
            }

            // currentCoordinate is destination so walk up previous coordinates and add to list, then reverse
            List <PathCoordinate> result = new List <PathCoordinate> {
                currentCoordinate
            };

            while (currentCoordinate.PreviousCoordinate != null)
            {
                result.Add(currentCoordinate.PreviousCoordinate);
                currentCoordinate = currentCoordinate.PreviousCoordinate;
            }

            result.Reverse();
            return(result);
        }
Пример #8
0
 public PathCoordinate GetClosest(PathCoordinate pathCoord1, PathCoordinate pathCoord2)
 {
     return((Coordinate.DistanceToSquared(pathCoord1.Coordinate) <= Coordinate.DistanceToSquared(pathCoord2.Coordinate)) ? pathCoord1 : pathCoord2);
 }
Пример #9
0
 /// <summary>
 /// Returns the distance to another path coordinate
 /// </summary>
 /// <param name="pathCoord"></param>
 /// <returns></returns>
 public double DistanceTo(PathCoordinate pathCoord)
 {
     return(Coordinate.DistanceTo(pathCoord.Coordinate));
 }