Skip to content
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

Improved AStar #7823

Closed
supagu opened this issue Feb 16, 2017 · 16 comments
Closed

Improved AStar #7823

supagu opened this issue Feb 16, 2017 · 16 comments

Comments

@supagu
Copy link
Contributor

supagu commented Feb 16, 2017

Hi,

I've improved the usability of the AStar class to be able to handle delegate to calculate distances between nodes.
I found the stock implementation too limited to straight lines where my project is using a custom method to compute distance between nodes, I am actually using splines instead of straight lines, so my changes allow for this by adding a delegate which then calls "compute_cost" on the delegate, or "estimate_cost" for cost estimation.

I've also added support for exhaustive AStar searching, flags and bindings for nodes.

If you just diff the files against the stock astar you will see my changes. I would like to see them merged in if you deem the changes suitable.

astar2.zip

@akien-mga
Copy link
Member

Thanks, but it would be much easier to review your patches if you made a pull request directly from a GitHub fork.

@ghost
Copy link

ghost commented Mar 2, 2017

@supagu What's the use of bindings and flags exactly?

@supagu
Copy link
Contributor Author

supagu commented Mar 2, 2017 via email

@ghost
Copy link

ghost commented Mar 3, 2017

these get sent path to the callback function so they are up to the callback
function what they do.

I'm not sure such having application specific parameters is a good idea in the core. I think you can simply pass a single context object which will contain all implementation specific details rather than hard-coded "binds" and "flags".

@ghost
Copy link

ghost commented Mar 3, 2017

BTW, I just created that PR such that others can see the diff, and I will eventually close it without doing any revisions to it myself.
It probably requires revision so if you're still interested in getting it merged, you should create a new PR.

@supagu
Copy link
Contributor Author

supagu commented Mar 3, 2017 via email

@ghost
Copy link

ghost commented Mar 3, 2017

@supagu Could you maybe post a GDScript snippet to show how this auxiliary data is used? Since A* doesn't make any use of that, I'm not sure if it's necessary at all: only GDScript has, and only GDScript uses that data, right?

@supagu
Copy link
Contributor Author

supagu commented Mar 4, 2017

https://github.com/bit-shift-io/trains-and-things/blob/master/Script/AStarMgr.gd

in _init i set the delegate, so the astar calls:
estimate_cost and compute_cost.

you will see in compute_cost the use of getRouteWeight which will get the length of the spline + any dynamic weighting of the AStar

@bojidar-bg
Copy link
Contributor

bojidar-bg commented Mar 4, 2017

Well, can't we add the following to AStar instead:

virtual float _estimate_cost(Vector3 from, Vector3 to); // or (int from, int to)
virtual float _compute_cost(Vector3 from, Vector3 to); // or (int from, int to)

And then have GDScript users do this:

class MyAStar extends AStar:
  const PORTAL_TRAVERSE_COST = 1
  var portal_a; var portal_b
  func _estimate_cost(a, b):
    var portal_a_distance = a.distance_to(portal_a) + b.distance_to(portal_b)
    var portal_b_distance = a.distance_to(portal_b) + b.distance_to(portal_a)
    return min( a.distance_to(b), min(portal_a_distance, portal_b_distance))
  func _compute_cost(a, b):
    if (a == portal_a and b == portal_b) or (a == portal_b and b == portal_a):
      return PORTAL_TRAVERSE_COST
    else:
      return a.distance_to(b)

var astar
func _ready():
  astar = MyAStar.new()
  add_child(astar)
  astar.portal_a = Vector3(0, 0, 0)
  astar.portal_b = Vector3(100, 100, 0)
  astar.add_point(0, astar.portal_a)
  astar.add_point(1, astar.portal_b)
  astar.connect_points(0, 1)
  # Connect points, set portal, do everything as usual with "astar"

@supagu
Copy link
Contributor Author

supagu commented Mar 4, 2017

Vector is not sufficient. There needs to be some way for the user to map back to the node IDs so I can atleast keep my user data outside of the astar class. Passing vectors back to gdscript is useless.

@bojidar-bg
Copy link
Contributor

Then, we would have

virtual float _estimate_cost(int from, int to);
virtual float _compute_cost(int from, int to);

@ghost
Copy link

ghost commented Mar 4, 2017

I believe @bojidar-bg means working purely with IDs, which seems to be the cleanest way to me too. Since GDScript has the mapping from ID to objects, both compute_cost and estimate_cost callbacks can access any relevant data they need.

@ghost
Copy link

ghost commented Mar 4, 2017

Also, I believe it is possible to remove delegate altogether, provide a default compute_cost and estimate_cost, and let user override these functions by extending the class as @bojidar-bg did?

@supagu
Copy link
Contributor Author

supagu commented Mar 5, 2017

Inheritance sounds better than a delegate if that is possible, that should be better performance wise as well for those who do not need a modified AStar impl.

@bojidar-bg
Copy link
Contributor

.. that should be better performance wise as well ..

Not really, as it would still use Object.call under the hood, though we might do some has_method checking if needed.

@tagcup And yeah, you were totally able to decipher (and repost) what I said above. 😉

@supagu
Copy link
Contributor Author

supagu commented Mar 25, 2017

Please refer to PR #8146 for further info

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants