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; }
/// <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; }