(cross-posting with Box2D forum)
Hi Forum, I've written a hockey goalie-style intercept code to move an opponent ai toward the target ball. It works on screen right, but does very badly on screen left. I think my prediction or motion code is wrong. It looks like predictedLocation is ok, but the transformations into opponent movements might be bad.
The calculations are in Box2d and OpenGL coordinates, and an atlasSprite is attached to the physics body as userData.
I'd like to ask the mathematically more talented amongst us for an opinion, if the calculations look correct?
Might Box2D already have a 'look-ahead' calculation function built in?
This is condensed from several functions to focus on the movement math:
-(void) updateOpponent
{
// initialize modifiers
float32 vectRange = NULL;
float32 vectClose = NULL;
float32 timeToClose = NULL;
b2Vec2 rangeToClose;
b2Vec2 closingVeloc;
b2Vec2 predictedLocation;
// init moving target
b2Vec2 targetPos = [self theTarget]->GetWorldCenter();
b2Vec2 targetVeloc = [self theTarget]->GetLinearVelocity();
// init opponent
b2Vec2 opponentPos = [self opponent]->GetWorldCenter();
b2Vec2 opponentVeloc = [self opponent]->GetLinearVelocity();
// Tier One - prediction
// check for target movement first before using function
if(targetVeloc.x != 0 && targetVeloc.y != 0) {
rangeToClose = targetPos - opponentPos;
closingVeloc = targetVeloc - opponentVeloc;
// calculate magnitude
vectRange = sqrt((rangeToClose.x * rangeToClose.x) + (rangeToClose.y * rangeToClose.y));
vectClose = sqrt((closingVeloc.x * closingVeloc.x) + (closingVeloc.y * closingVeloc.y));
// calculate time to close
timeToClose = vectRange / vectClose;
// projected location of target
predictedLocation = targetPos + b2Vec2((targetVeloc.x * timeToClose),(targetVeloc.y * timeToClose));
CCLOG(@"predicted target position is %f, %f",predictedLocation.x, predictedLocation.y);
}
// calculate opponent move
// kTagAttack
if(predictedLocation.y <= opponentPos.y) {
// go forward
reverseMod = -(predictLoc.y);
} else {
// retreat to defensive position
// kTagDefense
}
if(predictLoc.x >= opponentPos.x) {
// go right - mod X vector
lateralMod = predictLoc.x; // this works very well consistently
} else {
// go left - mod X vector
lateralMod = -(predictLoc.x); // is this correct for moving to screen left?
}
//final modified predictedLocation:
b2Vec2 opponentVector = b2Vec2 (lateralMod,reverseMod);
// move opponent piece to intercept target
if (currentOpponentState == ktagAttack) {
// intend to hit and push target with force
// normalise
opponentVector.Normalize();
opponentVector.x = opponentVector.x * (op->GetMass() * 0.86f); // tweak position
opponentVector.y = opponentVector.y * (op->GetMass() * 1.1f); // tweak position
[self opponent]->SetLinearVelocity(velocVect);
CCLOG(@"moving opponent with setLinearVelocity);
} else if (currentOpponentState == kTagDefend) {
// intend to guard goal
//CCLOG(@"moving opponent with ApplyImpulse");
opponentVector.x = opponentVector.x * (op->GetMass() *20.0f); // tweak speed
opponentVector.y = opponentVector.y * (op->GetMass() *40.0f); // tweak speed
[self opponent]->ApplyForce(velocVect, [self opponent]->GetWorldCenter());
}
}
Thank you.