Changeset 5935 for code/branches/pickup/src/modules/pong/PongAI.cc
- Timestamp:
- Oct 13, 2009, 5:05:17 PM (15 years ago)
- Location:
- code/branches/pickup
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/pickup
- Property svn:mergeinfo changed
-
code/branches/pickup/src/modules/pong/PongAI.cc
r5781 r5935 49 49 this->ballEndPosition_ = 0; 50 50 this->randomOffset_ = 0; 51 this->bChangedRandomOffset_ = false; 51 52 this->relHysteresisOffset_ = 0.02f; 52 53 this->strength_ = 0.5f; … … 60 61 PongAI::~PongAI() 61 62 { 62 for (std::list<std::pair<Timer <PongAI>*, char> >::iterator it = this->reactionTimers_.begin(); it != this->reactionTimers_.end(); ++it)63 delete (*it).first;63 for (std::list<std::pair<Timer*, char> >::iterator it = this->reactionTimers_.begin(); it != this->reactionTimers_.end(); ++it) 64 (*it).first->destroy(); 64 65 } 65 66 … … 113 114 this->ballEndPosition_ = 0; 114 115 this->randomOffset_ = 0; 116 this->bChangedRandomOffset_ = false; 115 117 116 118 this->calculateRandomOffset(); … … 129 131 this->bOscillationAvoidanceActive_ = false; 130 132 } 133 134 // If the ball is close enough, calculate another random offset to accelerate the ball 135 if (!this->bChangedRandomOffset_) 136 { 137 float timetohit = (-this->ball_->getPosition().x + this->ball_->getFieldDimension().x / 2 * sgn(this->ball_->getVelocity().x)) / this->ball_->getVelocity().x; 138 if (timetohit < 0.05) 139 { 140 this->bChangedRandomOffset_ = true; 141 if (rnd() < this->strength_) 142 this->calculateRandomOffset(); 143 } 144 } 131 145 132 146 // Move to the predicted end position with an additional offset (to hit the ball with the side of the bat) … … 184 198 Vector3 position = this->ball_->getPosition(); 185 199 Vector3 velocity = this->ball_->getVelocity(); 200 Vector3 acceleration = this->ball_->getAcceleration(); 186 201 Vector2 dimension = this->ball_->getFieldDimension(); 187 202 188 // calculate end-height: current height + slope * distance 189 this->ballEndPosition_ = position.z + velocity.z / velocity.x * (-position.x + dimension.x / 2 * sgn(velocity.x)); 190 191 // Calculate bounces 192 for (float limit = 0.35f; limit < this->strength_ || this->strength_ > 0.99f; limit += 0.4f) 193 { 194 // Calculate a random prediction error, based on the vertical speed of the ball and the strength of the AI 195 float randomError = rnd(-1, 1) * dimension.y * (velocity.z / velocity.x / PongBall::MAX_REL_Z_VELOCITY) * (1 - this->strength_); 196 197 // Bounce from the lower bound 198 if (this->ballEndPosition_ > dimension.y / 2) 199 { 200 // Mirror the predicted position at the upper bound and add some random error 201 this->ballEndPosition_ = dimension.y - this->ballEndPosition_ + randomError; 202 continue; 203 } 204 // Bounce from the upper bound 205 if (this->ballEndPosition_ < -dimension.y / 2) 206 { 207 // Mirror the predicted position at the lower bound and add some random error 208 this->ballEndPosition_ = -dimension.y - this->ballEndPosition_ + randomError; 209 continue; 210 } 211 // No bounce - break 212 break; 203 // Calculate bounces. The number of predicted bounces is limited by the AIs strength 204 for (float limit = -0.05f; limit < this->strength_ || this->strength_ > 0.99f; limit += 0.4f) 205 { 206 // calculate the time until the ball reaches the other side 207 float totaltime = (-position.x + dimension.x / 2 * sgn(velocity.x)) / velocity.x; 208 209 // calculate wall bounce position (four possible solutions of the equation: pos.z + vel.z*t + acc.z/2*t^2 = +/- dim.z/2) 210 float bouncetime = totaltime; 211 bool bUpperWall = false; 212 213 if (acceleration.z == 0) 214 { 215 if (velocity.z > 0) 216 { 217 bUpperWall = true; 218 bouncetime = (dimension.y/2 - position.z) / velocity.z; 219 } 220 else if (velocity.z < 0) 221 { 222 bUpperWall = false; 223 bouncetime = (-dimension.y/2 - position.z) / velocity.z; 224 } 225 } 226 else 227 { 228 // upper wall 229 float temp = velocity.z*velocity.z + 2*acceleration.z*(dimension.y/2 - position.z); 230 if (temp >= 0) 231 { 232 float t1 = (sqrt(temp) - velocity.z) / acceleration.z; 233 float t2 = (sqrt(temp) + velocity.z) / acceleration.z * (-1); 234 if (t1 > 0 && t1 < bouncetime) 235 { 236 bouncetime = t1; 237 bUpperWall = true; 238 } 239 if (t2 > 0 && t2 < bouncetime) 240 { 241 bouncetime = t2; 242 bUpperWall = true; 243 } 244 } 245 // lower wall 246 temp = velocity.z*velocity.z - 2*acceleration.z*(dimension.y/2 + position.z); 247 if (temp >= 0) 248 { 249 float t1 = (sqrt(temp) - velocity.z) / acceleration.z; 250 float t2 = (sqrt(temp) + velocity.z) / acceleration.z * (-1); 251 if (t1 > 0 && t1 < bouncetime) 252 { 253 bouncetime = t1; 254 bUpperWall = false; 255 } 256 if (t2 > 0 && t2 < bouncetime) 257 { 258 bouncetime = t2; 259 bUpperWall = false; 260 } 261 } 262 } 263 264 if (bouncetime < totaltime) 265 { 266 // Calculate a random prediction error, based on the vertical speed of the ball and the strength of the AI 267 float randomErrorX = rnd(-1, 1) * dimension.y * (velocity.z / velocity.x / PongBall::MAX_REL_Z_VELOCITY) * (1 - this->strength_); 268 float randomErrorZ = rnd(-1, 1) * dimension.y * (velocity.z / velocity.x / PongBall::MAX_REL_Z_VELOCITY) * (1 - this->strength_); 269 270 // ball bounces after <bouncetime> seconds, update the position and continue 271 velocity.z = velocity.z + acceleration.z * bouncetime; 272 273 if (bUpperWall) 274 { 275 position.z = dimension.y / 2; 276 velocity.z = -fabs(velocity.z) + fabs(randomErrorZ); 277 } 278 else 279 { 280 position.z = -dimension.y / 2; 281 velocity.z = fabs(velocity.z) - fabs(randomErrorZ); 282 } 283 284 position.x = position.x + velocity.x * bouncetime + randomErrorX; 285 this->ballEndPosition_ = position.z; 286 } 287 else 288 { 289 // ball doesn't bounce, calculate the end position and return 290 // calculate end-height: current height + slope * distance incl. acceleration 291 this->ballEndPosition_ = position.z + velocity.z * totaltime + acceleration.z / 2 * totaltime * totaltime; 292 return; 293 } 213 294 } 214 295 } … … 231 312 232 313 // Add a new Timer 233 Timer <PongAI>* timer = new Timer<PongAI>(delay, false, this, createExecutor(createFunctor(&PongAI::delayedMove)));234 this->reactionTimers_.push_back(std::pair<Timer <PongAI>*, char>(timer, direction));314 Timer* timer = new Timer(delay, false, createExecutor(createFunctor(&PongAI::delayedMove, this))); 315 this->reactionTimers_.push_back(std::pair<Timer*, char>(timer, direction)); 235 316 } 236 317 else … … 246 327 247 328 // Destroy the timer and remove it from the list 248 Timer <PongAI>* timer = this->reactionTimers_.front().first;249 delete timer;329 Timer* timer = this->reactionTimers_.front().first; 330 timer->destroy(); 250 331 251 332 this->reactionTimers_.pop_front();
Note: See TracChangeset
for help on using the changeset viewer.