package util { import config.Config; import flash.geom.Point; import flash.utils.Dictionary; import flash.utils.getTimer; import flashx.textLayout.formats.Direction; import gameui.RoleGameCoordinate; import gameui.newui.scene.GameWorld; /** * 2010-10-13 寻路核心算法 * @author xiaowei * */ public class Road { private var openList:Array = []; //两个hash表 private var closeListDic:Dictionary = new Dictionary(true); private var openListDic:Dictionary = new Dictionary(true); private var endX:int; private var endY:int; private const _mid:int = Math.round(Math.sqrt(Math.pow(Config.getMapRectWidth()/2,2)+Math.pow(Config.getMapRectHeight()/2,2)));//斜着走 public function Road() { } //开始寻路 public function search(startPos:Point,endPos:Point):Array { if(startPos == null || endPos == null) return openList; var startNode:Node = new Node(); this.endX = endPos.x; this.endY = endPos.y //把起点加入开启列表 startNode.x = startPos.x; startNode.y = startPos.y; this.openList.push(startNode); openListDic[startPos.x+"_"+startPos.y] = startNode; var dx:int = (startPos.x+startPos.y)/2; var dy:int = (startPos.x-startPos.y); //如果是不可站点 if(!isWay(dx,dy)){ return null; } while(openList.length>0){ //取出最小节 var currNode:Node = this.openList.shift(); delete openListDic[currNode.x+"_"+currNode.y]; //判断是否找出路径 if(currNode.x == endX && currNode.y == endY){ this.destroyHistoryNode(); return getPath(currNode); } //找周围8个格子,并加入开启列表 this.addOpenList(currNode); //排序 openList.sortOn("f",Array.NUMERIC); //加入关闭列表 closeListDic[currNode.x+"_"+currNode.y] = currNode; } this.destroyHistoryNode(); return null; } //得到路径 private function getPath(currNode:Node):Array{ var path:Array = []; while(currNode.parentNode != null){ path.push(currNode.pos); currNode = currNode.parentNode; } return path.reverse(); } //删除历史 private function destroyHistoryNode():void{ for (var ckey:Object in closeListDic){ delete closeListDic[ckey]; } for (var okey:Object in openListDic){ delete openListDic[okey]; } this.openList.splice(0,this.openList.length); } //找周围8个格子 public function addOpenList(currNode:Node):void{ var x:int = currNode.x; var y:int = currNode.y; getNode(x+1,y-1,Config.getMapRectHeight(),1,currNode); getNode(x,y-1,_mid,2,currNode); getNode(x-1,y-1,Config.getMapRectWidth(),3,currNode); getNode(x-1,y,_mid,4,currNode); getNode(x-1,y+1,Config.getMapRectHeight(),5,currNode); getNode(x,y+1,_mid,6,currNode); getNode(x+1,y+1,Config.getMapRectWidth(),7,currNode); getNode(x+1,y,_mid,8,currNode); } //判断每一个节点是否能加入列表 private function getNode(x:int,y:int,g:int,pos:int,currNode:Node):void{ var dx:int = (x+y)/2; var dy:int = (x-y); //如果是可站点 if(isWay(dx,dy)){ var g:int = currNode.g+g; var h:int = getH(x,y); var node:Node = null; if((node = openListDic[x+"_"+y])!=null){//加入了开启 if(g<node.g){ node.y = y; node.g = g; node.h = h; node.f = g+h; node.pos = pos; node.parentNode = currNode; } }else if((node = closeListDic[x+"_"+y])!=null){//加入了关闭 if(g<node.g){ node.y = y; node.g = g; node.h = h; node.f = g+h; node.pos = pos; node.parentNode = currNode; } }else{ node = new Node(); node.x = x; node.y = y; node.g = g; node.h = h; node.f = g+h; node.pos = pos; node.parentNode = currNode; openListDic[node.x + "_" + node.y] = node; this.openList.push(node); } } } //判断路是否可站 public static function isWay(dx:int,dy:int):Boolean{ //超出地图了 if(dx<0 || dy<0 || dx>GameWorld.mapCols-1 || dy>GameWorld.mapRows-1 || GameWorld.getInstance().getMapDatas()[dy][dx] == null){ return false; } //是否有障碍物 或者是不可以站的点 if(GameWorld.getInstance().getMapDatas()[dy][dx]==0){ return false; } return true; } //检查是否存在数组 private function checkInArray(x:int,y:int,array:Array):Node{ for each(var node:Node in array){ if(node.x == x && node.y ==y){ return node; } } return null; } //获取H private function getH(ix:int,iy:int):int{ var H:int = 0; var xDistance:int = Math.abs(ix-this.endX); var yDistance:int = Math.abs(iy-this.endY); if(xDistance > yDistance){ H = Config.getMapRectWidth()*yDistance + Config.getMapRectHeight()*(xDistance-yDistance); }else{ H = Config.getMapRectWidth()*xDistance + Config.getMapRectHeight()*(yDistance-xDistance); } return H; } } } package util { public class Node { public var x:int; public var y:int; public var pos:int; public var parentNode:Node; public var g:int; public var h:int; public var f:int; public function Node() { } } }