Creator 版本号:1.4.2
运行时目标平台:模拟器
操作系统:windows
最近在研究a*巡路的算法,然后自己写了一个,不说废话,先上代码:
--------------------------------------分割线--------------------------------------------
//点对象
var aStarPos = cc.Class({
ctor:function() {
this.pos = cc.v2(0, 0); //所在位置
this.fPos = null; //父节点
this.g = 0; // 到起点的位置
this.h = 0; // 到终点的位置
this.f = 0; //g + h
}
});
//巡路参数
var gridRank = 0; //宽
var gridLine = 0; //高
var gridWidth = 0; //格子大小
var gridArray = []; //障碍数组
var isFour = true; //是否四方向
//设置巡路参数
window.aStar_setPatrolConfig = function(rank, line, width, _gridArray, _isFour) {
gridRank = rank;
gridLine = line;
gridWidth = width;
gridArray = _gridArray;
isFour = _isFour;
};
//A*巡路
window.aStar_partrolFunc = function(startPos, endPos) {
var openArray = []; //开启列表
var closeArray = []; //关闭列表
//起点对象
var startObj = new aStarPos();
startObj.pos = startPos;
startObj.fPos = null;
//添加到关闭数组
closeArray.push(startObj);
//开始检测
return aStar_checkPosition(startPos, endPos, startObj, openArray, closeArray);
};
//位置判断
window.aStar_checkPosition = function(startPos, endPos, starObj, openArray, closeArray) {
//检测点位置
var position = starObj.pos;
var arr = [];
//四方向巡路
if(true === isFour) {
arr.push(cc.pAdd(position, cc.v2(-1, 0)));
arr.push(cc.pAdd(position, cc.v2(1, 0)));
arr.push(cc.pAdd(position, cc.v2(0, -1)));
arr.push(cc.pAdd(position, cc.v2(0, 1)));
}
//八方向巡路
else {
arr.push(cc.pAdd(position, cc.v2(-1, 0)));
arr.push(cc.pAdd(position, cc.v2(1, 0)));
arr.push(cc.pAdd(position, cc.v2(0, -1)));
arr.push(cc.pAdd(position, cc.v2(0, 1)));
arr.push(cc.pAdd(position, cc.v2(-1, -1)));
arr.push(cc.pAdd(position, cc.v2(-1, 1)));
arr.push(cc.pAdd(position, cc.v2(1, -1)));
arr.push(cc.pAdd(position, cc.v2(1, 1)));
}
//判断各个方向
for(var i = 0; i < arr.length; i++) {
//方向点
var pos = arr[i];
//越界处理
if(pos.x < 0 || pos.x > gridRank || pos.y < 0 || pos.y > gridLine) {
continue;
}
//障碍处理
if(true === aStar_dealObstacle(pos)) {
continue;
}
//判断是否在打开列表
if(-1 !== aStar_getObj(pos, openArray)) {
//取出在打开列表的对象
var oldObj = aStar_getObj(pos, openArray);
var objPos = oldObj.pos;
//重新计算g值
var newG = 0;
if(true === isFour) {
newG = (Math.abs(objPos.x - position.x) + Math.abs(objPos.y - position.y)) * gridWidth + starObj.g;
}
else {
var g_x = Math.abs(pos.x - position.x) * gridWidth;
var g_y = Math.abs(pos.y - position.y) * gridWidth;
newG = Math.sqrt(g_x * g_x + g_y * g_y) + starObj.g;
}
//比较替换
if(newG < oldObj.g) {
oldObj.g = newG;
oldObj.fPos = starObj;
}
}
//创建新的
else {
//新对象
var newObj = new aStarPos();
newObj.pos = pos;
//确定不在列表内
if(false === aStar_isAloneArray(newObj, closeArray) && false === aStar_isAloneArray(newObj, openArray)) {
//g、h
var g = 0;
var h = 0;
//区分四方向、八方向
if(true === isFour) {
g = (Math.abs(pos.x - position.x) + Math.abs(pos.y - position.y)) * gridWidth + starObj.g;
h = (Math.abs(pos.x - endPos.x) + Math.abs(pos.y - endPos.y)) * gridWidth;
}
else {
var g_x = Math.abs(pos.x - position.x) * gridWidth;
var g_y = Math.abs(pos.y - position.y) * gridWidth;
g = Math.sqrt(g_x * g_x + g_y * g_y) + starObj.g;
var h_x = Math.abs(pos.x - position.x) * gridWidth;
var h_y = Math.abs(pos.y - position.y) * gridWidth;
h = Math.sqrt(h_x * h_x + h_y * h_y);
}
newObj.fPos = starObj; //父节点
//赋值
newObj.g = g;
newObj.h = h;
newObj.f = g + h;
openArray.push(newObj);
if(pos.x === endPos.x && pos.y === endPos.y) {
return newObj;
}
}
}
}
//根据f值由低到高排序
openArray = aStar_bubbleSort(openArray);
//从开启列表zhong取出h最低的加入到关闭开启列表中列表
var _obj = openArray.pop();
//开启列表为空说明无路径
if(undefined === _obj) {
return -1; //死路
}
closeArray.push(_obj);
//继续判断
return aStar_checkPosition(startPos, endPos, _obj, openArray, closeArray);
};
//从列表取出一个对象
window.aStar_getObj = function(pos, array) {
for(var i = 0; i < array.length; i++) {
var a = array[i];
if(a.pos.x === pos.x && a.pos.y === pos.y) {
return a;
}
}
return -1;
};
//判断对象是否在数组内
window.aStar_isAloneArray = function(obj, array) {
for(var i = 0; i < array.length; i++) {
var a = array[i];
if(a.pos.x === obj.pos.x && a.pos.y === obj.pos.y) {
return true;
}
}
return false;
};
//障碍物处理
window.aStar_dealObstacle = function(pos) {
if(1 === gridArray[pos.x][pos.y]) {
return true;
}
else {
return false;
}
};
//冒泡排序
window.aStar_bubbleSort = function(array) {
var i = array.length;
var j = 0;
var tempExchangVal = 0; //中间变量
while (i > 0) {
for (j = 0; j < i - 1; j++) {
if (array[j].f < array[j + 1].f) {
tempExchangVal = array[j];
array[j] = array[j + 1];
array[j + 1] = tempExchangVal;
}
}
i–;
}
return array;
};
--------------------------------------分割线--------------------------------------------
区分了四方向和八方向,经过测试发现一个问题,仅四方向出现,八方向正常,如图:红色为障碍,黄色为路径
四方向不是最短路径
八方向正常
不知道是哪里的问题