A* pathfinder (bmx)

Community Forums/Showcase/A* pathfinder (bmx)

Andres(Posted 2008) [#1]
It's actually "Breadth-first pathfinder"

Here's an easy to use pathfinder, made it as portable as possible. Uses only 4 functions. Supports 2D and 3D maps (map's depth).
The pathmap is filled with flags like:
PATH_TOP, PATH_BOTTOM, PATH_LEFT, PATH_RIGHT, PATH_CEIL, PATH_FLOOR, PATH_ALL

As you can see it doesn't support just 1/0 maps, but also can handle walls (hope you understand what i mean :)

The path returned by FindPath() is a string (something like "11444422222222223331123") where 1 - north, 2 - south, 3 - west, 4 - east, 5 - up, 6 - down.

Win32 executable


Function list:
CreatePathmap:TPathmap(width:Long, height:Long, depth:Long = 1)
PathmapSlot(this:TPathmap, flags:Int, x:Long, y:Long, z:Long = 0) ' Used to fill pathmap with information
FindPath:String(this:TPathmap, x1:Long, y1:Long, z1:Long, x2:Long, y2:Long, z2:Long) ' finds the path in a pathmap from position x1, y1, z1 to x2, y2, z2
FreePathmap(this:TPathmap)


Example:
SuperStrict

Graphics(800, 600)
SeedRnd(MilliSecs())

Global map_width:Int = 80
Global map_height:Int = 60

Include "pathfind.bmx"

' Create level
Global map:Int[map_width, map_height]
For Local y:Int = 0 To map_height -1
	For Local x:Int = 0 To map_width - 1
		If Rand(0, 5) < 2 Then map[x, y] = PATH_ALL
	Next
Next

' Create pathmap
Global pathmap:TPathmap = CreatePathmap:TPathmap(map_width, map_height)
Global path:String = ""

' Copy level to pathmap
For Local y:Long = 0 To map_height -1
	For Local x:Long = 0 To map_width - 1
		PathmapSlot(pathmap, map[x, y], x, y)
	Next
Next

While Not KeyHit(KEY_ESCAPE)
	Cls()
	
	' Draw level
	For Local y:Int = 0 To map_height -1
		For Local x:Int = 0 To map_width - 1
			If CheckFlag(map[x, y], PATH_ALL)
				SetColor(255, 0, 0)
			Else
				SetColor(255, 255, 255)
			EndIf
			DrawRect(x * 10, y * 10, 10, 10)
		Next
	Next
	
	' 1 - north, 2 - south, 3 - west, 4 - east, 5 - up, 6 - down
	path = FindPath(pathmap, map_width / 2, map_height / 2, 0, MouseX() / 10.0, MouseY() / 10.0, 0)
	
	' Draw the PATH
	If Len(path) > 0
		SetColor(0, 0, 255)
		Local x:Long = map_width / 2, y:Long = map_height / 2
		For Local i:Int = 1 To Len(path)
			Select Mid(path, i, 1)
				Case "1"
					y :- 1
				Case "2"
					y :+ 1
				Case "3"
					x :- 1
				Case "4"
					x :+ 1
			End Select
			DrawOval(x * 10, y * 10, 10, 10)
		Next
	EndIf
	
	Flip()
Wend

FreePathmap(pathmap)


Engine ("pathfind.bmx"):



Damien Sturdy(Posted 2008) [#2]
Freaking wonderful work :-) Can't test it but thats the simplest bit of code i've seen doing this- ease of use wise!


Ginger Tea(Posted 2008) [#3]
sorry to be a sod here
but is it REALLY an A* pathfinder or just _A_ pathfinder

i even remember casey's list of alternate names for pathfinders calling themselves A*

A nother path finder
A* 's in their eyes path finder
ok i can only remember two
but if its not A* it shouldnt be called A*


Andres(Posted 2008) [#4]
nothing to be sorry about, that's why i added it here to get feedback. I've read articles about different search algorithms and if i'm correct then this is my engine's algo?


Ginger Tea(Posted 2008) [#5]
then as its not A* its kinda like calling a digestive biscuit a hobnob cos thats a biscuit too ;)

maybe its cos A* is well known and becoming a catch all for pathfinding like hoovering with a dyson


Andres(Posted 2008) [#6]
Well, my friend taught me that Breadth-first search algo, but I thought it was A* :(


Ginger Tea(Posted 2008) [#7]
taken from the same link http://en.wikipedia.org/wiki/A%2A_search_algorithm

i have no idea which is truely the best
A* is the most well known that is for sure
is it the best? id be lying if i said i knew either way

all i was doing was sticking me oar in and being a sod about a possible misnaming of it ;)


Andres(Posted 2008) [#8]
We've ran into a problem coz i can't change the topic!


chwaga(Posted 2008) [#9]
awesome, now convert it to b3d and c++


chwaga(Posted 2008) [#10]
(that was not a request)


Naughty Alien(Posted 2008) [#11]
there are good A* libs for B3D already done...as well as few other approaches


Ginger Tea(Posted 2008) [#12]
the only path finding i do is when im ratted trying to make my way home from some random pub or another :p


Tachyon(Posted 2008) [#13]
This is very well done. My small request: add diagonal spaces to the pathfinding algorithm.


Andres(Posted 2008) [#14]
Current and Diagonal space flags wouldn't fit in one byte anymore so the pathmap would be instantly twice the size and FindPath() would return Chr(0)...Chr(17). So i'ts possible that i'll do it :P

I'll add diagonal-space-support parameter to CreatePathmap() and rest of the engine would remain the same, except there are 12 more flags.

[EDIT]

Hmmm, 12 more flags wouldn't fit to even 2 bytes :(

I don't know how exactly bites shiftings works to use it with 3 bytes. There is no 3 byte variable type, so i'd need to poke the 3 ones with 3 different PokeByte()s.

Does the FLAG256 fit into 1 byte?
...
Const FLAG64:Int = $40
Const FLAG128:Int = $80

Const FLAG256:Int = $100
Const FLAG512:Int = $200
...



Pete Rigz(Posted 2008) [#15]
Surely when the monster/entity whatever is following the path then just analyse the next 3 moves and if it goes north east north then make a diagonal move and skip forward 2 places?

I guess it's extra processing versus extra memory and in both cases I doubt it'd be that much extra to worry about.


TaskMaster(Posted 2008) [#16]
You can't really do that. As, the option to go diagonal adds more optimization choices. So, the path will more than likely be even more different.


Pete Rigz(Posted 2008) [#17]
Yeh I guess so, looking at the map above you can see where areas could be cut across diagonally, but it still might be a comprise to stop entities behaving in a slightly less mechanical way.


chwaga(Posted 2008) [#18]
B3D version (translation courteousy of bram)

pathinc.bb:



pathtest.bb:



Andres(Posted 2008) [#19]
nice :)

I'm too busy with other projects to finish the corner code for this pathfind engine :(