利用A*寻路算法写的一个类,希望对研究tile和astar的flash朋友有所帮助。
1 /**
2 * @author rison
3 * @data 2006-05-03
4 * @version 1.1
5 * @usage A*path searching
6 */
7 class Astar {
8 //init var
9 private static var cost:Number = 10;
10 private static var isSearching:Boolean = false;
11 private static var broadcastInit = AsBroadcaster.initialize(Astar.prototype);
12 public var addListener:Function;
13 public var removeListener:Function;
14 private var broadcastMessage:Function;
15 private var path:Array;
16 private var openList:Array;
17 private var closeList:Array;
18 private var map:Array;
19 private var pointType:Array;
20 private var directData:Array;
21 //
22 public function Astar() {
23 path = new Array();
24 pointType = new Array();
25 openList = new Array();
26 closeList = new Array();
27 directData = new Array();
28 map = new Array();
29 initDirectData();
30 }
31 public function setMap(map_t:Array) {
32 map = map_t;
33 setPointType(map);
34 }
35 public function findPath(startX:Number, startY:Number, endX:Number, endY:Number) {
36 initData();
37 isSearching = true;
38 var startPoint:Object = new Object();
39 var endPoint:Object = new Object();
40 var prePoint:Object = new Object();
41 startPoint.X = startX;
42 startPoint.Y = startY;
43 endPoint.X = endX;
44 endPoint.Y = endY;
45 startPoint.parent = null;
46 startPoint.G = 0;
47 startPoint.H = manhattanDis(startPoint, endPoint);
48 startPoint.F = startPoint.G+startPoint.H;
49 prePoint = startPoint;
50 //send2List(startPoint, openList);
51 send2List(startPoint, closeList);
52 while (isSearching == true) {
53 for (var i = 0; i<directData.length; i++) {
54 var tempPoint:Object = new Object();
55 tempPoint.X = prePoint.X+directData[i][0];
56 tempPoint.Y = prePoint.Y+directData[i][1];
57 if (isOut(tempPoint) == true) {
58 } else {
59 if (tempPoint.Y == endPoint.Y && tempPoint.X == endPoint.X) {
60 //found
61 isSearching = false;
62 send2List(tempPoint, closeList);
63 tempPoint.parent = prePoint;
64 tempPoint.G = prePoint.G+directData[i][2];
65 tempPoint.H = manhattanDis(tempPoint, endPoint);
66 tempPoint.F = tempPoint.G+tempPoint.H;
67 //trace(closeList[closeList.length-1].X+" "+closeList[closeList.length-1].Y);
68 //trace("path found!");
69 drawPath();
70 broadcastMessage("onPathFound");
71 return;
72 }
73 if (getPointType(tempPoint) == "road" && isInList(tempPoint, closeList) == false) {
74 //trace("四向之"+i+" tempPoint:"+tempPoint.X+" "+tempPoint.Y);
75 //目标格不在关闭列表且是road
76 if (isInList(tempPoint, openList) == false) {
77 //目标格尚未开启
78 send2List(tempPoint, openList);
79 //trace("ol:"+openList[0].X+"=="+openList[0].Y);
80 tempPoint.parent = prePoint;
81 tempPoint.G = prePoint.G+directData[i][2];
82 tempPoint.H = manhattanDis(tempPoint, endPoint);
83 tempPoint.F = tempPoint.G+tempPoint.H;
84 } else {
85 //已经在开启列表中
86 var tempG:Number = prePoint.G+directData[i][2];
87 for (var j = 0; j<openList.length; j++) {
88 if (tempPoint.X == openList[j].X && tempPoint.Y == openList[j].Y) {
89 if (tempG<openList[j].G) {
90 //现在的路径G更好
91 openList[j].G = tempG;
92 openList[j].F = openList[j].G+openList[j].H;
93 openList[j].parent = prePoint;
94 }
95 break;
96 }
97 }
98 }
99 }
100 }
101 }
102 if (openList.length == 0) {
103 isSearching = false;
104 broadcastMessage("onPathBlock");
105 return;
106 }
107 sortList(openList);
108 prePoint = openList.shift();
109 send2List(prePoint, closeList);
110 //trace(closeList[closeList.length-1].X+" "+closeList[closeList.length-1].Y);
111 }
112 }
113 public function getPath():Array {
114 path.reverse();
115 trace("==========Path start===========");
116 for (var i = 0; i<path.length; i++) {
117 trace("path:"+path[i].X+path[i].Y);
118 }
119 trace("==========Path end ===========");
120 return path;
121 }
122 private function initData():Void {
123 openList = [];
124 closeList = [];
125 path = [];
126 }
127 private function drawPath() {
128 //trace("set path");
129 closeList.reverse();
130 var currentPathPoint:Object = new Object();
131 currentPathPoint = closeList[0];
132 send2List(currentPathPoint, path);
133 //trace(currentPathPoint.X+" "+currentPathPoint.Y);
134 for (var i = 1; i<closeList.length; i++) {
135 if (currentPathPoint.parent == null) {
136 break;
137 }
138 //trace(currentPathPoint.parent.X+" "+currentPathPoint.parent.Y);
139 send2List(currentPathPoint.parent, path);
140 currentPathPoint = currentPathPoint.parent;
141 }
142 }
143 private function getPointType(point_t:Object):String {
144 return pointType[point_t.X][point_t.Y];
145 }
146 private function setPointType(map_t:Array) {
147 for (var i = 0; i<map_t.length; i++) {
148 pointType[i] = new Array();
149 for (var j = 0; j<map_t[0].length; j++) {
150 if (map_t[i][j] == 1) {
151 pointType[i].push("wall");
152 } else if (map_t[i][j] == 0) {
153 pointType[i].push("road");
154 }
155 }
156 }
157 //trace("第一行:"+pointType[0]);
158 }
159 private function initDirectData():Void {
160 //下,右,上,左
161 directData[0] = [1, 0, 10];
162 directData[1] = [0, 1, 10];
163 directData[2] = [-1, 0, 10];
164 directData[3] = [0, -1, 10];
165 }
166 private function sortList(list_t:Array):Void {
167 list_t.sortOn("F", Array.NUMERIC);
168 }
169 private function isOut(point_t:Object):Boolean {
170 if (point_t.X<0 || point_t.Y<0 || point_t.X>16 || point_t.Y>16) {
171 return true;
172 } else {
173 return false;
174 }
175 }
176 private function isInList(point_t:Object, list_t:Array):Boolean {
177 if (list_t.length == 0) {
178 return false;
179 }
180 for (var i = 0; i<list_t.length; ) {
181 if (list_t[i].X == point_t.X && list_t[i].Y == point_t.Y) {
182 return true;
183 break;
184 }
185 i++;
186 if (i == list_t.length) {
187 return false;
188 }
189 }
190 }
191 private function manhattanDis(start_t:Object, end_t:Object):Number {
192 var dis:Number;
193 dis = Math.abs(start_t.X-end_t.X)+Math.abs(start_t.Y-end_t.Y);
194 return dis*cost;
195 }
196 private function send2List(point_t:Object, list_t:Array):Void {
197 list_t.push(point_t);
198 }
199 }
200
参考文档:http://blog.vckbase.com/panic/archive/2005/03/20/3778.html