Mercurial > projects > openmelee
annotate steer.d @ 11:d998bf1b0654
Added utilities and AI; fixed steer
author | Mason Green <mason.green@gmail.com> |
---|---|
date | Sun, 22 Mar 2009 09:35:24 -0400 |
parents | 5b61327b5a7c |
children | 2ecd16840900 |
rev | line source |
---|---|
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
1 /* |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
2 * Copyright (c) 2009, Mason Green (zzzzrrr) |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
3 * http://www.dsource.org/projects/openmelee |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
4 * Based on OpenSteer, Copyright (c) 2002-2003, Sony Computer Entertainment America |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
5 * Original author: Craig Reynolds |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
6 * |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
7 * All rights reserved. |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
8 * |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
9 * Redistribution and use in source and binary forms, with or without modification, |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
10 * are permitted provided that the following conditions are met: |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
11 * |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
12 * * Redistributions of source code must retain the above copyright notice, |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
13 * this list of conditions and the following disclaimer. |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
14 * * Redistributions in binary form must reproduce the above copyright notice, |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
15 * this list of conditions and the following disclaimer in the documentation |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
16 * and/or other materials provided with the distribution. |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
17 * * Neither the name of the polygonal nor the names of its contributors may be |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
18 * used to endorse or promote products derived from this software without specific |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
19 * prior written permission. |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
20 * |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
32 */ |
2 | 33 module openmelee.steer; |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
34 |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
35 import blaze.common.bzMath: bzDot, bzClamp, bzVec2; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
36 import openmelee.ship : Ship, State; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
37 import openmelee.utilities; |
0 | 38 |
9 | 39 class Steer |
40 { | |
41 // Constructor: initializes state | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
42 this (Ship ship) |
0 | 43 { |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
44 m_ship = ship; |
9 | 45 } |
0 | 46 |
9 | 47 // reset state |
48 void reset () { | |
49 // initial state of wander behavior | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
50 m_wanderSide = 0; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
51 m_wanderUp = 0; |
9 | 52 } |
53 | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
54 void update() { |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
55 m_position = m_ship.state.position; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
56 m_velocity = m_ship.state.velocity; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
57 m_speed = m_ship.state.speed; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
58 m_maxForce = m_ship.state.maxForce; |
9 | 59 } |
0 | 60 |
9 | 61 // -------------------------------------------------- steering behaviors |
0 | 62 |
9 | 63 bzVec2 steerForWander (float dt) { |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
64 // random walk m_wanderSide and m_wanderUp between -1 and +1 |
9 | 65 float speed = 12 * dt; // maybe this (12) should be an argument? |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
66 m_wanderSide = scalarRandomWalk (m_wanderSide, speed, -1, +1); |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
67 m_wanderUp = scalarRandomWalk (m_wanderUp, speed, -1, +1); |
0 | 68 |
9 | 69 // return a pure lateral steering vector: (+/-Side) + (+/-Up) |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
70 return (m_side * m_wanderSide) + (m_up * m_wanderUp); |
9 | 71 } |
0 | 72 |
9 | 73 // Seek behavior |
74 bzVec2 steerForSeek (bzVec2 target) { | |
75 bzVec2 desiredVelocity = target - m_position; | |
76 return desiredVelocity - m_velocity; | |
77 } | |
0 | 78 |
9 | 79 // Flee behavior |
80 bzVec2 steerForFlee (bzVec2 target) { | |
81 bzVec2 desiredVelocity = m_position - target; | |
82 return desiredVelocity - m_velocity; | |
83 } | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
84 |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
85 /* |
9 | 86 // xxx proposed, experimental new seek/flee [cwr 9-16-02] |
87 bzVec2 xxxsteerForFlee (bzVec2 target) { | |
88 bzVec2 offset = m_position - target; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
89 bzVec2 desiredVelocity = bzClamp(offset.truncateLength (maxSpeed ()); |
9 | 90 return desiredVelocity - m_velocity; |
91 } | |
0 | 92 |
9 | 93 bzVec2 xxxsteerForSeek (bzVec2 target) { |
94 // bzVec2 offset = target - position; | |
95 bzVec2 offset = target - m_position; | |
96 bzVec2 desiredVelocity = offset.truncateLength (maxSpeed ()); //xxxnew | |
97 return desiredVelocity - m_velocity; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
98 } |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
99 */ |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
100 |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
101 /* |
9 | 102 // ------------------------------------------------------------------------ |
103 // Obstacle Avoidance behavior | |
104 // | |
105 // Returns a steering force to avoid a given obstacle. The purely | |
106 // lateral steering force will turn our vehicle towards a silhouette edge | |
107 // of the obstacle. Avoidance is required when (1) the obstacle | |
108 // intersects the vehicle's current path, (2) it is in front of the | |
109 // vehicle, and (3) is within minTimeToCollision seconds of travel at the | |
110 // vehicle's current velocity. Returns a zero vector value (bzVec2::zero) | |
111 // when no avoidance is required. | |
112 bzVec2 steerToAvoidObstacle (float minTimeToCollision, Obstacle obstacle) { | |
0 | 113 |
9 | 114 bzVec2 avoidance = obstacle.steerToAvoid (this, minTimeToCollision); |
115 return avoidance; | |
116 } | |
117 | |
118 // avoids all obstacles in an ObstacleGroup | |
0 | 119 |
9 | 120 bzVec2 steerToAvoidObstacles (float minTimeToCollision, |
121 ObstacleGroup obstacles) { | |
0 | 122 |
9 | 123 bzVec2 avoidance; |
124 PathIntersection nearest, next; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
125 float minDistanceToCollision = minTimeToCollision * speed; |
0 | 126 |
9 | 127 next.intersect = false; |
128 nearest.intersect = false; | |
0 | 129 |
9 | 130 // test all obstacles for intersection with my forward axis, |
131 // select the one whose point of intersection is nearest | |
132 for (ObstacleIterator o = obstacles.begin(); o != obstacles.end(); o++) | |
133 { | |
134 // xxx this should be a generic call on Obstacle, rather than | |
135 // xxx this code which presumes the obstacle is spherical | |
136 findNextIntersectionWithSphere ((SphericalObstacle)**o, next); | |
0 | 137 |
9 | 138 if ((nearest.intersect == false) || |
139 ((next.intersect != false) | |
140 (next.distance < nearest.distance))) | |
141 nearest = next; | |
142 } | |
0 | 143 |
9 | 144 // when a nearest intersection was found |
145 if ((nearest.intersect != false) | |
146 (nearest.distance < minDistanceToCollision)) | |
147 { | |
148 // show the corridor that was checked for collisions | |
149 annotateAvoidObstacle (minDistanceToCollision); | |
0 | 150 |
9 | 151 // compute avoidance steering force: take offset from obstacle to me, |
152 // take the component of that which is lateral (perpendicular to my | |
153 // forward direction), set length to maxForce, add a bit of forward | |
154 // component (in capture the flag, we never want to slow down) | |
155 bzVec2 offset = m_position - nearest.obstacle.center; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
156 avoidance = offset.perpendicularComponent (m_forward()); |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
157 avoidance = avoidance.normalize; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
158 avoidance *= maxForce; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
159 avoidance += m_forward * maxForce * 0.75; |
0 | 160 } |
161 | |
9 | 162 return avoidance; |
163 } | |
164 | |
165 // ------------------------------------------------------------------------ | |
166 // Unaligned collision avoidance behavior: avoid colliding with other | |
167 // nearby vehicles moving in unconstrained directions. Determine which | |
168 // (if any) other other vehicle we would collide with first, then steers | |
169 // to avoid the site of that potential collision. Returns a steering | |
170 // force vector, which is zero length if there is no impending collision. | |
171 | |
172 bzVec2 steerToAvoidNeighbors (float minTimeToCollision, AVGroup others) { | |
0 | 173 |
9 | 174 // first priority is to prevent immediate interpenetration |
175 bzVec2 separation = steerToAvoidCloseNeighbors (0, others); | |
176 if (separation != bzVec2::zero) return separation; | |
0 | 177 |
9 | 178 // otherwise, go on to consider potential future collisions |
179 float steer = 0; | |
180 Ship* threat = NULL; | |
181 | |
182 // Time (in seconds) until the most immediate collision threat found | |
183 // so far. Initial value is a threshold: don't look more than this | |
184 // many frames into the future. | |
185 float minTime = minTimeToCollision; | |
0 | 186 |
9 | 187 // xxx solely for annotation |
188 bzVec2 xxxThreatPositionAtNearestApproach; | |
189 bzVec2 xxxOurPositionAtNearestApproach; | |
0 | 190 |
9 | 191 // for each of the other vehicles, determine which (if any) |
192 // pose the most immediate threat of collision. | |
193 for (AVIterator i = others.begin(); i != others.end(); i++) | |
194 { | |
195 Ship other = **i; | |
196 if (other != this) | |
0 | 197 { |
9 | 198 // avoid when future positions are this close (or less) |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
199 float collisionDangerThreshold = radius * 2; |
9 | 200 |
201 // predicted time until nearest approach of "this" and "other" | |
202 float time = predictNearestApproachTime (other); | |
0 | 203 |
9 | 204 // If the time is in the future, sooner than any other |
205 // threatened collision... | |
206 if ((time >= 0) (time < minTime)) | |
207 { | |
208 // if the two will be close enough to collide, | |
209 // make a note of it | |
210 if (computeNearestApproachPositions (other, time) | |
211 < collisionDangerThreshold) | |
0 | 212 { |
9 | 213 minTime = time; |
214 threat = other; | |
215 xxxThreatPositionAtNearestApproach | |
216 = hisPositionAtNearestApproach; | |
217 xxxOurPositionAtNearestApproach | |
218 = ourPositionAtNearestApproach; | |
0 | 219 } |
220 } | |
221 } | |
9 | 222 } |
0 | 223 |
9 | 224 // if a potential collision was found, compute steering to avoid |
225 if (threat) | |
226 { | |
227 // parallel: +1, perpendicular: 0, anti-parallel: -1 | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
228 float parallelness = m_forward.dot(threat.forward); |
9 | 229 float angle = 0.707f; |
230 | |
231 if (parallelness < -angle) | |
0 | 232 { |
9 | 233 // anti-parallel "head on" paths: |
234 // steer away from future threat position | |
235 bzVec2 offset = xxxThreatPositionAtNearestApproach - m_position; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
236 float sideDot = offset.dot(m_side()); |
9 | 237 steer = (sideDot > 0) ? -1.0f : 1.0f; |
238 } | |
239 else | |
240 { | |
241 if (parallelness > angle) | |
0 | 242 { |
9 | 243 // parallel paths: steer away from threat |
244 bzVec2 offset = threat.position - m_position; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
245 float sideDot = bzDot(offset, m_side); |
0 | 246 steer = (sideDot > 0) ? -1.0f : 1.0f; |
247 } | |
248 else | |
249 { | |
9 | 250 // perpendicular paths: steer behind threat |
251 // (only the slower of the two does this) | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
252 if (threat.speed() <= speed) |
0 | 253 { |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
254 float sideDot = bzDot(m_side, threat.velocity); |
0 | 255 steer = (sideDot > 0) ? -1.0f : 1.0f; |
256 } | |
257 } | |
258 } | |
259 } | |
260 | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
261 return m_side() * steer; |
9 | 262 } |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
263 */ |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
264 |
9 | 265 // Given two vehicles, based on their current positions and velocities, |
266 // determine the time until nearest approach | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
267 float predictNearestApproachTime (State other) { |
9 | 268 |
269 // imagine we are at the origin with no velocity, | |
270 // compute the relative velocity of the other vehicle | |
271 bzVec2 myVelocity = m_velocity; | |
272 bzVec2 otherVelocity = other.velocity; | |
273 bzVec2 relVelocity = otherVelocity - myVelocity; | |
274 float relSpeed = relVelocity.length; | |
275 | |
276 // for parallel paths, the vehicles will always be at the same distance, | |
277 // so return 0 (aka "now") since "there is no time like the present" | |
278 if (relSpeed == 0) return 0; | |
279 | |
280 // Now consider the path of the other vehicle in this relative | |
281 // space, a line defined by the relative position and velocity. | |
282 // The distance from the origin (our vehicle) to that line is | |
283 // the nearest approach. | |
284 | |
285 // Take the unit tangent along the other vehicle's path | |
286 bzVec2 relTangent = relVelocity / relSpeed; | |
287 | |
288 // find distance from its path to origin (compute offset from | |
289 // other to us, find length of projection onto path) | |
290 bzVec2 relPosition = m_position - other.position; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
291 float projection = bzDot(relTangent, relPosition); |
9 | 292 |
293 return projection / relSpeed; | |
294 } | |
0 | 295 |
9 | 296 // Given the time until nearest approach (predictNearestApproachTime) |
297 // determine position of each vehicle at that time, and the distance | |
298 // between them | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
299 float computeNearestApproachPositions (State other, float time) { |
0 | 300 |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
301 bzVec2 myTravel = m_forward * m_speed * time; |
9 | 302 bzVec2 otherTravel = other.forward * other.speed * time; |
303 | |
304 bzVec2 myFinal = m_position + myTravel; | |
305 bzVec2 otherFinal = other.position + otherTravel; | |
0 | 306 |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
307 return (myFinal - otherFinal).length; |
9 | 308 } |
309 | |
310 // ------------------------------------------------------------------------ | |
311 // pursuit of another vehicle ( version with ceiling on prediction time) | |
312 | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
313 bzVec2 steerForPursuit (State quarry) { |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
314 return steerForPursuit (quarry, float.max); |
9 | 315 } |
316 | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
317 bzVec2 steerForPursuit (State quarry, float maxPredictionTime) { |
0 | 318 |
9 | 319 // offset from this to quarry, that distance, unit vector toward quarry |
320 bzVec2 offset = quarry.position - m_position; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
321 float distance = offset.length; |
9 | 322 bzVec2 unitOffset = offset / distance; |
323 | |
324 // how parallel are the paths of "this" and the quarry | |
325 // (1 means parallel, 0 is pependicular, -1 is anti-parallel) | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
326 float parallelness = bzDot(m_forward , quarry.forward); |
9 | 327 |
328 // how "forward" is the direction to the quarry | |
329 // (1 means dead ahead, 0 is directly to the side, -1 is straight back) | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
330 float forwardness = bzDot(m_forward , unitOffset); |
0 | 331 |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
332 float directTravelTime = distance / m_speed; |
9 | 333 int f = intervalComparison (forwardness, -0.707f, 0.707f); |
334 int p = intervalComparison (parallelness, -0.707f, 0.707f); | |
335 | |
336 float timeFactor = 0; // to be filled in below | |
0 | 337 |
9 | 338 // Break the pursuit into nine cases, the cross product of the |
339 // quarry being [ahead, aside, or behind] us and heading | |
340 // [parallel, perpendicular, or anti-parallel] to us. | |
341 switch (f) | |
342 { | |
343 case +1: | |
344 switch (p) | |
0 | 345 { |
9 | 346 case +1: // ahead, parallel |
347 timeFactor = 4; | |
0 | 348 break; |
9 | 349 case 0: // ahead, perpendicular |
350 timeFactor = 1.8f; | |
0 | 351 break; |
9 | 352 case -1: // ahead, anti-parallel |
353 timeFactor = 0.85f; | |
0 | 354 break; |
355 } | |
9 | 356 break; |
357 case 0: | |
358 switch (p) | |
359 { | |
360 case +1: // aside, parallel | |
361 timeFactor = 1; | |
362 break; | |
363 case 0: // aside, perpendicular | |
364 timeFactor = 0.8f; | |
365 break; | |
366 case -1: // aside, anti-parallel | |
367 timeFactor = 4; | |
368 break; | |
369 } | |
370 break; | |
371 case -1: | |
372 switch (p) | |
373 { | |
374 case +1: // behind, parallel | |
375 timeFactor = 0.5f; | |
376 break; | |
377 case 0: // behind, perpendicular | |
378 timeFactor = 2; | |
379 break; | |
380 case -1: // behind, anti-parallel | |
381 timeFactor = 2; | |
382 break; | |
383 } | |
384 break; | |
385 } | |
0 | 386 |
9 | 387 // estimated time until intercept of quarry |
388 float et = directTravelTime * timeFactor; | |
389 | |
390 // xxx experiment, if kept, this limit should be an argument | |
391 float etl = (et > maxPredictionTime) ? maxPredictionTime : et; | |
392 | |
393 // estimated position of quarry at intercept | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
394 bzVec2 target = quarry.predictFuturePosition(etl); |
0 | 395 |
9 | 396 return steerForSeek (target); |
397 } | |
398 | |
399 // ------------------------------------------------------------------------ | |
400 // evasion of another vehicle | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
401 bzVec2 steerForEvasion (State menace, float maxPredictionTime) { |
0 | 402 |
9 | 403 // offset from this to menace, that distance, unit vector toward menace |
404 bzVec2 offset = menace.position - m_position; | |
405 float distance = offset.length; | |
0 | 406 |
9 | 407 float roughTime = distance / menace.speed; |
408 float predictionTime = ((roughTime > maxPredictionTime) ? maxPredictionTime : roughTime); | |
409 bzVec2 target = menace.predictFuturePosition (predictionTime); | |
410 | |
411 return steerForFlee (target); | |
412 } | |
0 | 413 |
414 | |
9 | 415 // ------------------------------------------------------------------------ |
416 // tries to maintain a given speed, returns a maxForce-clipped steering | |
417 // force along the forward/backward axis | |
418 bzVec2 steerForTargetSpeed (float targetSpeed) { | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
419 float mf = m_maxForce; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
420 float speedError = targetSpeed - m_speed; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
421 return m_forward * bzClamp(speedError, -mf, +mf); |
9 | 422 } |
0 | 423 |
424 | |
9 | 425 // ----------------------------------------------------------- utilities |
426 bool isAhead (bzVec2 target) {return isAhead (target, 0.707f);}; | |
427 bool isAside (bzVec2 target) {return isAside (target, 0.707f);}; | |
428 bool isBehind (bzVec2 target) {return isBehind (target, -0.707f);}; | |
0 | 429 |
9 | 430 bool isAhead (bzVec2 target, float cosThreshold) |
431 { | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
432 bzVec2 targetDirection = target - m_position; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
433 targetDirection.normalize(); |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
434 return bzDot(m_forward, targetDirection) > cosThreshold; |
9 | 435 } |
0 | 436 |
9 | 437 bool isAside (bzVec2 target, float cosThreshold) |
438 { | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
439 bzVec2 targetDirection = target - m_position; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
440 targetDirection.normalize(); |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
441 float dp = bzDot(m_forward, targetDirection); |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
442 return (dp < cosThreshold) && (dp > -cosThreshold); |
9 | 443 } |
0 | 444 |
9 | 445 bool isBehind (bzVec2 target, float cosThreshold) |
446 { | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
447 bzVec2 targetDirection = target - m_position; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
448 targetDirection.normalize(); |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
449 return bzDot(m_forward, targetDirection) < cosThreshold; |
9 | 450 } |
451 | |
452 private: | |
453 | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
454 Ship m_ship; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
455 |
9 | 456 bzVec2 m_position; |
457 bzVec2 m_velocity; | |
11
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
458 bzVec2 m_up; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
459 bzVec2 m_side; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
460 bzVec2 m_forward; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
461 |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
462 float m_speed = 0; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
463 float m_maxForce = 0; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
464 |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
465 // Wander behavior |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
466 float m_wanderSide; |
d998bf1b0654
Added utilities and AI; fixed steer
Mason Green <mason.green@gmail.com>
parents:
9
diff
changeset
|
467 float m_wanderUp; |
9 | 468 } |