Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 13, 2009, 5:05:17 PM (15 years ago)
Author:
dafrick
Message:

Hopefully merged trunk successfully into pickup branch.

Location:
code/branches/pickup
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/pickup

  • code/branches/pickup/src/modules/pong/PongAI.cc

    r5781 r5935  
    4949        this->ballEndPosition_ = 0;
    5050        this->randomOffset_ = 0;
     51        this->bChangedRandomOffset_ = false;
    5152        this->relHysteresisOffset_ = 0.02f;
    5253        this->strength_ = 0.5f;
     
    6061    PongAI::~PongAI()
    6162    {
    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();
    6465    }
    6566
     
    113114                this->ballEndPosition_ = 0;
    114115                this->randomOffset_ = 0;
     116                this->bChangedRandomOffset_ = false;
    115117
    116118                this->calculateRandomOffset();
     
    129131                this->bOscillationAvoidanceActive_ = false;
    130132            }
     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            }
    131145
    132146            // Move to the predicted end position with an additional offset (to hit the ball with the side of the bat)
     
    184198        Vector3 position = this->ball_->getPosition();
    185199        Vector3 velocity = this->ball_->getVelocity();
     200        Vector3 acceleration = this->ball_->getAcceleration();
    186201        Vector2 dimension = this->ball_->getFieldDimension();
    187202
    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            }
    213294        }
    214295    }
     
    231312
    232313            // 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));
    235316        }
    236317        else
     
    246327
    247328        // 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();
    250331
    251332        this->reactionTimers_.pop_front();
Note: See TracChangeset for help on using the changeset viewer.