1 #ifndef __BSTAR__H
2 #define __BSTAR__H
3
4 #include "AIDefine.h"
5 #include <vector>
6
7 class BStar
8 {
9 private:
10 BStar();
11 public:
12 static bool find(const PointI &size, const PointI &start, const PointI &end, AI_VisitFun visitFun, Path **path = NULL)
13 {
14 if(size.x <= 0 || size.y <= 0 || start.x < 0 || start.y < 0 || end.x < 0 || end.y < 0 ||
15 start.x >= size.x || start.y >= size.y || end.x >= size.x || end.y >= size.y ||
16 !visitFun(start.x, start.y), !visitFun(end.x, end.y))
17 {
18 if(NULL != path){*path = new Path(false, 0.0f);}
19 return false;
20 }
21 if(start.x == end.x && start.y == end.y)
22 {
23 if(NULL != path){*path = new Path(true, 0.0f);}
24 return true;
25 }
26
27 EDIRTYPE curDir = DIR_LEFT, nextDir = DIR_NONE;
28 if(AI_ABS(end.x - start.x) >= AI_ABS(end.y - start.y))
29 {
30 if(end.x > start.x){curDir = DIR_RIGHT;}
31 else{curDir = DIR_LEFT;}
32 }else
33 {
34 if(end.y > start.y){curDir = DIR_DOWN;}
35 else{curDir = DIR_UP;}
36 }
37
38 std::vector<Info*> visit;
39 std::vector<Info*>::iterator iter;
40 Info *nodeArr = new Info[size.x * size.y];
41 Info *cur, *next;
42 PointI pos;
43
44 cur = &nodeArr[size.x * start.y + start.x];
45 cur->x = start.x; cur->y = start.y; cur->visited = true;cur->dir = curDir;
46 visit.push_back(cur);
47
48 while(!visit.empty())
49 {
50 iter = visit.end(); --iter; cur = *iter;curDir = cur->dir;
51 if(cur->x == end.x && cur->y == end.y)
52 {
53 if(NULL != path)
54 {
55 *path = new Path(true, 0.0f);
56 for(iter = visit.begin(); iter != visit.end(); ++iter)
57 {
58 (*path)->push_back(PointI((*iter)->x, (*iter)->y));
59 }
60 }
61 if(NULL != nodeArr){delete[] nodeArr;}
62 return true;
63 }
64 if(DIR_LEFT == curDir){pos.x = cur->x - 1;pos.y = cur->y;}
65 else if(DIR_RIGHT == curDir){pos.x = cur->x + 1;pos.y = cur->y;}
66 else if(DIR_DOWN == curDir){pos.x = cur->x;pos.y = cur->y + 1;}
67 else if(DIR_UP == curDir){pos.x = cur->x;pos.y = cur->y - 1;}
68 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y))
69 {
70 next = &nodeArr[size.x * pos.y + pos.x];
71 next->x = pos.x; next->y = pos.y; next->visited = true;next->dir = curDir;
72 visit.push_back(next);
73 if(DIR_LEFT == curDir || DIR_RIGHT == curDir)
74 {
75 if(next->x == end.x)
76 {
77 if(end.y >= cur->y)
78 {
79 pos.x = cur->x; pos.y = cur->y + 1;
80 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y))
81 {
82 next->dir = curDir = DIR_DOWN;
83 }
84 }else
85 {
86 pos.x = cur->x; pos.y = cur->y - 1;
87 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y))
88 {
89 next->dir = curDir = DIR_UP;
90 }
91 }
92 }
93 }else if(DIR_DOWN == curDir || DIR_UP == curDir)
94 {
95 if(next->y == end.y)
96 {
97 if(end.x >= cur->x)
98 {
99 pos.x = cur->x + 1; pos.y = cur->y;
100 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y))
101 {
102 next->dir = curDir = DIR_RIGHT;
103 }
104 }else
105 {
106 pos.x = cur->x - 1; pos.y = cur->y;
107 if(AI_CheckRange(pos,size) && !nodeArr[size.x * pos.y + pos.x].visited && visitFun(pos.x, pos.y))
108 {
109 next->dir = curDir = DIR_LEFT;
110 }
111 }
112 }
113 }
114 }else
115 {
116 if(DIR_LEFT == curDir || DIR_RIGHT == curDir)
117 {
118 if(end.y >= cur->y)
119 {
120 pos.x = cur->x; pos.y = cur->y + 1;nextDir = DIR_DOWN;
121 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y))
122 {
123 pos.x = cur->x; pos.y = cur->y - 1;nextDir = DIR_UP;
124 }
125 }else
126 {
127 pos.x = cur->x; pos.y = cur->y - 1;nextDir = DIR_UP;
128 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y))
129 {
130 pos.x = cur->x; pos.y = cur->y + 1;nextDir = DIR_DOWN;
131 }
132 }
133 }else if(DIR_DOWN == curDir || DIR_UP == curDir)
134 {
135 if(end.x >= cur->x)
136 {
137 pos.x = cur->x + 1; pos.y = cur->y;nextDir = DIR_RIGHT;
138 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y))
139 {
140 pos.x = cur->x - 1; pos.y = cur->y;nextDir = DIR_LEFT;
141 }
142 }else
143 {
144 pos.x = cur->x - 1; pos.y = cur->y;nextDir = DIR_LEFT;
145 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y))
146 {
147 pos.x = cur->x + 1; pos.y = cur->y;nextDir = DIR_RIGHT;
148 }
149 }
150 }
151 if(!AI_CheckRange(pos,size) || nodeArr[size.x * pos.y + pos.x].visited || !visitFun(pos.x, pos.y))
152 {
153 visit.pop_back();
154 }else
155 {
156 next = &nodeArr[size.x * pos.y + pos.x];
157 next->x = pos.x; next->y = pos.y; next->visited = true;next->dir = nextDir;
158 visit.push_back(next);
159 }
160 }
161 }
162 if(NULL != path){*path = new Path(false, 0.0f);}
163 if(NULL != nodeArr){delete[] nodeArr;}
164 return false;
165 }
166 private:
167 enum EDIRTYPE
168 {
169 DIR_NONE,
170 DIR_LEFT,
171 DIR_RIGHT,
172 DIR_UP,
173 DIR_DOWN
174 };
175 struct Info
176 {
177 Info():visited(false),x(0),y(0),dir(DIR_NONE){}
178 bool visited;
179 int x,y;
180 EDIRTYPE dir;
181 };
182 };
183
184 #endif