-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added GDX port of Slick2D's AStarPathFinder #575
Conversation
Soo, i've been pondering if i want to include this in core. Unless @NathanSweet objects, i'd like to hold out. What's really nice is that this doesn't allocate anything. What's less nice is that it's bound to tilemaps. I have an A* implementation laying around somewhere that's more general, that is, it works on arbitrary graphs (a tilemap is just a specialized graph really). My implementation doesn't use a binary heap though. I'll see if i can dig it up, maybe we can merge the two things. I'll send it via e-mail. |
A generic implementation would be nice. I'd also like to see it done in a small amount of code and optimized. FWIW, here is some code from an old project of mine: |
The current implementation can be changed to work with an arbitrary graph instead of a tiled map. Just the places where x/y are used need to be replaced with graph-navigation through the nodes. The implementation provides the mean of a Context which is passed around while searching. This makes it possible to find different paths for different cases (e.g. flying units). The downside of this is that we have to program against interfaces which is maybe not what @NathanSweet had in mind as optimized code. I did a short brainstorming and came up with what needed to be changed imho (see list below). If this is something you guys want in libgdx I can follow up on this. Maybe it is not required in libgdx at all as there seem to be some libs around, but so far I could not find one with has no memory allocation, is gwt ready and doesn't use Maps. If it is not required you can close this PR as I am happy with the implementation in my current project as it is.
|
Hi guys, pretty interesting stuff. I think this would be a good addition to libgdx, if not in the core, as an extension. The approach hneuer just proposed seems good to me, pretty generic and it'd work with 2D as well as 3D nav graphs. May I make a suggestion? It'd be super cool if the system supported deferred path requests. You could give the pathfinder a time budget per frame and we could time slice the whole process so as to cope with many requests at the same time. I guess we might not want to do that in the basic PathFinder, but why not have a derived class featuring that? I'm happy to do it myself. |
As long as we are making requests, I'd like to see it extensible so |
Using interfaces doesn't stop the internals from being efficient. :) No GC, no maps, binary heap, checkedID, etc. It would be nice to support n-directions (eg hex grids). I haven't looked at the proposal close enough to see if that would work. FWIW I've found it useful to find all possible paths within a given distance/cost. Imagine a board game and you want to show possible moves. |
Second iteration. AStarPathFinder now works on arbitrary graphs, details about the path itself need to be implemented as needed in subclasses. What is required is a NavNode implementation (they are building the graph), a NavPath implementation (this is holding the result of the search) and heuristics. For a tile based map (integer x/y) I added the implementations (package com.badlogic.gdx.utils.pathfinding.tiled). Algorithm specific data is attached to a NavNode (it is no longer part of a NavNode) by the field algoData, so different implementations of the PathFinder interface can use their own data (jump point search could be implemented this way in addition). In the PathFinderTest class there can be found a simple graph implementation for a map holding its tiles bocling information as a boolean array and setting up a graph with up to 4 neighbours for each tile. I think I have respected all your suggestions except two:
Comments are welcome! |
All possible paths would be a way of (ab)using the astar to do a BFS, since the same pathing costs need to be done. |
I think Dijkstra / bfs would be better, since when you are getting all paths you do not need heuristics, right? Should be faster than doing all paths plus heuristics |
That is true. Mostly I want a BFS for free. :) I'm not actually using this in a game right now, so it's not that important. Quick glance at the latest update, looks good. Merge has my vote if @badlogic likes. |
I'm not sure that you can provide a generic AND efficient algorithm for Android. I tried almost all A* algo found on internet and many of them were too slow on an ordinary phone for a dozen of units on a non-tiled map, so I had to create my own implementation (I increased the speed by 100% but it is not as generic as you expect). I think it's better to create different algorithms, each one with a different goal. |
@cortobass, I am not sure what you mean. Do you see any specific problems? |
@hneuer It's not a comment about your code (I don't have enough time to try it, but at first glance it looks fine); I just warn that is difficult (impossible?) to implement an algorithm for Android that is both generic and quick enough for a real use. Any algorithm will have to be carefully tested under this OS because I had a lot of surprises while working on my project. Maybe, instead of trying to create a function that tries to satisfy every need, it is better to create different functions with different algorithms to cover most needs with the best performance. For a map without movement costs (or just two or three different costs), JPS is an excellent algorithm (probably the best). With movement costs, A* is very good. If you don't need heuristics at all (???), there are probably faster choices. |
The PathFinder from this PR is only an interface (as everything else too) and the AStar algo is just a single implementation provided, so other implementations can be used without a problem if one just programs against the interface. |
I would like to argue two points:
I personally only start deviating from my pre-written core techniques when all else fails; and then all bets are off. (bitfields, static misusage, etc) Also if speed is of the essence, the argument could be made that we would need to implement native code. So I'd like to suggest selecting a datastructure (or abstraction thereof / set of) to be used for pathfinding, along with a common query interface and then implementing a suite of core search techniques on top of this. This also allows for higher-level optimization:
@cortobass |
@methius I completely agree with you. |
@methius having a GDX extension with common data structures and algorithms on top of that sounds like a great idea. After all I did this A* port because GDX was missing it and I did not have something pre-written as I am currently in my first game project :-) As it is my first game I am afraid I can't bring in too much knowledge about such an extension and what is required to make it generally useful. |
@badlogic did we want to merge this after it was revised? @methius seems to be wanting for a more complex API? Without a PR for that, maybe this PR is just fine. Performance is likely fine for an out of the box solution, native code is not the answer for everything. Also it increases maintenance as it doesn't run on GWT. |
Should I reopen it? |
You could reopen it until @badlogic comments. From his first post it seemed like he might merge it if it were more general, which I believe you have made it. |
FWIW, here is an executable example of my simple but optimized a* stuff: |
OK, this PR is now open for discussion again. :-) |
Hi, I just found this PR and I'm really interested in knowing if deferred pathfinding is still in the works. Also, is there any way to add Pooling so that multiple units can search the graph without running out of memory. For my own game I've implemented a time slice proceedure to spread the pathfinding over several frames. So far I've been able to get 500+ units walking randomly around a 64x64 tiled map at 60fps on my Nexus 7. Unfortunately I screwed something up and now I'm getting out of memory errors. I learning a lot from the code here. I'm hoping to improve my code with the addition of a binary heap, pooling, and a better way to handle deferred pathfinding. |
For the desktop green threads would be great for deferred pathing: |
I'll add a new extension for algos like this. We can then merge those things into that extensions. |
* PathFinder is the main entry point * unit tests available in PathFinderTest * graphical test (PathTester) * graphical shape editing (ShapeEditor2)
I like the idea of creating a new extension intended to provide the most common techniques of the artificial intelligence literature, stuff like automata, behavior trees, steering behaviors, path finding, fuzzy logic, goal-driven behaviors, and so on. |
Ok I've implemented generic state machine and messaging. |
@hneuer |
@hneuer |
@hneuer has been with us since forever :) I should update the CONTRIBUTORS list some day. |
@davebaol sure, I will pack up a new PR for this. |
thank :) |
This is a GDX port of Slick2D's AStarPathFinder which I am currently using. It uses GDX container classes and works without the need of additional memory allocations for a path search.
It may be of use to others too so I moved it into a gdx package and created this PR.