Jump to content

AStar.js Pathfinding Bug


Recommended Posts

While using the AStar.js plugin (from the official Phaser plugin repository), I have been running into a strange bug. Whenever I try to find a path between any two points on my map, the findPath function returns a path of zero length every time. Even more odd, the path, regardless of where I set it to begin or end, always has a start point and goal of (32, 47). This point does exist on my map and is the closest walkable tile to the bottom-right of the map, but there appears to be nothing else of significance about it. It is never mentioned in my code; the number 47 does not even exist in any of my files. The path should not cross that point and a quick manual calculation of A* on my map suggests that (32, 47) would not even be considered, since it should find a direct path to the goal fairly quickly.
Does anyone know what might be causing this problem? The only useful tutorial I found online specific to this plugin is the example by Rafarel that is currently a pull request for the Phaser Examples repository. I copied parts of it directly and still had the same bug. If anyone else has a tutorial or example of using this plugin they would like to share, I (and probably quite a few others) would appreciate it, especially if it showed a common use of A* in games, such as pathfinding for multiple characters.
Some relevant code:

this.AStar = this.game.plugins.add(new Phaser.Plugin.AStar(this));
this.AStar.setAStarMap(this.tileMap, 'Tile Layer 1', 'tiles_3_final');this.pathfindKey = this.input.keyboard.addKey(Phaser.Keyboard.ONE);this.pathfindKey.onDown.add(this.pathfindFromCharToChar, this);
pathfindFromCharToChar: function() {	var path = this.AStar.findPath(new Phaser.Point(40, 18), new Phaser.Point(9, 17));	// var path = ast.findPath(this.player.tilePos, this.otherChar.tilePos); // I tried this and several other ways to get points;                                                                                 // I can confirm that the method of passing the points                                                                                  // in is not part of the problem.	this.player.tilePos.x = path.nodes[3].x; // Returns an error, as the path, which should be ~42 nodes long (43 with the start point),                                                 // is only 1 node long.	this.player.tilePos.y = path.nodes[3].y;	this.player.x = tilePos.x*32;	this.player.y = tilePos.y*32;},

EDIT: After some more digging around in the console, I found some information that might be useful. Forgive me if I ramble on a bit, but I figure that I might as well, since anyone who tries to help either has already gone through the exact same issue and can skip it, or would otherwise have to go through this whole process themselves.


The findPath() function is properly passed the correct startPoint (40, 18) and goalPoint (9, 17). However, both start and goal return an AStarNode with an x and y of (32, 47), meaning that something happens in the below segment of code in AStar.js to cause the bug. I can confirm that _tilemap, _layerIndex, goalPoint.y, and goalPoint.x all reference the proper things. Going into properties.astarNode at the correct locations show that the astarNode.x and astarNode,y are set to 32 and 47, respectively.

Phaser.Plugin.AStar.prototype.findPath = function(startPoint, goalPoint){    var path = new Phaser.Plugin.AStar.AStarPath();    var start = this._tilemap.layers[this._layerIndex].data[startPoint.y][startPoint.x].properties.astarNode; //:AStarNode;    var goal = this._tilemap.layers[this._layerIndex].data[goalPoint.y][goalPoint.x].properties.astarNode    path.start = start;    path.goal = goal;    this._open = [];    this._closed = [];    this._visited = [];       this._open.push(start);    ...}

While searching for examples originally, I found this Stack Overflow question about AStar.js. I ignored it at the time, but thankfully remembered now. Of course, it remains unanswered, but it did point out that each AStarNode contains the x and y coordinates of the last location to use the same tile as it. So (0, 0), using tile 5, is marked as being at (49, 49), as is everything else that uses tile 5. Likewise, everything using tile 16 is marked as (32, 47). I hadn't noticed since 16 is the only currently used walkable tile, and I didn't think to try using AStar on a non-walkable tile.  <_<


So the next thing to look at is where the astarNode property is set up on each tile. The updateMap is automatically called when you setup a map for AStar, and can also be manually called after a change to the map. I set up some variables (not shown below) to track whatever the previous tile was so I could check the astarNode property and see if the x and y are changing.

Phaser.Plugin.AStar.prototype.updateMap = function(){    var tile;    var walkable;    //for each tile, add a default AStarNode with x, y and walkable properties according to the tilemap/tileset datas    for(var y=0; y < this._tilemap.height; y++)    {        for(var x=0; x < this._tilemap.width; x++)        {            tile = this._tilemap.layers[this._layerIndex].data[y][x];            walkable = this._tilemap.tilesets[this._tilesetIndex].tileProperties[tile.index - 1][this._walkablePropName] !== "false" ? true : false;            tile.properties.astarNode = new Phaser.Plugin.AStar.AStarNode(x, y, walkable);        }    }};

And apparently, as expected, they are. Going through it line by line, and checking for changes, I can tell that it is line 166 that is changing it. And so the next stop is in the AStarNode constructor, shown below (with comments removed for length).

Phaser.Plugin.AStar.AStarNode = function(x, y, isWalkable){    this.x = x;    this.y = y;    this.g = 0;    this.h = 0;    this.f = 0;    this.parent;     this.walkable = isWalkable;    this.travelCost;};

The console says nothing unexpected happens there (not that I really expected anything to). So I am stuck once again. Somehow, this line of code...

tile.properties.astarNode = new Phaser.Plugin.AStar.AStarNode(x, y, walkable);

...or a related line is causing other tiles to have their properties changed. All I can think of is that somehow an update to Phaser may have broken this plugin, as it doesn't appear to have been updated since 2.0.4 (at least). I read back through about half of Phaser's entire changelog and cannot see anything that obviously would break this plugin.


So that's everything I have found out. Does anyone else who knows more about changes in how Phaser deals with tile properties (or anyone else) know anything that might be causing this problem?

Link to comment
Share on other sites

  • 1 month later...
  • 2 months later...

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...