Game Maker's Garage Forum

Game Creation => Code Exchange => Topic started by: WarHampster on April 02, 2011, 12:07:16 PM

Title: [SC] Pathfinding Algorithm
Post by: WarHampster on April 02, 2011, 12:07:16 PM
http://www.lastbossworks.com/Files/Pathfinding_distribution.zip

I'm finally following through on my promises to release this! I couldn't just release the pathfinding method; it relies on the rest of my engine. So the source I'm distributing now is a stripped-down version of SC2D, I've included just enough for the pathfinding to run. I'll release the rest sometime, but this is the meat of the engine!

Here's how the engine works:

Tilesets are defined in Open Game and look like this:

Code: [Select]
LET TESTTILES$ = "open block"

Where "open" and "block" are the names of sprites. That tileset will associate the open sprite with 0, and the block sprite with 1.

Tilemaps are defined as a string of numbers that represent tiles and a tileset that associates those numbers with sprites. A tilemap definition looks like this:

Code: [Select]
// define a test tile map
LET row1$ = "111111111111"
LET row2$ = "100000000001"
LET row3$ = "111100100101"
LET row4$ = "100010101001"
LET row5$ = "101000010001"
LET row6$ = "101010000001"
LET row7$ = "101001001001"
LET row8$ = "100100101001"
LET row9$ = "100000010001"
LET row10$ = "111111111111"

// to make a grid out of a tile map just add all the rows into one string
LET grid$ = row1$+row2$+row3$+row4$+row5$+row6$+row7$+row8$+row9$+row10$

// define map properties

LET tileheight = 45
LET tilewidth = 45
LET tilehh = tileheight/2
LET tilewh = tilewidth/2

LET MAP_W = 12
LET MAP_H = 10

// create the tilemap
//               the grid|  the tileset   |  i don't even | x| y|
TILEMAPMAKE grid$,TESTTILES$ , LEN(row1$), 49, 30

Ignore the tilehh and tilewh stuff, I forgot to take that out. The method TILEMAPMAKE takes a grid of tiles, the tileset, the length of a row of tiles (ignore that I don't remember why that's there), and the x and y coordinate of the top left tile on the screen, and displays the tilemap on-screen.

Code: [Select]
Parameters: gridd$,tileset$,rowlen,x,y

Pathfinding is achieved by two methods: BLA and FLOODPATH. BLA is a Bresenham's line algorithm implementation and is used to optimize the pathfinding in case a direct line from the starting to the ending position exists. Floodpath is a full-fledged pathfinding algorithm of my own design.

BLA takes the starting coordinates and the ending coordinates of a line, and attempts to cast a ray from startx, starty, to endx, endy, storing the coordinates of tiles intercepted by the ray in the arrays xlist() and ylist().

Code: [Select]
Parameters: startx, starty, endx, endy

FLOODPATH takes starting coordinates and ending coordinates and attempts to trace a path from startx, endx, to endx, endy, storing the coordinates of tiles in the path in the arrays xpath() and ypath().

Code: [Select]
Parameters: startx, starty, endx, endy

I've included an demonstration of how these methods can be used to move a sprite around a tilemap. The code for the demonstration is all in the Open Card and Mouse Down routines of card 1.

After defining and showing the tilemap, I define and create the player. The player is assigned the lowest open sprite number, x and y coordinates, and a move speed.

I ensure that the tile map is fully loaded, set a path iterator variable to store the player's location in his current path, and then start the main loop. Every iteration of the timer, I check to see if the player is at the end of his path. If he is not, I de-increment the path iterator and move the player to the next step on his path.

Whenever the player clicks the mouse, I find what tile the mouse is on. If the player has clicked an open tile, I check if a direct line exists from the player to the clicked tile - if so, I append the locations in that line to the path arrays and return. If not, I call the pathfinding algorithm to create a path from the player to the clicked location.

The pathfinding algorithm is really complicated, but I've commented it heavily. Rather than trying to turn the comments into a coherent explanation to put up here I'll let you guys read the source and ask me questions.  
Title: Re: [SC] Pathfinding Algorithm
Post by: Gan on April 02, 2011, 03:42:40 PM
This is really neat. Sometimes I notice the character taking a rather unusual path to get to the point clicked but so far he still gets there.

Would it be possible to block the character from cutting diagonally across two blocks?
Title: Re: [SC] Pathfinding Algorithm
Post by: WarHampster on April 02, 2011, 04:01:23 PM
Yeah the paths aren't always the shortest, but they're always (as far as I've tested) correct.

And yeah, the directions that the pathfinder can check are defined in the beginning of FLOODPATH:

Code: [Select]
// these arrays store the directions in which the path finding algorithim checks for tile neighbors
// so theoretically for different AIs I can just change what directions are in here or add totally different stuff

// note - cutting out diagonal directions works. can use for different AI

DIM xdirection(8)
DIM ydirection(8)

// 1 = x+1, y+1
LET xdirection(1) = 1
LET ydirection(1) = 1
// 2 = x-1, y-1
LET xdirection(2) = -1
LET ydirection(2) = -1
// 3 = x+1, y-1
LET xdirection(3) = 1
LET ydirection(3) = -1
// 4 = x-1,y+1
LET xdirection(4) = -1
LET ydirection(4) = 1

// 5 = x+1, y
LET xdirection(5) = 1
// 6 = x-1,y
LET xdirection(6) = -1
// 7 = x, y+1
LET ydirection(7) = 1
// 8 = x, y-1
LET ydirection(8) = -1

So to make diagonals illegal you would just cut out the first four additions to the arrays and have

Code: [Select]
// 1 = x+1, y 
LET xdirection(1) = 1
// 2 = x-1,y
LET xdirection(2) = -1
// 3 = x, y+1
LET ydirection(3) = 1
// 4 = x, y-1
LET ydirection(4) = -1
Title: Re: [SC] Pathfinding Algorithm
Post by: Gan on April 02, 2011, 04:10:01 PM
I did that but sometimes when the character is close to a diagonal of two blocks, he'll cut through.
Otherwise when going long routes he doesn't cut through but sometimes it'll take 30 sec to route the path and start moving.
Title: Re: [SC] Pathfinding Algorithm
Post by: WarHampster on April 02, 2011, 04:19:41 PM
Ohhh I know why, it's because when there's an unblocked line between the player and the destination it just uses a line drawing algorithm. So you would just have to change the Mouse Down code to always use FLOODPATH.

I'm playing with it right now and I haven't experienced a noticeable processing time... can you post the code you're using or make a video?
Title: Re: [SC] Pathfinding Algorithm
Post by: Gan on April 02, 2011, 04:56:30 PM
Hey that worked like a charm! No more diagonal cutting. :)

Though unfortunately there are some slow downs some times. The largest slow down is at the end.
http://www.youtube.com/watch?v=E4LDAxD0_bg

Edit: Nearly a minute of processing for the last path.
Title: Re: [SC] Pathfinding Algorithm
Post by: x on April 02, 2011, 06:40:20 PM
http://en.wikipedia.org/wiki/A*_search_algorithm
Title: Re: [SC] Pathfinding Algorithm
Post by: WarHampster on April 02, 2011, 07:41:53 PM
Shut up, x. I suppose if Telstar posted an operating system that he developed you'd post a link to OSX's page.

Gan, that's kind of disturbing, because I'm running the exact same code as you with no slow downs at all. Case in point: http://www.screencast.com/users/WarHampster/folders/Jing/media/0dc0209a-a419-4206-9e68-6c07084282ab

Did Hacksilver run really slowly for you?

Title: Re: [SC] Pathfinding Algorithm
Post by: Gan on April 02, 2011, 07:46:18 PM
Quote
Shut up, x. I suppose if Telstar posted an operating system that he developed you'd post a link to OSX's page.
Hahahah.

HackSilver seemed to run perfectly fine for me. Hm. I'll try compiling to see if it runs any differently.
Title: Re: [SC] Pathfinding Algorithm
Post by: x on April 02, 2011, 08:19:24 PM
Quote
Shut up, x. I suppose if Telstar posted an operating system that he developed you'd post a link to OSX's page.

Gan, that's kind of disturbing, because I'm running the exact same code as you with no slow downs at all. Case in point: http://www.screencast.com/users/WarHampster/folders/Jing/media/0dc0209a-a419-4206-9e68-6c07084282ab

Did Hacksilver run really slowly for you?

Thats a pretty flawed analogy. OSX isn't open source, Telstar wouldn't be able to read the algorithms and learn from them, I would probably link him to a simple Linux distro :P. You were having problems with speed (although I don't see why), I posted what might be another way of doing things - or something to learn from -, I really don't see what there is to be upset about. If you don't want criticism, say so, but you might be short changing yourself.
Title: Re: [SC] Pathfinding Algorithm
Post by: WarHampster on April 02, 2011, 10:03:54 PM
There's a difference between giving constructive criticism and just posting a link, which comes off as demeaning.
Title: Re: [SC] Pathfinding Algorithm
Post by: Gan on April 02, 2011, 10:54:00 PM
I've done a compiled test. Still has slow downs. Which makes me wonder. I'm using the latest beta version of Sc. Could that be the cause?
Title: Re: [SC] Pathfinding Algorithm
Post by: x on April 03, 2011, 04:12:19 AM
Quote
There's a difference between giving constructive criticism and just posting a link, which comes off as demeaning.

You are making a big deal out of nothing. If you have a problem with how something is presented thats purely subjective. Also you do realize that A* isn't a proprietary product, its merely a concept, like the quicksort alogirthm, or a binary search. There are millions of explanations of it, and implementations in pretty much every language. Theres even pseudocode on the wikipedia page, how is posting it NOT helpful for the development of your path finding algorithm(s)?

Here let me try the exact same thing in a way you might not get so petulant over:

You might want to check this out, it could be useful -> http://www.policyalmanac.org/games/aStarTutorial.htm

Better?

Anyways,
I would like to see the performance on a really big map, so far this runs perfectly fine for me using the non-beta version of SC. Which is impressive as SC is a scripted and not a compiled language. AI path-finding is an extremely complex area.
Title: Re: [SC] Pathfinding Algorithm
Post by: WarHampster on April 03, 2011, 11:32:01 AM
Quote
I've done a compiled test. Still has slow downs. Which makes me wonder. I'm using the latest beta version of Sc. Could that be the cause?
Quote
so far this runs perfectly fine for me using the non-beta version of SC.

Sounds like that must be the problem Gan. Did you test with a different version?

And come on x, just because this is the internet does not mean that common courtesy doesn't apply. Your second link achieved the same thing but didn't make me feel like you were blowing me off.

And before I settled with my current solution I tried to implement A*, using the very tutorial you just posted no less! After a few attempts I got frustrated, and because I was operating under a time limit to finish Hacksilver decided to work off of a less efficient but easier to understand algorithm - flood fill, which is explained here: http://www.gamasutra.com/blogs/AdamSaltsman/20090430/1287/A_for_Artists.php

Confusingly that tutorial calls the algorithm A* which is inaccurate.
Title: Re: [SC] Pathfinding Algorithm
Post by: x on April 03, 2011, 06:55:52 PM
It probably calls it A*, because its based on A*, at least it looks like it too me. Using something you can understand and modify is always a better practice than just copying and pasting a chunk of confusing code, I agree with that completely. I have made enough mistakes along those lines myself :P
Title: Re: [SC] Pathfinding Algorithm
Post by: EqwanoX on April 10, 2011, 08:59:32 AM
i really want to understand this but im haveing a hard time, could you make a quick screencast explaining the key things i need to know like what values do i need to keep track of

how and where is the flood path stored??

i cant condomplate how it processes every path as it branches
Title: Re: [SC] Pathfinding Algorithm
Post by: Charlo on April 10, 2011, 11:35:46 AM
Quote
condomplate
uh...
Title: Re: [SC] Pathfinding Algorithm
Post by: Connors on April 10, 2011, 12:19:53 PM
Fruedian typo! ;D
Title: Re: [SC] Pathfinding Algorithm
Post by: EqwanoX on April 11, 2011, 10:41:13 AM
i finally figured it out, this was so hard, i almost went insane. i was able to cut down the coding some, its mostly in one method
updated v2.2: http://cl.ly/0D053o1b0Y1C3q2h1K0D

thanks to warhampster for doing this, i dont know how he did this from scratch!
Title: Re: [SC] Pathfinding Algorithm
Post by: WarHampster on April 11, 2011, 01:18:49 PM
Hey sorry I didn't help you out with that, yesterday was my birthday and I haven't been online all weekend. Really really good job on the rewrite, my code was a huge mess and relied on ancient pieces of my tile engine.
Title: Re: [SC] Pathfinding Algorithm
Post by: Zoo on April 11, 2011, 04:53:26 PM
It's still a little buggy, try going to that one place in the bottom right side as close to the middle as possible. Then, try going to over to the left. The guy just goes one space back, and stops. But that's still an amazing program.
Title: Re: [SC] Pathfinding Algorithm
Post by: EqwanoX on April 12, 2011, 08:52:11 AM
whoops, fixed. the FOR loop for step goes from 1 to 30 and the path is 33 steps, i changed it to 40, but i should just make it 100 sinse it exits the loop anyway, just a note in case someone uses a larger map, they may have to increase that later
Title: Re: [SC] Pathfinding Algorithm
Post by: x on April 12, 2011, 06:42:10 PM
What order of complexity is this algorithm. Is it viable for big maps?
Title: Re: [SC] Pathfinding Algorithm
Post by: Gan on April 12, 2011, 07:23:22 PM
:O This is fantastic! There's no lag of any kind, super fast. Whatever you did, it's amazing!

Edit: Even though it's very fast, I found a few bugs.
Here's the buggy source:
Sc Pathfinding Source with Buggy Map (http://cl.ly/0323000L3l422L2T262P)
Video of Bugs in Action! (http://www.youtube.com/watch?v=K1KYsSYb4Sw)
Title: Re: [SC] Pathfinding Algorithm
Post by: EqwanoX on April 12, 2011, 09:12:54 PM
thats the same bug, just change the step FOR loop to 100 instead of 33, its line 19 in the findpath method, it wont make it any slower sinse it exits the FOR loop when it reaches the destination

FOR step=1 to 100

Quote
the FOR loop for step goes from 1 to 30 and the path is 33 steps, i changed it to 40, but i should just make it 100 sinse it exits the loop anyway, just a note in case someone uses a larger map, they may have to increase that later



those building destruction videos are so amusing
Title: Re: [SC] Pathfinding Algorithm
Post by: Gan on April 12, 2011, 09:24:26 PM
That fixed it!  :D Man this is some great stuff. I'm gonna have to use this sometime for something.

Quote
those building destruction videos are so amusing
Why thank yee! I think I'll make a post about them.