I am looking for an elegant implementation of a program to point the
enemy's spaceship at the player's. I am using theta in degrees, but
could switch to radians if there is a good reason to do so. Any ideas?
The crux of the problem is figuring out which way is the shorter
rotation to match the theta to the other ship with the theta of the
direction in which the ship is pointing now.
This is the code that I have so far:
void Object::calcEnemyAI(Object& thePlayer)
{
// follow player
double deltaX, deltaY, thetaToPlayer;
deltaX = xpos - thePlayer.getXpos();
deltaY = ypos - thePlayer.getYpos();
thetaToPlayer = atan(deltaY/deltaX)*TODEGREES;
if(thetaToPlayer < 0) thetaToPlayer += 360;
if( abs(theta - thetaToPlayer) < 180 )
{
if(theta - thetaToPlayer > 0) // turn right
theta += TURNSPEED*3;
else if(theta - thetaToPlayer < 0) // turn left
theta -= TURNSPEED*3;
}
else if( abs(theta - thetaToPlayer) > 180 )
{
if(theta - thetaToPlayer < 0) // turn right
theta += TURNSPEED*3;
else if(theta - thetaToPlayer > 0) // turn left
theta -= TURNSPEED*3;
}
else // exactly behind you- just turn one way- in this case
right
theta += TURNSPEED*3;
}
I also tried this:
ENEMYACTION Object::calcEnemyAI(Object& thePlayer)
{
// follow player
double deltaX, deltaY, thetaToPlayer;
deltaX = xpos - thePlayer.getXpos();
deltaY = ypos - thePlayer.getYpos();
thetaToPlayer = atan(deltaY/deltaX)*TODEGREES;
if(thetaToPlayer < 0) thetaToPlayer += 360;
bool rightDone = false;
bool leftDone = false;
int countLeft=0, countRight=0;
int thetaRight = (int)theta;
int thetaLeft = (int)theta;
while(!rightDone || !leftDone)
{
if( (int)thetaToPlayer == thetaRight ) rightDone = true;
else
{
thetaRight--;
countRight++;
if(thetaRight == -1) thetaRight = 359;
}
if( (int)thetaToPlayer == thetaLeft ) leftDone = true;
else
{
thetaLeft++;
countLeft++;
if(thetaLeft == 360) thetaLeft = 0;
}
}
if(deltaX < 0)
{
if(countLeft >= countRight)
theta -= TURNSPEED*3;
else if(countLeft < countRight)
theta += TURNSPEED*3;
}
else
{
if(countLeft >= countRight)
theta += TURNSPEED*3;
else if(countLeft < countRight)
theta -= TURNSPEED*3;
}
if(calcHypotenuse(deltaX, deltaY) < 200 && abs(theta - thetaToPlayer)
< 10)
return FIRE1;
return NIL;
}
The second one basically counts up the degrees in each direction and it
chooses the shorter count. Both of these implementations are ugly, I
know, and at this point the first doesn't even work quite right.
Sometimes
the ship points its butt at the player's ship and other times its nose.
I think it depends on which quadrant the player's ship is in, in
referrence to it. Probably having to do with the signs for tangent are
positive in quadrants I, III. I haven't bothered to work it out yet,
because I wanted to see if there were any suggestions on a cleaner
approach. theta, xpos, ypos are all member variables of the Object
class and therefore accessible by these functions.
Scott I
ps the ships being round is cute, but not an option... ;)


|