A*寻路的原理,网上很多,可以看这里
1 var A_STAR_DISTANCE = 7; //像素大小,越小越精确,同时越耗时 2 var A_STAR_G_EXPEND_MIN = 10; //上下左右G值消耗数 3 var A_STAR_G_EXPEND_MAX = 14; //斜角G值消耗数 4 5 var HelloWorldLayer = cc.Layer.extend({ 6 sprite:null, //角色 7 aStarPathArray:[], //最终角色要行走的路径 8 aStarBarrierArray:[], //地图障碍物 9 testNumber:1, 10 ctor:function () { 11 ////////////////////////////// 12 // 1. super init first 13 this._super(); 14 ///////////////////////////// 15 // 2. add a menu item with "X" image, which is clicked to quit the program 16 // you may modify it. 17 // ask director the window size 18 var size = cc.director.getWinSize(); 19 20 this.sprite = cc.Sprite.create(res.Plane_png); //角色初始化 21 this.sprite.attr({ 22 x: 150, 23 y: 50, 24 rotation: 90 25 }); 26 this.addChild(this.sprite, 0); 27 28 var barrier1 = cc.rect(200,50,50,350); //绘制障碍物 29 var barrier2 = cc.rect(250,50,350,50); 30 var barrier3 = cc.rect(250,350,350,50); 31 this.aStarBarrierArray.push(barrier1); 32 this.aStarBarrierArray.push(barrier2); 33 this.aStarBarrierArray.push(barrier3); 34 35 var drawBarrier = cc.DrawNode.create(); //在屏幕上显示障碍物 36 this.addChild(drawBarrier, 10); 37 var vertices = [cc.p(200,50),cc.p(600,50),cc.p(600,100),cc.p(250,100),cc.p(250,350),cc.p(600,350),cc.p(600,400),cc.p(200,400)]; 38 drawBarrier.drawPoly(vertices,null,2,cc.color(255,0,0,255)); 39 40 if ('mouse' in cc.sys.capabilities) 41 cc.eventManager.addListener({ 42 event: cc.EventListener.MOUSE, 43 onMouseUp:function(event){ 44 if(event.getButton() != undefined) 45 { 46 var t = new Date().getTime(); 47 event.getCurrentTarget().getStartAndEndPoint(event); //A*算法开始 48 cc.log("算法耗时:"+(new Date().getTime() - t)+"ms"); //计算起点到终点的算法耗时 49 } 50 } 51 }, this); 52 53 54 return true; 55 }, 56 getStartAndEndPoint:function (event) { //得到起始点和终点坐标 57 var sp = {coordX:parseInt(this.sprite.x,10),coordY:parseInt(this.sprite.y,10)}; 58 var ep = {coordX:parseInt(event.getLocation().x,10),coordY:parseInt(event.getLocation().y,10)}; 59 var endPointIsObstacle = false; //判断终点是否在障碍物上,是的话就提示路径走不了 60 for (var theBarrierIndex=0; theBarrierIndex<this.aStarBarrierArray.length; theBarrierIndex++){ 61 if(cc.rectContainsPoint(this.aStarBarrierArray[theBarrierIndex],cc.p(ep.coordX,ep.coordY))) 62 { 63 endPointIsObstacle = true; 64 cc.log("你要去的位置有障碍物,请换条路线"); 65 break; 66 } 67 } 68 if(!endPointIsObstacle) 69 this.findingPath(sp,ep); 70 }, 71 findingPath:function(startPoint,endPoint){ //A*算法 72 var openList = []; //初始化开启列表 73 var closeList = []; //初始化关闭列表 74 startPoint.ag = 0; 75 startPoint.ah = 0; 76 startPoint.af = startPoint.ag + startPoint.ah; //起点的G,H,F值为0 77 openList.push(startPoint); //起点加入开启列表 78 var findTheWay = false; 79 do{ 80 var centerNode = this.findMinNode(openList); //寻找F值最低的节点 81 openList.remove(centerNode); //将此节点从开启列表中删除,为了下次遍历开启列表的时候不再出现此节点 82 closeList.push(centerNode); //并将此节点加入到关闭列表 83 for(var i=0;i<8;i++) //遍历此节点周围的节点,并给这些节点加入坐标属性和G值 84 { 85 var aroundNode = {}; 86 switch (i){ 87 case 0: 88 aroundNode.coordX = centerNode.coordX+A_STAR_DISTANCE; //坐标属性 89 aroundNode.coordY = centerNode.coordY+A_STAR_DISTANCE; 90 break; 91 case 1: 92 aroundNode.coordX = centerNode.coordX+A_STAR_DISTANCE; 93 aroundNode.coordY = centerNode.coordY; 94 break; 95 case 2: 96 aroundNode.coordX = centerNode.coordX+A_STAR_DISTANCE; 97 aroundNode.coordY = centerNode.coordY-A_STAR_DISTANCE; 98 break; 99 case 3: 100 aroundNode.coordX = centerNode.coordX; 101 aroundNode.coordY = centerNode.coordY-A_STAR_DISTANCE; 102 break; 103 case 4: 104 aroundNode.coordX = centerNode.coordX-A_STAR_DISTANCE; 105 aroundNode.coordY = centerNode.coordY-A_STAR_DISTANCE; 106 break; 107 case 5: 108 aroundNode.coordX = centerNode.coordX-A_STAR_DISTANCE; 109 aroundNode.coordY = centerNode.coordY; 110 break; 111 case 6: 112 aroundNode.coordX = centerNode.coordX-A_STAR_DISTANCE; 113 aroundNode.coordY = centerNode.coordY+A_STAR_DISTANCE; 114 break; 115 case 7: 116 aroundNode.coordX = centerNode.coordX; 117 aroundNode.coordY = centerNode.coordY+A_STAR_DISTANCE; 118 break; 119 } 120 for (var barrierIndex=0; barrierIndex<this.aStarBarrierArray.length; barrierIndex++){ 121 aroundNode.isOb = cc.rectContainsPoint(this.aStarBarrierArray[barrierIndex],cc.p(aroundNode.coordX,aroundNode.coordY)); //判断当前节点是否在障碍物形成的方框里 122 if(aroundNode.isOb) 123 break; 124 } 125 if (aroundNode.isOb){ //如果是障碍物,跳过 126 127 } 128 else if(closeList.hasObject(aroundNode)){ //如果在关闭列表里,跳过 129 130 } 131 else if(!openList.hasObject(aroundNode)){ //如果不在开启列表里,加入到开启列表 132 aroundNode.parentPath = centerNode; 133 if (Math.abs(aroundNode.coordX-endPoint.coordX)<=A_STAR_DISTANCE/2 && Math.abs(aroundNode.coordY-endPoint.coordY)<=A_STAR_DISTANCE/2) //如果节点和终点的值相近,那么A*算法结束,得到路径 134 { 135 findTheWay = true; 136 var pathArry = []; 137 this.gettingAStarPath(aroundNode,pathArry); //寻找路径 138 pathArry.splice(0,0,{starX:endPoint.coordX,starY:endPoint.coordY}); //加终点到数组头部 139 pathArry.splice(pathArry.length-1,1); //删一项数组底部的起点数据,此时的数组是最终的路径数组 140 141 this.aStarPathArray = []; 142 this.aStarPathArray = pathArry; 143 this.aStarPathArray.theIndex = this.aStarPathArray.length; 144 145 this.unschedule(this.thePathSelector); 146 this.schedule(this.thePathSelector,null,pathArry.length-1); 147 break; //找到最短路径并跳出循环 148 } 149 if (aroundNode.coordX!=centerNode.coordX && aroundNode.coordY!=centerNode.coordY) //确定中心节点和周围节点形成的角度,正交G值消耗10*像素,斜角G值消耗14*像素 150 aroundNode.ag = centerNode.ag + A_STAR_G_EXPEND_MAX*A_STAR_DISTANCE; 151 else 152 aroundNode.ag = centerNode.ag + A_STAR_G_EXPEND_MIN*A_STAR_DISTANCE; 153 aroundNode.af = this.getAF(aroundNode,endPoint); 154 openList.push(aroundNode); 155 } 156 else if(openList.hasObject(aroundNode)){ //如果在开启列表里 157 var newExpend = A_STAR_G_EXPEND_MIN*A_STAR_DISTANCE; 158 if (aroundNode.coordX!=centerNode.coordX && aroundNode.coordY!=centerNode.coordY) //确定中心节点和周围节点形成的角度,正交G值消耗10*像素,斜角G值消耗14*像素 159 newExpend = A_STAR_G_EXPEND_MAX*A_STAR_DISTANCE; 160 if (centerNode.ag + newExpend < aroundNode.ag){ //如果新的g值小于周围节点本身的g值,那么周围节点的父节点改为当前中心节点,并重新计算其F值 161 aroundNode.parentPath = centerNode; 162 aroundNode.ag = centerNode.ag + newExpend; 163 aroundNode.af = this.getAF(aroundNode,endPoint); 164 } 165 } 166 } 167 }while(!findTheWay) 168 169 }, 170 findMinNode:function(openListArray){ 171 var minNode = openListArray[0]; 172 for (var i=0;i<openListArray.length;i++) 173 { 174 if (minNode.af>openListArray[i].af) minNode=openListArray[i]; 175 } 176 return minNode; 177 }, 178 getAF:function(thisNode,endNode){ 179 var aHExpend = (Math.abs(thisNode.coordX-endNode.coordX) + Math.abs(thisNode.coordY-endNode.coordY))*A_STAR_G_EXPEND_MIN; 180 return aHExpend+thisNode.ag; 181 }, 182 gettingAStarPath:function(laseNode,array){ 183 if(laseNode.parentPath != null) 184 { 185 array.push({starX:laseNode.parentPath.coordX,starY:laseNode.parentPath.coordY}); 186 this.gettingAStarPath(laseNode.parentPath,array); 187 } 188 }, 189 thePathSelector:function(){ 190 this.roleRunThePath(this.aStarPathArray); 191 }, 192 roleRunThePath:function(array){ 193 this.sprite.x = array[--array.theIndex].starX; 194 this.sprite.y = array[array.theIndex].starY; 195 } 196 }); 197 198 var HelloWorldScene = cc.Scene.extend({ 199 onEnter:function () { 200 this._super(); 201 var layer = new HelloWorldLayer(); 202 this.addChild(layer); 203 } 204 }); 205 206 //这里给Array数组添加3个实例方法 207 Array.prototype.aStarIndexOf = function(val) { //通过对象寻找index值 208 for (var i = 0; i < this.length; i++) { 209 if (this[i].coordX==val.coordX && this[i].coordY==val.coordY) return i; 210 } 211 return -1; 212 }; 213 Array.prototype.remove = function(val) { //删除相应的对象 214 var index = this.aStarIndexOf(val); 215 if (index > -1) { 216 this.splice(index, 1); 217 } 218 }; 219 220 Array.prototype.hasObject = function(val){ //判断是否是同一个对象 221 for (var i = 0; i < this.length; i++){ 222 if (this[i].coordX==val.coordX && this[i].coordY==val.coordY) 223 return true; 224 } 225 return false; 226 };