This is a more advanced alternative to the Game Maker's built-in pathfinding engine.It's perfectly suitable for grid based games with obstacles, or even mazes.

Compatible with GM 6 Registered and GM 7 Pro.

Change List:1.4 - straight and diagonal costs are now saved in variables which can be changed with AStar_setAll - the grid can have an offset - you can now choose one of two coordinate systems and path returning systems - most of the variables now have retrievable default values - the estimate has been rewritten - if the goal node is blocked, the engine doesn't even start searching - more information in the scripts' headers - corrected some lower/upper-case var errors - enlarged the example grid - part is now maze-like, part map-like (with obstacles)1.3 - you can set whether to allow diagonal movement and cutting through obstacles when moving diagonally (AStar_setAll) - changed scripts: AStar_init, AStar_getNeighbors - corrected a bug which caused the blocked direction setting to work only one-way - enhanced the example - added a default maze and two new controls (see Example Controls in the game info)1.2 - corrected the AStar_getCost script - previously, the system didn't return the shortest path in some cases1.1- fixed a bug which caused individual direction blocking not to work at all + some little polishments- the scripts changed are AStar_init, AStar_setBlocked and AStar_setDirBlocked1.0- the initial release

Features:

4- or 8- directional movement

cell blocking (obstacles)

individual direction blocking for each cell

allow/disable cutting through obstacles when moving diagonally

always finds the shortest path

fast and fairly easy to implement

More details are in the examples' game information (viewed in-game by pressing F1).Sorry for the lack of proper documentation and script comments, I may improve it sometime later - but no promises.

Use this freely in your projects and modify it to your liking. Credit is appreciated, but won't be enforced through lawsuits .

This engine was created by Ansgar (Oskar Maxa) with some help from DFortun81.It is based on David Brackeen's "Game Character Path Finding in Java" article, which can be found on the following address:http://www.peachpit....p?p=101142&rl=1.

I guess most people only require the built-in mp grid functions. Personally, this is better for me because it offers more features and can be drawn MUCH faster. (With MP grid, there is no way to access the cell's blocked/unblocked-ness.)

EDIT: Also, the built in are unmodifiable. For yours, I was able to make modified copies of the script and make it do more than just find a path. Pretty useful if you asked me.

It makes no sense to change the direction variable, but you can definitely change image_angle.
If you put the code in the (end) step event along with an "if (path index == ...)" check, it will make the sprite face the direction in which the object is currently moving.
The engine just creates a path which you set to the object by calling path_start - just like with any other path - so you can change anything you want in the process of movement.

Well, it's expected to freeze for a little while, it's made in GML after all.
However, if the speed bugs you too much, there's an AStar DLL made by homebrewpc in the DLL section - I guess it would be faster. It used to be quite buggy, but homebrewpc says he fixed all the problems (I can't confirm that though, I haven't tested it since then). Still, the disadvantage of it is the impossibility to customize the system.

And some GENERAL INFO:
If I have enough time, I'll probably try to make another version of the engine that supports hexagonal grid, and perhaps add some other enhancements. Stay tuned.

The AStar_getCost script was buggy, causing the system not to find the shortest path in some cases. Now it's fixed, along with a little (probably unnoticable) speed gain.Please redownload from the first post.

Oh and by the way, I changed the examples' filenames to AStar_gm6 and AStar_gm7.

Now I can code my AI without having to do their path-finding too ... I tend to give up when I'm trying to do too many things at once :-D

Keep up the good work (even if it is now in "real" programming ;-) )

And btw, I'm a real programmer at work and trust me, GM is far more fun :-D

EDIT: I'm not sure if this is wanted, let alone needed, but I felt I had to:I felt very limited by the hard-coded single path restriction of the engine, so with a few teeny changes I made a version that can use as many as you like:

Basically I just changed all the objPathFinder reference's into pathfinder (as a local variable) and when you create the path it saves the value of the created pathfinder object.(And moved the obstruction create into a 1step alarm because otherwise their create gets called before the second player.

The one small drawback of my version is that all the scripts must be called from the "path owner" instance, as it is no longer "global"

If you want to use this don't even think about crediting me - give it to Ansgar: it's still his engine.

Actually, I've already had a new version of this engine which allows you to choose between using one internal path or always returning the new one. I was just quite busy lately and forgot to upload it.

So now get yourself ready for version 1.4!Download links and the information on what's new are in the first post as usual.

Looking good. My only suggestion is instead of creating a pathfinding instance during init(), adding an option to set the instance which holds the variables and we create it ourselves. This way we can have both local and global systems.

It works well. It always found a path when there was one. It lags a bit when calculating the path (about 2-3 seconds when going across the screen) but that probably can't be helped because of GM. One minor problem is that if I add a wall after it calculates the path then it will go through the wall! This is not good for a game where the player/other enemies are constantly moving, but should be fine in an RTS.

My only suggestion is instead of creating a pathfinding instance during init(), adding an option to set the instance which holds the variables and we create it ourselves. This way we can have both local and global systems.

OK... It'll be in the next version.

One minor problem is that if I add a wall after it calculates the path then it will go through the wall! This is not good for a game where the player/other enemies are constantly moving, but should be fine in an RTS.

Yes, this engine is suitable for finding a stationary path, but it can't adjust it in real-time according to changes on the map.

Well, the motion will be pretty static since you only have a 4/8 -directional movement. (I am thinking bots/A.I-controlled players for e.g. top-down games...)

Is there any possibility that you can let the user have a more free movement (maybe like sliding, sort of) ? (Do not worry about colission, I have a good code for that, might give it to others if they have problems with objects getting stuck ).

There are only 2 different Hex grid orientations that I am aware of, one with vertical movement and diagonal horizontal movement and the other with horizontal movement and diagonal vertical movement.

The most common form of Hex grid indexing is using the same index system a simple square grid with every other row (or column) offset by 50% of the hex width (Or height).

Thanks,Dan

Yeah, but there are some small dilemmas (like whether the odd or the even rows should be offset). I'll consider it.Also I might add support for isometric grids.

Well, the motion will be pretty static since you only have a 4/8 -directional movement. (I am thinking bots/A.I-controlled players for e.g. top-down games...)

Is there any possibility that you can let the user have a more free movement (maybe like sliding, sort of) ? (Do not worry about colission, I have a good code for that, might give it to others if they have problems with objects getting stuck

I could probably do this by checking if there's anything between pairs of nodes in the returned path and smoothing the path accordingly.To make the path smoother in another way (curved instead of angular), you can use the path_set_kind function.

Perfect. I needed something like this for a long time. I started making it, then failed so I just search and I found your scripts.

Thanks again

EDIT:

One really really stupid question:
I know A* is used to find the shortest path from point A to B, but...

The thing is that I need it to do is find the shortest path from point A to the farthest away space available. I thought that I could convert it to do this, but its more confusing than I thought. Any ideas?

The thing is that I need it to do is find the shortest path from point A to the farthest away space available. I thought that I could convert it to do this, but its more confusing than I thought. Any ideas?

If you need to find a path from point A to the node with the greatest distance between it and A;1) Create an array of all the nodes arrDisFromA[nodeID] = abs(Xa - XnodeID) + abs(Ya - YnodeID)2) Find the highest value of arrDisFromA[nodeID]. This is your B3) Use A* pathfinding as normal to find the best path between A and B.

lets says here is the graph:...............................<-- basic equation would pick this spot..................................#########################..................#..............................#...............##########.....#.....##########...............#..............................#..............................#..............................#..............................#....................start.....#...............<-- end point I would like it to figure out

Note: graph would be about 20x harder. This was something really simple that I made for the forum

after it found the farthest position it would find the way through.................................._________________________...../#########################\....\_______.....#............/............\....#.....______/...##########|....#..../##########..........|....#....\_...................|....#......\_.................|....#........\_...............|....#..........\_............/.....#............\_......start.....#..............\

Hi Ansgar! I used your scripts for a role playing game i am making together with a classmate. This role playing game is a project for our school and I need to understand and explain your codes to our artificial intelligence prof. I just would like to know what these lines meant and why are pi, cos, sin are needed in your a* algorithm: d = c * pi / 4;
a1 = a + round(cos(d));
b1 = b - round(sin(d));

I thought it might have something to do with the instance id, but I couldn't find it exactly. It also seems to be having a problem executing the init script. Thanks again, and keep up the good work!

-Ainafuin

Edited by Ainafuin, 20 July 2008 - 04:35 PM.

0

"Last night I was lying in bed, looking at the stars, and I wondered, where did my ceiling go?""Last night, I dreamt I ate a huge marshmallow. When I woke up my pillow was gone.""Consciousness: that annoying time between naps."

"God is dead." - Nietzsche"Nietzsche is dead." - God

"So tell me, are those cookies made with real Girl Scouts?""Whatdoesthebigbaratthebottomofthekeyboarddo?""The greatest trick the devil ever played was convincing the world he did not exist" -Courtesy of MTT

You'll get that error if objPlayer isn't created before objObstacle. The code for creating objPathFinder lies in the objPlayer create event, so if objPlayer isn't created first, objPathFinder won't exist (nor will objPathFinder.CELL_WIDTH, hence the unknown variable error).

Fix: Make the objObstacle object initialize after objPlayer is created. purple_pixie ran into the same problem and suggested adding a timer to objObstacle. Here's what my objObstacle looks like:

Actually, I've already had a new version of this engine which allows you to choose between using one internal path or always returning the new one. I was just quite busy lately and forgot to upload it.

So now get yourself ready for version 1.4!Download links and the information on what's new are in the first post as usual.

So how do you have more then one object following different paths? Could you provide an example (Ex: Left click moves one object, right click moves the other)

Anyone else getting an issue where the obstacles bunch together? I've had no problem changing the grid to 32x32 squares, but this thing refuses to cooperate when I stick it into my own file. Any help would be appreciated. >.>

I tried to implement your version in my game and it actually works nice, with one exception:

If I create the objPartyMember by scripts say that by pressing the "S" button would do this: instance_create(objPartyMember,x,y); If I now create another one in the same way, that objPartyMember adopts the first objPartyMember's path and moves through walls and stuff.Can this be prevented?

NOTE: This does not happen if all of them are created at the same time and then no more are created.