comparison ai/steer.d @ 22:4fce5596d1f6

ai work
author zzzzrrr <mason.green@gmail.com>
date Thu, 26 Mar 2009 16:56:30 -0400
parents cad384ad349e
children e79347dd38a3
comparison
equal deleted inserted replaced
21:cad384ad349e 22:4fce5596d1f6
47 // Constructor: initializes state 47 // Constructor: initializes state
48 this (Ship ship) 48 this (Ship ship)
49 { 49 {
50 m_ship = ship; 50 m_ship = ship;
51 m_body = ship.rBody; 51 m_body = ship.rBody;
52 m_radius = 0.0f;
53
54 // Find radius of body
55 for (bzShape s = m_body.shapeList; s; s = s.next) {
56 if(s.sweepRadius > m_radius) {
57 m_radius = s.sweepRadius;
58 }
59 }
60 } 52 }
61 53
62 struct PathIntersection 54 struct PathIntersection
63 { 55 {
64 bool intersect; 56 bool intersect;
79 m_position = m_ship.state.position; 71 m_position = m_ship.state.position;
80 m_velocity = m_ship.state.velocity; 72 m_velocity = m_ship.state.velocity;
81 m_speed = m_ship.state.speed; 73 m_speed = m_ship.state.speed;
82 m_maxForce = m_ship.state.maxForce; 74 m_maxForce = m_ship.state.maxForce;
83 m_forward = m_ship.state.forward; 75 m_forward = m_ship.state.forward;
76 m_radius = m_ship.state.radius;
84 } 77 }
85 78
86 // -------------------------------------------------- steering behaviors 79 // -------------------------------------------------- steering behaviors
87 80
88 bzVec2 steerForWander (float dt) { 81 bzVec2 steerForWander (float dt) {
145 138
146 bzVec2 steerToAvoidObstacles (float minTimeToCollision, bzBody obstacles) { 139 bzVec2 steerToAvoidObstacles (float minTimeToCollision, bzBody obstacles) {
147 140
148 bzVec2 avoidance; 141 bzVec2 avoidance;
149 PathIntersection nearest, next; 142 PathIntersection nearest, next;
150 float minDistanceToCollision = minTimeToCollision * m_speed; 143 float minDistanceToCollision = 10; //minTimeToCollision * m_speed;
151 144
152 next.intersect = false; 145 next.intersect = false;
153 nearest.intersect = false; 146 nearest.intersect = false;
154 147
155 // test all obstacles for intersection with my forward axis, 148 // test all obstacles for intersection with my forward axis,
157 for (bzBody o = obstacles; o; o = o.next) { 150 for (bzBody o = obstacles; o; o = o.next) {
158 151
159 if(o is m_body) continue; 152 if(o is m_body) continue;
160 153
161 // This code which presumes the obstacle is spherical 154 // This code which presumes the obstacle is spherical
162 findNextIntersectionWithSphere(o, next, minDistanceToCollision); 155 findNextIntersectionWithSphere(o, next);
163 156
164 if (!nearest.intersect || (next.intersect && next.distance < nearest.distance)) { 157 if (!nearest.intersect || (next.intersect && next.distance < nearest.distance)) {
165 nearest = next; 158 nearest = next;
166 } 159 }
167 } 160 }
168 161
169 // when a nearest intersection was found 162 // when a nearest intersection was found
170 if (nearest.intersect && (nearest.distance < minDistanceToCollision)) { 163 if (nearest.intersect && (nearest.distance < minDistanceToCollision)) {
171 Stdout("Distance: ")(nearest.distance).newline;
172 // compute avoidance steering force: take offset from obstacle to me, 164 // compute avoidance steering force: take offset from obstacle to me,
173 // take the component of that which is lateral (perpendicular to my 165 // take the component of that which is lateral (perpendicular to my
174 // forward direction), set length to maxForce, add a bit of forward 166 // forward direction), set length to maxForce, add a bit of forward
175 // component (in capture the flag, we never want to slow down) 167 // component (in capture the flag, we never want to slow down)
176 bzVec2 offset = m_position - nearest.obstacle.position; 168 bzVec2 offset = m_position - nearest.obstacle.position;
177 avoidance = perpendicularComponent(offset, m_forward); 169 avoidance = perpendicularComponent(offset, m_forward);
178 avoidance.normalize; 170 avoidance.normalize;
179 //avoidance *= m_maxForce; 171 avoidance = m_body.localPoint(avoidance);
172 ///avoidance *= m_maxForce;
180 //avoidance += m_forward * m_maxForce * 0.75f; 173 //avoidance += m_forward * m_maxForce * 0.75f;
181 } 174 }
182 175
176 auto state = cast(State) m_body.userData;
177 state.avoid = avoidance;
183 return avoidance; 178 return avoidance;
184 } 179 }
185 180
186 bzVec2 avoid(float minTimeToCollision, bzBody obstacles) { 181 bzVec2 avoid(float minTimeToCollision, bzBody obstacles) {
187 182
199 bzVec2 movementNormal = m_velocity; 194 bzVec2 movementNormal = m_velocity;
200 movementNormal.normalize(); 195 movementNormal.normalize();
201 bzVec2 characterToObstacle = o.position - m_position; 196 bzVec2 characterToObstacle = o.position - m_position;
202 197
203 real distanceSquared = bzDot(characterToObstacle, movementNormal); 198 real distanceSquared = bzDot(characterToObstacle, movementNormal);
204 distanceSquared = characterToObstacle.length - 199 distanceSquared = characterToObstacle.lengthSquared - distanceSquared*distanceSquared;
205 distanceSquared*distanceSquared;
206 200
207 // Check for collision 201 // Check for collision
208 // Find radius of obstacle
209 float oRad = 0; 202 float oRad = 0;
210 for (bzShape shape = o.shapeList; shape; shape = shape.next) { 203 for (bzShape s = o.shapeList; s; s = s.next) {
211 if(shape.sweepRadius > oRad) { 204 if(s.sweepRadius > oRad) {
212 oRad = shape.sweepRadius; 205 oRad = s.sweepRadius;
213 } 206 }
214 } 207 }
215 208
216 real radius = oRad + avoidMargin; 209 real radius = oRad + avoidMargin;
217 if (distanceSquared < radius*radius) 210 if (distanceSquared < radius*radius)
221 214
222 // Make sure this isn't behind us and is closer than our lookahead. 215 // Make sure this isn't behind us and is closer than our lookahead.
223 if (distanceToClosest > 0 && distanceToClosest < maxLookahead) 216 if (distanceToClosest > 0 && distanceToClosest < maxLookahead)
224 { 217 {
225 // Find the closest point 218 // Find the closest point
226 bzVec2 closestPoint = 219 bzVec2 closestPoint = o.position + movementNormal * distanceToClosest;
227 o.position + movementNormal*distanceToClosest;
228 220
229 // Find the point of avoidance 221 // Find the point of avoidance
230 bzVec2 target = 222 bzVec2 target = o.position + (closestPoint - o.position).length * radius;
231 o.position + 223
232 (closestPoint - o.position).length * 224 auto state = cast(State) m_body.userData;
233 (oRad + avoidMargin); 225 state.avoid = target;
234 226
235 return target; 227 return target;
236 } 228 }
237 } 229 }
238 } 230 }
239 } 231 }
232
233 auto state = cast(State) m_body.userData;
234 state.avoid = bzVec2.zeroVect;
235
240 return bzVec2.zeroVect; 236 return bzVec2.zeroVect;
241 237
242 } 238 }
243 239
244 void findNextIntersectionWithSphere(bzBody obs, 240 void findNextIntersectionWithSphere(bzBody obs,
245 inout PathIntersection intersection, float mdc) { 241 inout PathIntersection intersection) {
246 242
247 // This routine is based on the Paul Bourke's derivation in: 243 // This routine is based on the Paul Bourke's derivation in:
248 // Intersection of a Line and a Sphere (or circle) 244 // Intersection of a Line and a Sphere (or circle)
249 // http://www.swin.edu.au/astronomy/pbourke/geometry/sphereline/ 245 // http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/raysphere.c
250 246
251 float b, c, d, p, q, s; 247 float b, c, d, p, q, s;
252 bzVec2 lc; 248 bzVec2 lc;
253 249
254 // initialize pathIntersection object 250 // initialize pathIntersection object
255 intersection.intersect = false; 251 intersection.intersect = false;
256 intersection.obstacle = obs; 252 intersection.obstacle = obs;
257 253
258 // find "local center" (lc) of sphere in boid's coordinate space 254 // find "local center" (lc) of sphere in coordinate space
259 lc = m_body.localPoint(obs.position); 255 lc = m_body.localPoint(obs.position);
260 256
261 // computer line-sphere intersection parameters 257 // computer line-sphere intersection parameters
262 b = 0; 258 b = 0;
263 259
267 if(shape.sweepRadius > obsRadius) { 263 if(shape.sweepRadius > obsRadius) {
268 obsRadius = shape.sweepRadius; 264 obsRadius = shape.sweepRadius;
269 } 265 }
270 } 266 }
271 267
272 c = square(lc.x) + square(lc.y) - square(obsRadius + m_radius+mdc); 268 c = square(lc.x) + square(lc.y) - square(obsRadius + m_radius);
273 d = (b * b) - (4 * c); 269 d = (b * b) - (4 * c);
274 270
275 // when the path does not intersect the sphere 271 // when the path does not intersect the sphere
276 if (d < 0) return; 272 if (d < 0) return;
277 273