Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / Pathfinding in Tier 1

Author
Message
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 19:23 Edited at: 1st Jun 2012 19:26
Hi

Im trying to make pathfinding for my future projects, but I have a few problems. I think that using A* is the best way to do it, but there are some things that I don't know how I should do.

First of all, storing the path. Im guessing that creating a path once and then storing it is much better than creating a path every time that the unit should move. But that would requier a lot of variables, a few hundred for every unit I create. Or would creating a path every frame be better?

Another problem im having us storage of the "open" and "closed" nodes. From what I understand it's better to store them as separate arrays, but that causes a problem for me since I store my nodes as 2 dimentional arrays (Nodes[X, Y]). How can I store them in the open and closed arrays?
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 1st Jun 2012 19:43
Are you working in Tier1 or Tier2?

Cheers,
Ancient Lady
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 20:06
Tier 1
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 1st Jun 2012 20:11
If you create a node type that has an entity indicating whether the node is opened or closed, might that work?

Something like this:


Cheers,
Ancient Lady
basjak
14
Years of Service
User Offline
Joined: 16th Apr 2010
Location: feel like signing up for mars
Posted: 1st Jun 2012 20:22
I am more with the way that create expandable array

Quote: "global total_nodes as integer

type nodes
node_no as interger
x as float
y as float
endtype

dim node[0] as nodes
.
.
.
end

function create_node_on_path(x#,y#)
inc total_nodes,1
dim node[total_nodes] as nodes
node[total_nodes].node_no = total_nodes
node[total_nodes].x = x#
node[total_nodes].y = y#
endfunction total_nodes"


The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 20:41
Quote: "type nodes
node_no as interger
x as float
y as float
endtype"


The problem with that is that you need to find the nodes that are adjacent to specific nodes

Quote: "TYPE tNode
i_openclose AS integer // 0=closed, 1=opened
<other node stuff>
ENDTYPE

global Nodes[5,5] AS tNode

<stuff to load up nodes>

do
<stuff that affects i_openclose value>
for i=0 to 4 // or 1 to 5, or 0 to 5
for j=0 to 4
if Nodes[i,j].i_openclose = 1
<do node open stuff>
else
<do node close stuff>
endif
next j
next i

<other stuff>
Sync()
loop"


That may work, but you need to look for the open node with the lowest "F" value. Wich is someting that may be hard to do with this.
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 1st Jun 2012 20:58
I was going for pseudo code showing basic type definition and usage, not actually meant to be part of real path finding.

Basic is not really a good language for doing path finding, object avoidance, chasing and all those other behaviors.

Tier2 languages give you much more flexibility with lists and things and dynamic creation.

baxslash (I think) had a good example of code for sort of growing and shrinking arrays which might help you do what you are trying. Marl had some interesting ideas as well.
http://forum.thegamecreators.com/?m=forum_view&t=197321&b=41

Cheers,
Ancient Lady
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 21:08 Edited at: 1st Jun 2012 21:09
Quote: "Basic is not really a good language for doing path finding, object avoidance, chasing and all those other behaviors."


I know, but I don't really feel like learning a new language right now
Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 1st Jun 2012 21:22
You are very brave to take on this task.

I'll be curious to see how it comes out for you.

If you get it working, it is something that a lot of forum members might truly appreciate.

Happy Programming!

Cheers,
Ancient Lady
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 21:41
Quote: "First of all, storing the path. Im guessing that creating a path once and then storing it is much better than creating a path every time that the unit should move. But that would requier a lot of variables, a few hundred for every unit I create. Or would creating a path every frame be better?"


Does anyone have any ideas about this though?

Because I suspect that recalculating the path every frame will cause a fair bit of lag...
Marl
12
Years of Service
User Offline
Joined: 19th Nov 2011
Location: Bradford, UK
Posted: 1st Jun 2012 22:37 Edited at: 1st Jun 2012 22:47
As I recall from the last time I looked at this, the key is to pre-calculate as much as possible the distances between nodes.

For a lot of nodes, that's going to be a problem, so you have to break the task down into smaller bits.

I'm just brainstorming here, so it might not work out too well.

Start with two classes of nodes.

Primary nodes - which have the distances to the other primary nodes
Secondary nodes - which are linked to their nearest primary.

Suppose you want to get from point A to Point B - a common goal. You do a rough path find from Point A's primary to Point B's primary to get a rough route.

You then parse that route to see if any of the nodes on the way offer a shortcut.

A good analogy would be to have Cities as Primary , Towns or Villages as secondary.

The rough route would be the best way from city to city, and the fine tuning would be if you come close to any towns on the way.



Edit: should point out that the lines in the diagram are not the paths themselves, but the data connections between the nodes.

Attachments

Login to view attachments
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 1st Jun 2012 22:42
It all really depends on how your program is going to be. If you are going to have a lot of moving objects that should be avoided you are going to have to call the pathfinder more often. If there are only a few objects moving you could store the path, do some quick proximity checks to see if moving objects are close, if they are check for a new path.

There is also other methods to speed things up if you need to call the pathfinder often with many objects that need to pathfind. You can have 2 A* functions, a Macro A* and Micro A*. The Macro A* searches larger Blocks/Nodes to find the general direction to head in and can search very large maps more quickly. Once you have your Macro A* path you can the call the Micro A* on the first section of the Macro path which will have a smaller search area and be faster. You would store your Macro path and only use the Micro pathfinder each time you move to the next section of the Macro path.

Hope this somewhat helpful.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 22:50
Those are some good ideas, thanks.

I dont think that I will change the enviroment very much so avoiding moving obstacles shouldn't be a problem.

My main consern right now is storage of the path...
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 1st Jun 2012 23:03
What exactly are you having trouble with in storing the path?
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 23:34
Quote: "What exactly are you having trouble with in storing the path?"


Basicaly, if I was to have 20 units, all of them would have to have one array for every unit, I think that may cause some problems, but I will do some test...
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 1st Jun 2012 23:40 Edited at: 1st Jun 2012 23:44
I see. As long as you have a good/efficent pathfinder it really should not matter about how many arrays you have to store the path. One thing that may help is use a multi-dimensional array to store your paths. Something like Paths[20, 100]. Use the first part to store the id of the unit and the 2nd part for the path itself. That way you only need 1 array for your paths.

EDIT: I said that a little wrong, you will not be storing the id in the first part, just as your reference. for instance the player would be referenced at 0 so Path[0, x] would be the path for the player.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 1st Jun 2012 23:41 Edited at: 2nd Jun 2012 00:33
Quote: " Something like Paths[20, 100]. Use the first part to store the id of the unit and the 2nd part for the path itself"


Yes, that was what I thought about doing
Ashambles
11
Years of Service
User Offline
Joined: 9th May 2012
Location: Georgia, USA
Posted: 2nd Jun 2012 00:28
This is my favorite A* tutorial. I've used it to do A* in PHP and Javascript for tiles and hexes. But more to the point, he has a sample implementation in BlitzBasic that you can download towards the bottom of the page. I just gave it a quick read-through and nothing jumped out at me that can't be done in AppGameKit Tier 1, but you may find something in there that won't translate.

I'd definitely solve the path for each moving entity once when they decide to move and then only recalculate if the next step has become blocked in the meantime. You'll need to consider what happens when two or more entities converge, but you can put in place some kind of rule for precedence.

Sorry, I know you're most interested in data structures, but maybe that'll help some.

Twitter: MuseHill
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 2nd Jun 2012 00:35 Edited at: 2nd Jun 2012 00:35
That seems to be a very popular tutorial, and it's the one I have looked the most at. I took a look at the BlitzBasic code, but there was something about the language/IDE that realy anoyed me for some reason.

Thanks for the tip though

Allso this is not a major consern, but is there a more space eficcient way of doing


What this does, is that it does the exact same thing for Node[StartX+1, StartY], Node[StartX-1, StartY], Node[StartX, StartY+1] Node[StartX, StartY-1]. But this way of doing it forces me to write the same code 4 times, and every time that I want to change it, I have to change it 4 times...
Cliff Mellangard 3DEGS
Developer
18
Years of Service
User Offline
Joined: 20th Feb 2006
Location: Sweden
Posted: 2nd Jun 2012 00:41
if you check the codebase so have someone already done 2 various pathfinding codes for tier 1 you could look at.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 2nd Jun 2012 00:51
Hmm, I had no idea about that, I need to look in the codebase more often

I'll have to check that out tomorrow then
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 2nd Jun 2012 02:44
There are some much easier ways of doing it.

One way is to do 2 for loops, one nested in the other and set the range x-1 current position TO x+1 current position...



That method does assume your searching all 8 directions though. The other method is setup a node linkage array at the begining of your program.

The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 2nd Jun 2012 10:12 Edited at: 2nd Jun 2012 17:14
The first way seems a lot better...

I think i'll use that

Edit, I got some good news, and some bad.

First of all. I got basic pathfinding working, it can now find a path between 2 points and avoid obstacles

The problem is that it behaves in a weird way and prioritises the nodes above the current node. This makes it slow down quite a bit, on windows it genrates a path in a 100x100 space in 0.1 seconds, but on android it's way to slow, it takes up to 2.5 seconds to generate the same path
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 2nd Jun 2012 17:36
Seems kind of odd, I don't think you would get that much of a slow down between a computer and android, although it is a rather large area to search. Might be a good use for Macro / Micro method or the method Marl mentioned where you pre-compute your common paths (or both methods combined).

If you would be willing to post the code for your pathfinder, I would not mind taking a look to see if there is anything that could be improved upon and get some extra speed out of it.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 2nd Jun 2012 17:57 Edited at: 2nd Jun 2012 18:08
I attatched the whole project, you will need to remove the line "#Include "../~global/functions.agc" then it should work...

Edit This time I actually included the files

Attachments

Login to view attachments
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 2nd Jun 2012 18:37
From the looks of it, somewhere a H or G value is not being calculated correctly, still looking through it to see exactly how your doing everything.


For now, here is an A* function I wrote for the Snake Competition to control the mouse that you can look at and maybe get some ideas from. (it is a bit messy, sorry).

The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 2nd Jun 2012 19:16
Quote: "From the looks of it, somewhere a H or G value is not being calculated correctly, still looking through it to see exactly how your doing everything."


That's what I thought to, but I can't find anything that isn't done the way I think it should
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 2nd Jun 2012 20:59
One thing I meant to add to my post from last night is to add this...

IF X <> 0 AND Y <> 0 after the for y and for x.

don't want to check the spot you are on. It did not fix the problem, but it is something that should be there.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 2nd Jun 2012 21:29 Edited at: 2nd Jun 2012 21:44
That's realy odd, I added that and it saw the And as an Or, leading to it only checking diagonaly

So I had to use
If X=0 and Y=0
Else
Do stuff
endif
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 2nd Jun 2012 21:48
Yeah that is really odd. I was wondering why it was only going diagonal after I added that. But it works perfectly on this end with that added, Did that make things work for you? I changed a few things, so not sure if those are helping at all.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 2nd Jun 2012 22:54
That did not help at all...

What else did you add?
baxslash
Valued Member
Bronze Codemaster
17
Years of Service
User Offline
Joined: 26th Dec 2006
Location: Duffield
Posted: 3rd Jun 2012 00:09
Looks like I'm late to this party but I did start a dynamic path finding system based on physics in AGK. The idea was you could add obstacles and it would use Dijkstra's algorithm for path finding using a node based system.

It almost works... anyway here's the link (I abandoned the project for the time being): http://forum.thegamecreators.com/?m=forum_view&t=190051&b=41

Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 3rd Jun 2012 04:34 Edited at: 3rd Jun 2012 04:42
Sorry it took so long to respond, I have attached the altered version. I changed a few things with the resolution and the variable names a little to make it easier for me to read. besides those things I changed the way H was calculated.



and did this with the check for the diagonal, I think it might of been getting confused with all those ands / or combinations.



I am pretty sure that is all i did, and should be fairly easy to implement. hope this helps, and again sorry for taking so long to get back to you.

EDIT: Also for some reason it made a new .exe called pathfinder1 in the attachment and was not running that from the IDE, took me a while to figure out why my changes were not having an effect.

Attachments

Login to view attachments
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 3rd Jun 2012 12:17
Quote: "(ABS(GoalX-(X)) + ABS(GoalY-(Y)))*10 )"


It seems that's what made it work.

Thank you so much for the help. And don't worry about not awnsering so quickly. Without your help, I probably wouldn't have figured this out at all
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 3rd Jun 2012 17:53
No problem and glad I could help. Good luck on the rest of your project
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 3rd Jun 2012 22:02
Quote: "Good luck on the rest of your project"


Thank you

Anyway

While the pathfinder works as it should now, it's fairly slow, I aim to make it quick enough to work on an android and keep a steady framerate.

One thing I think would help is remaking the open list an actual list.

As I have it now, when I look for the lowest F value I go thru all nodes like this



While it works, it still has to go thru all the nodes and do these things while it really only has to thru a tenth of them, maybe even less.

The problem im having now though is that I need to find what variable on the open list contains a node, so I can remove it from the list when I close it. I don't realy know of any good way of doing this since my nodes are stored as X and Y in a 2 dimentional array and my open list should only be a 1 dimentional array where the nodes are stored as part of the type.
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 3rd Jun 2012 23:14
First of all are you still syncing in every loop? That will slow things down alot. Sync after the path is complete. Could be getting a slow down from the actual sprite drawing / calculations as well, since you know it works now maybe try removing all the actual drawing functions and just display the time it took. See if there is any difference.

I do a similar way of getting my lowest F Score, only difference really is having a FreeID so it only looks through as high as FreeID. There are other methods of sorting the lists to always have the best, but I have never been able to wrap my head around them, Binary Heaps are one method.

As for storing in a 1 dimensional array, Take a look at the Mouse A* I posted above, I used a 1 dimensonal array for my list and a 2 dimensional array to store the x, y of the FreeID so I knew where in the list to look from a 2 dimensonal array.
Cliff Mellangard 3DEGS
Developer
18
Years of Service
User Offline
Joined: 20th Feb 2006
Location: Sweden
Posted: 3rd Jun 2012 23:55
you could check how this guy solved it?

Iam my self looking at the code and is not satisfied with it and rewritting parts to fit my raycaster.

But the patfinding it self is pretty good.

http://www.thegamecreators.com/?m=codebase_view_shot&i=b496ae7bec039ca2806967d3443fd672

To bad that math is my weak point
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 4th Jun 2012 00:16
The drawi.g functions are not what causes the problem, I do that in the main loop. The I added the "step by step" drawing for debug purposes. The way I meassure the speed of the pathfinder is by starting a timer in the beginning of the function and outputting the time between the start and end. Right now, it takes about 0.3 seconds on to find a path with obstacles on android wich is to slow unless there is a way to calculate the path in the background and keep running the program normaly.
JimHawkins
14
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 4th Jun 2012 09:24
Ideally, these kinds of calculations could be done using threads. That shouldn't be too hard to implement in C++ or Pascal, but would be a fairly big problem to implement in Tier 1.

-- Jim
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 4th Jun 2012 11:04
Is it even possible to use threads in tier 1?
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 4th Jun 2012 17:34
I don't think there is anyway to do threading in Tier 1.

If you want to share your most recent version, I can take a look on my lunch break or later this evening and do some tests on my android tablet. See if I can help figure out where the slow down is. For the most part A* should be very quick even on an android, unless of course there are just a lot of objects to avoid and it has to search a large area to find a path, but in that case it would be slow on a computer as well.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 4th Jun 2012 18:15
Quote: "If you want to share your most recent version, I can take a look on my lunch break or later this evening and do some tests on my android tablet."


I attatched the latest version, thanks for the help

Allso, I have begun working on a system to save the path once one has been found, but I have encountered a pretty weird problem. What I do is that I backtrack the "parentX and Y" from the destination back to the start. This works, but not allways. If the path is straight, it works flawlessly, if the path is "bent" hovever, it only works when the straight part of the path is vertical, if it's horizonatal however, the first time that it goes diagonal, the parent seems to be offset and it dosn't return to the start.

You will see what you mean when you run the program.

Allso I added 3 variables in the top which controlls what will get shown during the calculations

Attachments

Login to view attachments
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 4th Jun 2012 20:03
I see what your talking about, that is really strange. Did not get to look to deeply into it, be able to take a better look this evening. Changed the H calulation in the check for a better path part and did 1 thing which should help with the speed a little.

Added a XStart, YStart, XEnd, and YEnd for the For Loops. Every time you checked a new spot you were doing 24*8 Calculations and for the spots that were being checked again another 20*8 + the original 24*8. This way you only make 4 calculations per a Node Check. It is good practice when doing the same calculation many times to just do it once and store the value, such as CurrentX+X and CurrentY+Y.


The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 4th Jun 2012 21:56
I changed both of those things and it seems to have cut the time it takes to generate a path in half on PC. Sadly, I didn't get that big changes on my android phone

Thank you for the help
bjadams
AGK Backer
16
Years of Service
User Offline
Joined: 29th Mar 2008
Location:
Posted: 5th Jun 2012 00:20
in the last AppGameKit survey there was a question about pathfinding, and if AppGameKit should have this as part of a command set.

However the roadmap does not have much detailed info on what is being worked on.
Cliff Mellangard 3DEGS
Developer
18
Years of Service
User Offline
Joined: 20th Feb 2006
Location: Sweden
Posted: 5th Jun 2012 01:23
Quote: "I changed both of those things and it seems to have cut the time it takes to generate a path in half on PC. Sadly, I didn't get that big changes on my android phone "

Somethings are sadly enough very slow on droid.
I noticed it with my raycaster and cant find the trouble?
100 pc fps is the same as 7-8 on my droid

There seams to be some math that is slow on droid?
Pilz X Schizo
17
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Massachusetts, USA
Posted: 5th Jun 2012 01:24
Not having too much luck with this. Very odd bug and can not track down where the logic is going wrong. Added some debug code and some sleep statments to watch it go step by step. For some reason the ParentY is not getting set correctly. I'll have to take another look at it tomorrow with fresh eyes.
The Zoq2
14
Years of Service
User Offline
Joined: 4th Nov 2009
Location: Linköping, Sweden
Posted: 5th Jun 2012 08:47
Same as me then... Hopefully we will find a solution...
JimHawkins
14
Years of Service
User Offline
Joined: 26th Jul 2009
Location: Hull - UK
Posted: 5th Jun 2012 10:40
Quote: "Somethings are sadly enough very slow on droid."


Apparently, very many Android devices either do not have a floating-point unit (FPU) or disable it to save power. Some devices may be 6%-10% slower using software FP emulation. Division is also a substantially slower operation than + - *.

There's some info on how to find out about the processor here:

http://stackoverflow.com/questions/8161184/detecting-fpu-presence-on-android

Most hardware FPUs are more efficient using double-precision rather than single precision because they are internally 64-bit. AppGameKit uses single-precision. If using C/C++ or Pascal or Java, says, it may be faster to do calculations using doubles and convert to single before passing to an AppGameKit function.

This may seem mad, but 99.9% of programs, and particularly programs on mobile devices, do not use any floating point.

-- Jim

Login to post a reply

Server time is: 2024-05-02 15:33:50
Your offset time is: 2024-05-02 15:33:50