A* Pathfinding With AS3

When I earned my degree as a designer, I never thought I’d end up writing a blog post about AI. However, I took a crack at writing an A* (A-star) pathfinding algorithm about five years ago for the avatar movement system in the first generation of the Lassie Engine (built using Macromedia Director and Lingo). My entire source of reference for that first implementation was The Beginner’s Guide to Pathfinding Algorithms. If you’re interested in pathfinding theory, that article is an absolute gold mine. I won’t even pretend that I could do a better job of explaining the algorithm’s nuts and bolts, so I’ll just stick to what an AS3 implementation looks like.

First, we need a data structure of a grid to run searches across. I’m generally drawn to XML for raw data structures like this since it’s easy to compose and maintain by hand. Here’s a simple XML grid of points:

That XML structure is extremely simple. Each node is given an ID, an X and Y coordinate, and has a comma-separated list of other node ID’s that it connects to.

Next, we move on to the simple geometry structures that we’ll feed into our pathfinder. First is the Node object. While we’ll load our grid data as XML, we’ll want to parse that into typed Objects to give our implementation compile-time validation. So, we’d load our XML and then parse the nodes into this structure:

Now let’s put all that together. Create a new Flash document in the root of your class path and put that “grid.xml” file in with it. Then in frame-1 actions of the root timeline, just add the following:

Those are traces of two separate path searches run across the grid. The first search connected n1 and n5 to one another through their common neighbor of n3. The second search took a dramatically different route from n1 to n6 that branched through n2 and n4. Why? Because it was slightly shorter to run through two connections rather take the single connection through n3.

Like this:

Related

22 comments so far

This is awesome – probably the cleanest pathfinding routine I’ve seen for AS3. Also happens to be the first AS3 pathfinding routine I’ve been able to successfully put into a movie and test.

How would I return the available spaces given a set range of nodes? For instance, I ask your pathfinder for all nodes that are 3 or less nodes away? Instead of finding a path, I just want it to tell me an array of all nodes within the range.

Matt, thanks for the feedback. Glad it was helpful. As for putting in node count restriction, you’d just have to add in some rules in the later part of the algorithm. That would be some very specific logic custom to your program (given that it generally goes against the goals of pathfinding to stop the process before a complete path has been found). I guess I could see the practicality of that feature though in a case like wanting a player to move toward a goal, but limiting their move per turn to X spaces…

If that’s what you have in mind, then I’d suggest adding in some logic to look at the number of nodes stored in each path toward the end of the cycle, and start forking all working paths out to a secondary queue once they reach your node count limit. This will halt the A* algorithm in its typical manner, given that A* runs until all search paths have been exhausted. If you retain your omitted search paths in a secondary queue, then you could run a post process that would compare all of those search paths and yield the path with the shortest length estimate.

I’m pretty much just looking to add a function into the pathfinder that: given node-x, return an array of all nodes within 3 positions from the origin, including the origin itself. I really don’t even need it to show me the best option, or really even find a best path at all. I’ll mess around with holding the path data in a second private array and do some condition to return it instead of the path. Maybe if there is no destination node, it will fork and just spit back all the nodes within the range. This would all go in the Path.as file I imagine. Thoughts?

Bah, I’ve worked on this for the last 15 hours and haven’t come up with the solution. The recursion is just killing me. Can you write a function for me in the Grid.as class called getRadius(origin, radius) that will return all the spaces within range of the origin? The best I’ve been able to do is to return all the origin’s neighbor nodes (which was pretty easy), but I can’t seem to figure out how to loop that to get the neighbors of those neighbors and so on up to x steps out. Thanks a million!

Figured out how to create a radius search and add it to your pathfinder script. If you have any suggestions on ways to improve it I’m all ears, but it works and that’s good enough for me.

Instead of calling findPath(start, end) I added another class function called findRadius(start, distance). It returns an array of all nodes within 5 (or x or whatever) nodes distance from the starting point.

Add the following to the Grid.as:

// RADIUS SEARCH GIVEN A STARTING NODE
// this will expand outward and return connected nodes
// -----------------------------------------------------------------------------------------------------
public function findRadius($startId:String, $radius:Number):Array {
trace("\nCalculating path:");
// arrays for keeping track of the path and distances from the origin
var $workArray:Array = new Array(new Path(0, 0, [$startId]));
var $tempArray:Array = new Array();
var $masterArray:Array = new Array();
// put the point of origin into the results array
$masterArray.push($startId);
// init inner recursive loop counter
var k:int = 0;
// outer loop for the number of steps to take from origin
for (var i:int = 0; i < $radius; i++) {
// reset the contents of the temp array for each step loop
$tempArray = [];
// find the length of the work array (all neighbors of current point)
var $mainLength:int = $workArray.length;
// loop through all connected points
for (var j:int = 0; j < $mainLength; j++) {
// take the current point as the search point to iterate
var $searchPath:Path = $workArray[j] as Path;
// pull the last node element from the path
var $searchNode:Node = getNodeById($searchPath.lastElement);
trace("$searchNode = " + $searchNode.id);
// find all the neighbor nodes from the current node and loop all
k = 0;
while (k < $searchNode.numNeighbors) {
// make this node a path piece to conform to the code rules
var $simplePath:Path = new Path(0, 0, [($searchNode.getNeighbor(k))]);
// if this node isn't in master results array, add it
// run the same check for the temp array into the work array
var checkThis:String = $searchNode.getNeighbor(k);
var isDupe:int = $masterArray.indexOf(checkThis);
if (isDupe == -1) {
$masterArray.push($searchNode.getNeighbor(k));
$tempArray.push($simplePath);
}
// increment the neighbor nodes and recurse
k++;
}
}
// copy the new temp array over the the work array for the next loop
$workArray = $tempArray.concat();
}
// return all the possible path nodes
return $masterArray;
}

although i am still having a bit hard time to make your code work, i will try it again. it will be great if you can provide the source files, zip it, change the extension from ‘.zip’ to ‘.jpg’ and upload it to wordpress.com.

LOL… well, that is always the pickle, isn’t it? For what it’s worth though, you’ve got the hard part done… animating a graphic along a path is –technically– far easier to do, but HOW you do it is entirely dependent on the goals of your game. For a really quick start, I’d suggest using an existing tween engine like TweenLite or Tweener. Both of those engines support queued tweens as I recall, so a dirt simple way to follow the path would just be to loop through the returned nodes and configure a Tween engine call to move the object to each point, then you can just let the tween queue play out. It’s quick and dirty, but it should give some instant gratification!

This code snippet looks promising, but I have some problem with it. I hope someone can help.
I tried to pass two string parameters to the function findPath from two input textfields but it just wouldn’t work. Here’s how I tried it:

Hmmm… dunno, that looks okay, although I can’t guarantee that the “s1” and “s2” vars aren’t being lost during the timeline transition. For what it’s worth, I’ve found the Flash timeline to be notoriously unreliable within AS3 programming… things that used to work reliably in AS2 between timeline frames are now hit-or-miss in AS3. However, that’s also not really a bad thing because you can do so much more with the display architecture within AS3, so the timeline becomes fairly useless for anything save for good old fashion timeline animation.

So, in RE: to your question… just instantiate the grid and run the search in response to the button click on frame-1. Otherwise, I’d start debugging the problem by tracing the values both at the point that they’re set and at the point that they’re fed into the “findPath” method.

Hy, i saw your script and is one of the most accurate and clean. It works, but i have a question. How do i implement it visually? I want do i import the graphics, like buttons or the red line, within this code.

Hey this seems pretty good. I’m not very fluent on pathfinding and A* but I know enough that pathfinding provides a more intelligent AI.

In any case, I notice that these classes basically require everything to follow on the grid. Unfortunately, for what I’m looking to create, I can’t always be “on the grid.”

So to solve this problem, I see the code above that allows adding of nodes without XML. I’m wondering how I can get that to create dynamic nodes?

For example, instead of having everything go based on grid movement I want my objects to be able to move as fast/slow as they want and as freely as they want. This means that their node relative to the static nodes are constantly changing.

How would I go about dynamically changing their node so that it always retains the closest neighbors? If I can solve that aspect, then I can get say enemies to always move towards a player but with a more intelligent AI.

Any ideas on how to solve this? I would be greatly appreciative of any help offered. Thanks again!

It appears your path class is missing something. I can comment out public var nodes:Array; and nodes = null; and the class will still compile.

Apparently you are not setting nodes to anything at any point, which makes that variable useless. It would also explain why jay was having problems. I suggest this be corrected as soon as possible so others do not have the same issues.

Perhaps it would just be best to return _path by use of a function and eliminate that variable altogether.

I was looking for A* in AS3, and your site was one of the first on Google. Nice achievement.

Got one problem, if the node name are not linear (p1, p2, p4, p7), then it crash in the findPath main loop. I need it to be that way as I’m making a game on top of an existing application that have the nodes id named that way.

Try to find a quick solution, but haven’t figure it out yet. Any idea beside a lookup table?

This is by far the most comprehendable explanation of A*pathfinding that I have found. Kudos sir. This has helped me tremendously to move my own project further; but more so to ferment my own understanding of pathfinding which will be useful for all of my future endeavors. Many thanks and God bless!