public static MovementPath AStar(Point start, Point end, Stage stage = null)
        {
            MovementPath newPath = new MovementPath(null);
            if (stage == null)
            {
                stage = Stage.CurrentStage;
            }

            // setup grid with walls
            //MyPathNode[,] grid = new MyPathNode[(int)stage.Width, (int)stage.Height];
            MyPathNode[][] grid = new MyPathNode[(int)stage.Width][];

            for (int x = 0; x < (int)stage.Width; x++)
            {
                grid[x] = new MyPathNode[(int) stage.Height];
                for (int y = 0; y < (int)stage.Height; y++)
                {

                    grid[x][y] = new MyPathNode()
                    {
                        IsWall = stage.GetTileAt(x, y).GetWalkable(),
                        X = x,
                        Y = y,
                    };
                }
            }

            SpatialAStar<MyPathNode, Object> aStar = new SpatialAStar<MyPathNode, Object>(grid);

            LinkedList<MyPathNode> path = aStar.Search(new Point(0, 0),
               new Point(stage.Width - 2, stage.Height - 2), null);
            return null;
        }
        public static MovementPath DirectWithObstacles(Point start, Point end, Rectangle acceptableArea)
        {
            MovementPath returnPath = new MovementPath(null);
            returnPath.AddPoint(start);
            Point currentPoint = start;
            MovementDirection lastMovement = MovementDirection.None;

            int obstacleProbability = 5;
            List<Point> obstacles = new List<Point>();

            //work toward the 'finish'
            while (currentPoint.x != end.x && currentPoint.y != end.y)
            {
                //try to continue in a straight line
                //if(lastMovement != MovementDirection.None && currentPoint.x
            }

            returnPath.AddPoint(end);
            return returnPath;
        }
        public static MovementPath DrunkWalk(Point start, Point end, Rectangle acceptableArea)
        {
            MovementPath newPath = new MovementPath(null);
            newPath.AddPoint(start);
            Point currentPoint = start;
            Point midPoint = end;

            Point point1 = end;
            Point point2 = null;

            for (int deviations = 0; deviations < 7; deviations++)
            {
                point1 = Point.MidPoint(start, point1).Shift(MovementPath.randomDirection(), 3);
                if (acceptableArea.Contains(point1))
                {
                    newPath.AddPoint(point1);
                }

                if (point2 != null)
                {
                    point2 = Point.MidPoint(point2, end).Shift(MovementPath.randomDirection(), 3);
                    if (acceptableArea.Contains(point2))
                    {
                        newPath.AddPoint(point2);
                    }
                }
                else
                {
                    point2 = point1;
                }
            }

            newPath.AddPoint(end);

            return newPath;
        }
        //resolve the shortest path between two given points
        public static MovementPath ResolvePath2(Point start, Point end, Stage stage = null)
        {
            MovementPath newPath = new MovementPath(null);
            if (stage == null)
            {
                stage = Stage.CurrentStage;
            }
            // The last point added
            Point currentPoint = start;

            //need better pathfinding and collision detection later

            // Add the beginning
            newPath.AddPoint(start);

            // List all of the avenues we've explored
            List<PathLeg> pathLegs = new List<PathLeg>();

            // Start from the start and explore the legs
            // March repeatedly through each path, until reaching the exit or a dead end

            //if there's horizontal distance to cover between the points, cover it first
            while(currentPoint.x != end.x)
            {
                // If we can move to the next tile, do so
                if (stage.GetTileAt((int)currentPoint.x + 1, (int)currentPoint.y).GetWalkable())
                {
                    currentPoint = new Point(currentPoint.x + 1, currentPoint.y);
                    newPath.AddPoint(currentPoint);
                }
                // If not, switch to vertical differencing ...
                else
                {

                }
            }

            return newPath;
        }
        //resolve the shortest path between two given points
        public static MovementPath ResolvePath(Point start, Point end, Stage stage = null)
        {
            MovementPath newPath = new MovementPath(null);
            if (stage == null)
            {
                stage = Stage.CurrentStage;
            }
            // The last point added
            Point currentPoint = start;

            // A list of all path legs on the horizontal plane of the map, indexed by map row.
            Dictionary<short, List<PathLeg>> horizontalPathLegs = new Dictionary<short, List<PathLeg>>();
            // A list of all path legs on the vertical plane of the map, indexed by map column.
            Dictionary<short, List<PathLeg>> verticalPathLegs = new Dictionary<short, List<PathLeg>>();
            // Resolve the legs in the map
            MovementPath.resolvePathLegs(stage, false, ref horizontalPathLegs);
            MovementPath.resolvePathLegs(stage, true, ref verticalPathLegs);

            // Prioritize the side with more long paths (horizontal or vertical)

            // Determine which paths to attempt to join together, and calculate the cost of traveling between those paths

            // If the travel cost is significant (exceeds the difference with the next-shortest path), try the next path

            return newPath;
        }
        public static MovementPath Patrol(Point origin, Point destination)
        {
            MovementPath newPath = new MovementPath(null);

            newPath.AddPoint(origin);
            newPath.AddPoint(destination);
            newPath.SetLooping(true);

            return newPath;
        }
        /// <summary>
        /// Randomize a path from start to finish. Assume no obstacles.
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static MovementPath old_DrunkWalk(Point start, Point end, Rectangle acceptableArea)
        {
            MovementPath newPath = new MovementPath(null);
            //the number of steps taken in this direction so far
            int stepsTaken = 0;
            //the maximum number of 'steps' the 'drunk' can take in one direction before stumbling / changing direction
            int maxSteps = 5;
            //the current position of the path
            Point currentPos = start;
            //the next position
            Point nextPos;
            //the last cardinal direction the character has walked
            Direction lastDirection;

            //walk until we get to the end
            while (currentPos != end)
            {
                /*
                //if we have moved previously, and haven't walked so far as to have to stumble
                if (lastDirection != "" && stepsTaken < maxSteps)
                {
                    //throw a weighted random to select if we move on this direction again
                }
                */

                //pick a random direction
                lastDirection = MovementPath.randomDirection();
                //make sure it's a valid (non negative) point
                nextPos = currentPos.Shift(lastDirection);
                if(newPath.Contains(nextPos) == false && acceptableArea.Contains(nextPos))
                {
                    newPath.AddPoint(nextPos);
                    currentPos = nextPos;
                }
                //otherwise, we'll just try again next time!
            }

            return newPath;
        }
Example #8
0
        /// <summary>
        /// Return every single node from the start to the finish, the full path of this movementpath.
        /// </summary>
        /// <returns></returns>
        public MovementPath FullPath()
        {
            MovementPath returnPath = new MovementPath(null);
            int currentPos = 0;
            int totalPoints = this.nodes.Count - 1;
            Point currentPoint = this.nodes[0];
            returnPath.AddPoint(this.nodes[0]);

            Point comparePoint;

            //loop through all of the points
            while (currentPos < totalPoints)
            {
                comparePoint = this.nodes[currentPos + 1];

                //walk towards each point
                while (currentPoint.x != comparePoint.x || currentPoint.y != comparePoint.y)
                {
                    if (currentPoint.x < comparePoint.x)
                    {
                        currentPoint.x = currentPoint.x + 1;
                    }
                    else if (currentPoint.x > comparePoint.x)
                    {
                        currentPoint.x = currentPoint.x - 1;
                    }
                    else if (currentPoint.y < comparePoint.y)
                    {
                        currentPoint.y = currentPoint.y + 1;
                    }
                    else
                    {
                        currentPoint.y = currentPoint.y - 1;
                    }
                    returnPath.AddPoint(currentPoint);
                }
                currentPos++;
            }

            return returnPath;
        }
        private void ThinkAboutWhereToGo()
        {
            // Implement tracking of expected location, and handling of displacement at top of function (here) if not at expected location.

            // If something has slated this entity to move differently, do that instead.
            if (this.alternateMovementProcess != null)
            {
                this.alternateMovementProcess.Invoke(this);
                return;
            }

            // Default to not moving
            body.SetDirection(MovementDirection.None);

            // If we have previously temporarily altered the speed, restore it
            if (oldSpeed != null)
            {
                this.body.SetSpeed(oldSpeed);
                oldSpeed = null;
            }

            // Pick a direction (if any) to move
            // If there is a current movement path, move toward the current node
            if (this.currentPath != null)
            {
                if (this.currentPath.GetNodeCount() == 0)
                {
                    Debug.log("A non null path has 0 nodes for entity " + this.GetBody().GetId() + " (" + this.GetBody().GetName() + ")");
                }

                //the current node that we are targeted at / walking toward
                Point curNode = this.currentPath.GetNode(this.currentNode);
                //Point curNode = this.currentPath.GetNextNode();

                //there are no more nodes, the entity has reached the end of the path
                if (curNode == null)
                {
                    //Script.Eval("console.log('The current node in the current AI path is null for some entity.')");
                    this.currentPath = null;
                    //stop the entity
                    this.body.SetSpeed(new Vector(0, 0));

                    // If we need to do something at the completion of the path, do it.
                    if (this.DestinationArrival != null)
                    {
                        this.DestinationArrival.Invoke(this);
                    }
                }
                else
                {
                    // The difference between the current horizontal position and the target horizontal position
                    double hOffset = body.GetPosition().x - curNode.x;
                    // The difference between the current vertical position and the target vertical position
                    double vOffset = body.GetPosition().y - curNode.y;

                    //I wonder if these should be rounded?
                    //hOffset = Helpah.Round(hOffset);
                    //vOffset = Helpah.Round(vOffset);

                    //if there's more horizontal distance than vertical, we want to go that way
                    if (Math.Abs(hOffset) > Math.Abs(vOffset))
                    {
                        //if we're to the right of the target, move left
                        if (hOffset > 0)
                        {
                            body.SetDirection(MovementDirection.Left);
                        }
                        else
                        {
                            body.SetDirection(MovementDirection.Right);
                        }
                    }
                    else
                    {
                        if (vOffset > 0)
                        {
                            body.SetDirection(MovementDirection.Down);
                        }
                        else
                        {
                            body.SetDirection(MovementDirection.Up);
                        }
                    }

                    //if the horizontal distance is less than or equal to the current speed divided by the acceleration, begin decelerating
                    if (hOffset != 0 && Math.Abs(hOffset) <= body.GetSpeed().X / body.GetAcceleration())
                    {
                        body.SetDirection(MovementDirection.None);

                        //if the body needs to travel a distance less than its normal acceleration
                        if (Math.Abs(hOffset) < body.GetAcceleration())
                        {
                            //this.oldSpeed = body.GetSpeed();
                            //this.oldSpeed.x = 0;
                            body.SetSpeed(new Vector(hOffset, body.GetSpeed().Y));
                        }
                    }

                    //if the vertical distance is less than or equal to the current speed divided by the acceleration, begin decelerating
                    if (vOffset != 0 && Math.Abs(vOffset) <= body.GetSpeed().Y / body.GetAcceleration())
                    {
                        //Debug.log("Setting speed manually (voffset).");
                        body.SetDirection(MovementDirection.None);

                        //if the body needs to travel a distance less than its normal acceleration
                        if (Math.Abs(vOffset) < body.GetAcceleration())
                        {
                            //this.oldSpeed = body.GetSpeed();
                            body.SetSpeed(new Vector(body.GetSpeed().X, vOffset));
                        }
                    }

                    //the entity is at the same position as the node, time to target the next one
                    //if (Helpah.Round(hOffset, 2) == 0 && Helpah.Round(vOffset, 2) == 0)
                    if(hOffset == 0 && vOffset == 0)
                    {
                        body.SetDirection(MovementDirection.None);
                        this.currentNode++;
                    }

                    Debug.Watch("Desired direction:", body.GetDirection().ToString());
                }
            }
        }
 /// <summary>
 /// Set the MovementPath object attached to this ArtificialIntelligence.
 /// </summary>
 /// <param name="newPath">The new path.</param>
 public void SetMovementPath(MovementPath newPath)
 {
     //I don't think that we need ot clone the path, because they can all share one instance, as the path itself doesn't have any dynamic variables
     //this.currentPath = (MovementPath)Helpah.Clone(newPath);
     this.currentPath = newPath;
 }