mirror of
https://github.com/photonstorm/phaser
synced 2024-11-16 09:48:18 +00:00
640 lines
20 KiB
JavaScript
640 lines
20 KiB
JavaScript
|
/**
|
||
|
* The MIT License (MIT)
|
||
|
|
||
|
* Copyright (c) 2014 Raphaël Roux
|
||
|
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
* THE SOFTWARE.
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @author Raphaël Roux
|
||
|
* @copyright 2014 Raphaël Roux
|
||
|
* @license {@link http://opensource.org/licenses/MIT}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* AStar is a phaser pathfinding plugin based on an A* kind of algorythm
|
||
|
* It works with the Phaser.Tilemap
|
||
|
*
|
||
|
* @class Phaser.Plugin.AStar
|
||
|
* @constructor
|
||
|
* @param {Any} parent - The object that owns this plugin, usually Phaser.PluginManager.
|
||
|
*/
|
||
|
Phaser.Plugin.AStar = function (parent)
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* @property {Any} parent - The parent of this plugin. If added to the PluginManager the parent will be set to that, otherwise it will be null.
|
||
|
*/
|
||
|
this.parent = parent;
|
||
|
|
||
|
/**
|
||
|
* @property {Phaser.Tilemap} _tilemap - A reference to the tilemap used to store astar nodes according to the Phaser.Tilemap structure.
|
||
|
*/
|
||
|
this._tilemap;
|
||
|
|
||
|
/**
|
||
|
* @property {number} _layerIndex - The layer index of the tilemap that is used to store astar nodes.
|
||
|
*/
|
||
|
this._layerIndex;
|
||
|
|
||
|
/**
|
||
|
* @property {number} _tilesetIndex - The tileset index of the tileset that handle tiles properties.
|
||
|
*/
|
||
|
this._tilesetIndex;
|
||
|
|
||
|
/**
|
||
|
* @property {array} _open - An array that references nodes to be considered by the search path algorythm.
|
||
|
*/
|
||
|
this._open;
|
||
|
|
||
|
/**
|
||
|
* @property {array} _closed - An array that references nodes not to consider anymore.
|
||
|
*/
|
||
|
this._closed;
|
||
|
|
||
|
/**
|
||
|
* @property {array} _visited - Internal array of visited tiles, use for debug pupose.
|
||
|
*/
|
||
|
this._visited;
|
||
|
|
||
|
/**
|
||
|
* @property {boolean} _useDiagonal - Does the astar algorythm can use tile diagonal?
|
||
|
* @default true
|
||
|
*/
|
||
|
this._useDiagonal = true;
|
||
|
|
||
|
/**
|
||
|
* @property {boolean} _findClosest - Does the findPath algorythm must calculate the closest result if destination is unreachable. If not findPath will return an empty array
|
||
|
* @default true
|
||
|
*/
|
||
|
this._findClosest = true;
|
||
|
|
||
|
/**
|
||
|
* @property {string} _walkablePropName - Wich name have the walkable propertiy in your tileset.
|
||
|
* @default 'walkable'
|
||
|
*/
|
||
|
this._walkablePropName = 'walkable';
|
||
|
|
||
|
/**
|
||
|
* @property {function} _distanceFunction - The function used to calculate distance.
|
||
|
*/
|
||
|
this._distanceFunction = Phaser.Plugin.AStar.DISTANCE_EUCLIDIAN;
|
||
|
|
||
|
/**
|
||
|
* @property {Phaser.Plugin.AStar.AStarPath} _lastPath - The last path calculated by astar.
|
||
|
*/
|
||
|
this._lastPath = null;
|
||
|
|
||
|
/**
|
||
|
* @property {boolean} _debug - Boolean to debug mode, stores visited nodes, and have a cost. Disable in production.
|
||
|
* @default false
|
||
|
*/
|
||
|
this._debug = true;
|
||
|
};
|
||
|
|
||
|
Phaser.Plugin.AStar.prototype = Object.create(Phaser.Plugin.prototype);
|
||
|
Phaser.Plugin.AStar.prototype.constructor = Phaser.Plugin.AStar;
|
||
|
|
||
|
|
||
|
Phaser.Plugin.AStar.VERSION = '0.0.101';
|
||
|
Phaser.Plugin.AStar.COST_ORTHOGONAL = 1;
|
||
|
Phaser.Plugin.AStar.COST_DIAGONAL = Phaser.Plugin.AStar.COST_ORTHOGONAL*Math.sqrt(2);
|
||
|
Phaser.Plugin.AStar.DISTANCE_MANHATTAN = 'distManhattan';
|
||
|
Phaser.Plugin.AStar.DISTANCE_EUCLIDIAN = 'distEuclidian';
|
||
|
|
||
|
/**
|
||
|
* Sets the Phaser.Tilemap used to searchPath into.
|
||
|
* @method Phaser.Plugin.AStar#setAStarMap
|
||
|
* @public
|
||
|
* @param {Phaser.Tilemap} map - the Phaser.Tilemap used to searchPath into. It must have a tileset with tile porperties to know if tiles are walkable or not.
|
||
|
* @param {string} layerName - The name of the layer that handle tiles.
|
||
|
* @param {string} tilesetName - The name of the tileset that have walkable properties.
|
||
|
* @return {Phaser.Plugin.AStar} The Phaser.Plugin.AStar itself.
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.prototype.setAStarMap = function(map, layerName, tilesetName)
|
||
|
{
|
||
|
this._tilemap = map;
|
||
|
this._layerIndex = this._tilemap.getLayerIndex(layerName);;
|
||
|
this._tilesetIndex = this._tilemap.getTilesetIndex(tilesetName);
|
||
|
|
||
|
this.updateMap();
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Sets the Phaser.Tilemap used to searchPath into.
|
||
|
* @method Phaser.Plugin.AStar-setAStarMap
|
||
|
* @private
|
||
|
* @return {void} The Phaser.Plugin.AStar itself.
|
||
|
*/
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Find a path between to tiles coordinates
|
||
|
* @method Phaser.Plugin.AStar#findPath
|
||
|
* @public
|
||
|
* @param {Phaser.Point} startPoint - The start point x, y in tiles coordinates to search a path.
|
||
|
* @param {Phaser.Point} goalPoint - The goal point x, y in tiles coordinates that you trying to reach.
|
||
|
* @return {Phaser.Plugin.AStar.AStarPath} The Phaser.Plugin.AStar.AStarPath that results
|
||
|
*/
|
||
|
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);
|
||
|
|
||
|
start.g = 0;
|
||
|
start.h = this[this._distanceFunction](start, goal);
|
||
|
start.f = start.h;
|
||
|
start.parent = null;
|
||
|
|
||
|
//Loop until there are no more nodes to search
|
||
|
while(this._open.length > 0)
|
||
|
{
|
||
|
//Find lowest f in this._open
|
||
|
var f = Infinity;
|
||
|
var x;
|
||
|
for (var i=0; i<this._open.length; i++)
|
||
|
{
|
||
|
if (this._open[i].f < f)
|
||
|
{
|
||
|
x = this._open[i];
|
||
|
f = x.f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Solution found, return solution
|
||
|
if (x == goal)
|
||
|
{
|
||
|
path.nodes = this.reconstructPath(goal);
|
||
|
this._lastPath = path;
|
||
|
if(this._debug === true) path.visited = this._visited;
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
//Close current node
|
||
|
this._open.splice(this._open.indexOf(x), 1);
|
||
|
this._closed.push(x);
|
||
|
|
||
|
//Then get its neighbors
|
||
|
var n = this.neighbors(x);
|
||
|
|
||
|
for(var yIndex=0; yIndex < n.length; yIndex++)
|
||
|
{
|
||
|
|
||
|
var y = n[yIndex];
|
||
|
|
||
|
if (-1 != this._closed.indexOf(y))
|
||
|
continue;
|
||
|
|
||
|
var g = x.g + y.travelCost;
|
||
|
var better = false;
|
||
|
|
||
|
//Add the node for being considered next loop.
|
||
|
if (-1 == this._open.indexOf(y))
|
||
|
{
|
||
|
this._open.push(y);
|
||
|
better = true;
|
||
|
if(this._debug === true) this.visit(y);
|
||
|
}
|
||
|
else if (g < y.g)
|
||
|
{
|
||
|
better = true;
|
||
|
}
|
||
|
|
||
|
if (better) {
|
||
|
y.parent = x;
|
||
|
y.g = g;
|
||
|
y.h = this[this._distanceFunction](y, goal);
|
||
|
y.f = y.g + y.h;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//If no solution found, does A* try to return the closest result?
|
||
|
if(this._findClosest === true)
|
||
|
{
|
||
|
var min = Infinity;
|
||
|
var closestGoal, node, dist;
|
||
|
for(var i=0, ii=this._closed.length; i<ii; i++)
|
||
|
{
|
||
|
node = this._closed[i];
|
||
|
|
||
|
var dist = this[this._distanceFunction](goal, node);
|
||
|
if (dist < min)
|
||
|
{
|
||
|
min = dist;
|
||
|
closestGoal = node;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Reconstruct a path a path from the closestGoal
|
||
|
path.nodes = this.reconstructPath(closestGoal);
|
||
|
if(this._debug === true) path.visited = this._visited;
|
||
|
}
|
||
|
|
||
|
this._lastPath = path;
|
||
|
|
||
|
return path;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Reconstruct the result path backwards from the goal point, crawling its parents. Internal method.
|
||
|
* @method Phaser.Plugin.AStar-reconstructPath
|
||
|
* @private
|
||
|
* @param {Phaser.Plugin.AStar.AStarNode} n - The astar node from wich you want to rebuild the path.
|
||
|
* @return {array} An array of Phaser.Plugin.AStar.AStarNode
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.prototype.reconstructPath = function(n)
|
||
|
{
|
||
|
var solution = [];
|
||
|
var nn = n;
|
||
|
while(nn.parent) {
|
||
|
solution.push({x: nn.x, y: nn.y});
|
||
|
nn = nn.parent;
|
||
|
}
|
||
|
return solution;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Add a node into visited if it is not already in. Debug only.
|
||
|
* @method Phaser.Plugin.AStar-visit
|
||
|
* @private
|
||
|
* @param {Phaser.Plugin.AStar.AStarNode} node - The astar node you want to register as visited
|
||
|
* @return {void}
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.prototype.visit = function(node)
|
||
|
{
|
||
|
for(var i in this._visited)
|
||
|
{
|
||
|
if (this._visited[i] == node) return;
|
||
|
}
|
||
|
|
||
|
this._visited.push(node);
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Add a node into visited if it is not already in. Debug only.
|
||
|
* @method Phaser.Plugin.AStar-neighbors
|
||
|
* @private
|
||
|
* @param {Phaser.Plugin.AStar.AStarNode} n - The astar node you want to register as visited
|
||
|
* @return {void}
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.prototype.neighbors = function(node)
|
||
|
{
|
||
|
var x = node.x;
|
||
|
var y = node.y;
|
||
|
var n = null;
|
||
|
var neighbors = [];
|
||
|
|
||
|
var map = this._tilemap.layers[this._layerIndex].data;
|
||
|
|
||
|
//West
|
||
|
if (x > 0) {
|
||
|
|
||
|
n = map[y][x-1].properties.astarNode;
|
||
|
if (n.walkable) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
//East
|
||
|
if (x < this._tilemap.width-1) {
|
||
|
n = map[y][x+1].properties.astarNode;
|
||
|
if (n.walkable) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
//North
|
||
|
if (y > 0) {
|
||
|
n = map[y-1][x].properties.astarNode;
|
||
|
if (n.walkable) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
//South
|
||
|
if (y < this._tilemap.height-1) {
|
||
|
n = map[y+1][x].properties.astarNode;
|
||
|
if (n.walkable) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//If diagonals aren't used do not search for other neighbors and return orthogonal search result
|
||
|
if(this._useDiagonal === false)
|
||
|
return neighbors;
|
||
|
|
||
|
//NorthWest
|
||
|
if (x > 0 && y > 0) {
|
||
|
n = map[y-1][x-1].properties.astarNode;
|
||
|
if (n.walkable
|
||
|
&& map[y][x-1].properties.astarNode.walkable
|
||
|
&& map[y-1][x].properties.astarNode.walkable
|
||
|
) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
//NorthEast
|
||
|
if (x < this._tilemap.width-1 && y > 0) {
|
||
|
n = map[y-1][x+1].properties.astarNode;
|
||
|
if (n.walkable
|
||
|
&& map[y][x+1].properties.astarNode.walkable
|
||
|
&& map[y-1][x].properties.astarNode.walkable
|
||
|
) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
//SouthWest
|
||
|
if (x > 0 && y < this._tilemap.height-1) {
|
||
|
n = map[y+1][x-1].properties.astarNode;
|
||
|
if (n.walkable
|
||
|
&& map[y][x-1].properties.astarNode.walkable
|
||
|
&& map[y+1][x].properties.astarNode.walkable
|
||
|
) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
//SouthEast
|
||
|
if (x < this._tilemap.width-1 && y < this._tilemap.height-1) {
|
||
|
n = map[y+1][x+1].properties.astarNode;
|
||
|
if (n.walkable
|
||
|
&& map[y][x+1].properties.astarNode.walkable
|
||
|
&& map[y+1][x].properties.astarNode.walkable
|
||
|
) {
|
||
|
n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL;
|
||
|
neighbors.push(n);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return neighbors;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Calculate a distance between tow astar nodes coordinates according to the Manhattan method
|
||
|
* @method Phaser.Plugin.AStar-distManhattan
|
||
|
* @private
|
||
|
* @param {Phaser.Plugin.AStar.AStarNode} nodeA - The A node.
|
||
|
* @param {Phaser.Plugin.AStar.AStarNode} nodeB - The B node.
|
||
|
* @return {number} The distance between nodeA and nodeB
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.prototype.distManhattan = function (nodeA, nodeB)
|
||
|
{
|
||
|
return Math.abs(nodeA.x - nodeB.x) + Math.abs(nodeA.y - nodeB.y);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Calculate a distance between tow astar nodes coordinates according to the Euclidian method. More accurate
|
||
|
* @method Phaser.Plugin.AStar-distEuclidian
|
||
|
* @private
|
||
|
* @param {Phaser.Plugin.AStar.AStarNode} nodeA - The A node.
|
||
|
* @param {Phaser.Plugin.AStar.AStarNode} nodeB - The B node.
|
||
|
* @return {number} The distance between nodeA and nodeB
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.prototype.distEuclidian = function(nodeA, nodeB)
|
||
|
{
|
||
|
return Math.sqrt(Math.pow((nodeA.x - nodeB.x), 2) + Math.pow((nodeA.y -nodeB.y), 2));
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Tells if a tile is walkable from its tilemap coordinates
|
||
|
* @method Phaser.Plugin.AStar-isWalkable
|
||
|
* @public
|
||
|
* @param {number} x - The x coordiante of the tile in tilemap's coordinate.
|
||
|
* @param {number} y - The y coordinate of the tile in tilemap's coordinate.
|
||
|
* @return {boolean} The distance between nodeA and nodeB
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.prototype.isWalkable = function(x, y)
|
||
|
{
|
||
|
return this._tilemap.layers[this._layerIndex].data[y][x].properties.astarNode.walkable;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @properties {string} version - The version number of Phaser.Plugin.AStar read only
|
||
|
*/
|
||
|
Object.defineProperty(Phaser.Plugin.AStar.prototype, "version", {
|
||
|
|
||
|
get: function () {
|
||
|
return Phaser.Plugin.AStar.VERSION;
|
||
|
}
|
||
|
|
||
|
});
|
||
|
|
||
|
|
||
|
/**
|
||
|
* AStarNode is an object that stores AStar value. Each tile have an AStarNode in their properties
|
||
|
* @class Phaser.Plugin.AStar.AStarNode
|
||
|
* @constructor
|
||
|
* @param {number} x - The x coordinate of the tile.
|
||
|
* @param {number} y - The y coordinate of the tile.
|
||
|
* @param {boolean} isWalkable - Is this tile is walkable?
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.AStarNode = function(x, y, isWalkable)
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* @property {number} x - The x coordinate of the tile.
|
||
|
*/
|
||
|
this.x = x;
|
||
|
|
||
|
/**
|
||
|
* @property {number} y - The y coordinate of the tile.
|
||
|
*/
|
||
|
this.y = y;
|
||
|
|
||
|
/**
|
||
|
* @property {number} g - The total travel cost from the start point. Sum of COST_ORTHOGONAL and COST_DIAGONAL
|
||
|
*/
|
||
|
this.g = 0;
|
||
|
|
||
|
/**
|
||
|
* @property {number} h - The remaing distance as the crow flies between this node and the goal.
|
||
|
*/
|
||
|
this.h = 0;
|
||
|
|
||
|
/**
|
||
|
* @property {number} f - The weight. Sum of g + h.
|
||
|
*/
|
||
|
this.f = 0;
|
||
|
|
||
|
/**
|
||
|
* @property {Phaser.Plugin.AStar.AStarNode} parent - Where do we come from? It's an AStarNode reference needed to reconstruct a path backwards (from goal to start point)
|
||
|
*/
|
||
|
this.parent;
|
||
|
|
||
|
/**
|
||
|
* @property {boolean} walkable - Is this node is walkable?
|
||
|
*/
|
||
|
this.walkable = isWalkable;
|
||
|
|
||
|
/**
|
||
|
* @property {number} travelCost - The cost to travel to this node, COST_ORTHOGONAL or COST_DIAGONAL
|
||
|
*/
|
||
|
this.travelCost;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* AStarPath is an object that stores a searchPath result.
|
||
|
* @class Phaser.Plugin.AStar.AStarPath
|
||
|
* @constructor
|
||
|
* @param {array} nodes - An array of nodes coordinates sorted backward from goal to start point.
|
||
|
* @param {Phaser.Plugin.AStarNode} start - The start AStarNode used for the searchPath.
|
||
|
* @param {Phaser.Plugin.AStarNode} goal - The goal AStarNode used for the searchPath.
|
||
|
*/
|
||
|
Phaser.Plugin.AStar.AStarPath = function(nodes, start, goal)
|
||
|
{
|
||
|
/**
|
||
|
* @property {array} nodes - Array of AstarNodes x, y coordiantes that are the path solution from goal to start point.
|
||
|
*/
|
||
|
this.nodes = nodes || [];
|
||
|
|
||
|
/**
|
||
|
* @property {Phaser.Plugin.Astar.AStarNode} start - Reference to the start point used by findPath.
|
||
|
*/
|
||
|
this.start = start || null;
|
||
|
|
||
|
/**
|
||
|
* @property {Phaser.Plugin.Astar.AStarNode} goal - Reference to the goal point used by findPath.
|
||
|
*/
|
||
|
this.goal = goal || null;
|
||
|
|
||
|
/**
|
||
|
* @property {array} visited - Array of AStarNodes that the findPath algorythm has visited. Used for debug only.
|
||
|
*/
|
||
|
this.visited = [];
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Debug method to draw the last calculated path by AStar
|
||
|
* @method Phaser.Utils.Debug.AStar
|
||
|
* @param {Phaser.Plugin.AStar} astar- The AStar plugin that you want to debug.
|
||
|
* @param {number} x - X position on camera for debug display.
|
||
|
* @param {number} y - Y position on camera for debug display.
|
||
|
* @param {string} color - Color to stroke the path line.
|
||
|
* @return {void}
|
||
|
*/
|
||
|
Phaser.Utils.Debug.prototype.AStar = function(astar, x, y, color, showVisited)
|
||
|
{
|
||
|
if (this.context == null)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var pathLength = 0;
|
||
|
if(astar._lastPath !== null)
|
||
|
{
|
||
|
pathLength = astar._lastPath.nodes.length;
|
||
|
}
|
||
|
|
||
|
color = color || 'rgb(255,255,255)';
|
||
|
|
||
|
game.debug.start(x, y, color);
|
||
|
|
||
|
|
||
|
if(pathLength > 0)
|
||
|
{
|
||
|
var node = astar._lastPath.nodes[0];
|
||
|
this.context.strokeStyle = color;
|
||
|
this.context.beginPath();
|
||
|
this.context.moveTo((node.x * astar._tilemap.tileWidth) + (astar._tilemap.tileWidth/2) - game.camera.view.x, (node.y * astar._tilemap.tileHeight) + (astar._tilemap.tileHeight/2) - game.camera.view.y);
|
||
|
|
||
|
for(var i=0; i<pathLength; i++)
|
||
|
{
|
||
|
node = astar._lastPath.nodes[i];
|
||
|
this.context.lineTo((node.x * astar._tilemap.tileWidth) + (astar._tilemap.tileWidth/2) - game.camera.view.x, (node.y * astar._tilemap.tileHeight) + (astar._tilemap.tileHeight/2) - game.camera.view.y);
|
||
|
}
|
||
|
|
||
|
this.context.lineTo((astar._lastPath.start.x * astar._tilemap.tileWidth) + (astar._tilemap.tileWidth/2) - game.camera.view.x, (astar._lastPath.start.y * astar._tilemap.tileHeight) + (astar._tilemap.tileHeight/2) - game.camera.view.y);
|
||
|
|
||
|
this.context.stroke();
|
||
|
|
||
|
//Draw circles on visited nodes
|
||
|
if(showVisited !== false)
|
||
|
{
|
||
|
var visitedNode;
|
||
|
for(var j=0; j < astar._lastPath.visited.length; j++)
|
||
|
{
|
||
|
visitedNode = astar._lastPath.visited[j];
|
||
|
this.context.beginPath();
|
||
|
this.context.arc((visitedNode.x * astar._tilemap.tileWidth) + (astar._tilemap.tileWidth/2) - game.camera.view.x, (visitedNode.y * astar._tilemap.tileHeight) + (astar._tilemap.tileHeight/2) - game.camera.view.y, 2, 0, Math.PI*2, true);
|
||
|
this.context.stroke();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.line('Path length: ' + pathLength);
|
||
|
this.line('Distance func: ' + astar._distanceFunction);
|
||
|
this.line('Use diagonal: ' + astar._useDiagonal);
|
||
|
this.line('Find Closest: ' + astar._findClosest);
|
||
|
|
||
|
game.debug.stop();
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|