[SOLVED] rotate turret to aim at target

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
death_au
Posts: 38
Joined: Tue Apr 17, 2007 9:48 am
Location: Australia

[SOLVED] rotate turret to aim at target

Post by death_au »

This may seem like a simple problem to some, but I've been fiddling with it for a while and can't seem to nut it out properly. Basically, it's like this:
I have a turret made up of three scene nodes (turretBase, turretTop and turretGun). The base stays static and does not move. The top is parented to the base and rotates around the Y axis to point towards an enemy (usually the player). The gun just rotates around it's X-axis to aim up or down towards the enemy.
I've been mainly playing with rotating the top, but I can't seem to get it to pint at the player properly. I want it to turn smoothly, i.e. each time it is updated, it checks whether it has to turn left or right based on the enemy's position, and then does so.
There was a code snippet I found on the forums to rotate from one angle to another in the shortest direction, but I don't have the angles, and everything I try comes out wrong. I know there's a nice, simple solution, my brain just won't let me see it.

I have the turret's position, and I want to pass in a target position, then have the turret top begin to rotate towards that target.
Last edited by death_au on Wed Jul 04, 2007 1:39 am, edited 1 time in total.
Image
Andreas
Posts: 166
Joined: Sun Oct 31, 2004 7:15 am
Location: Münster / Germany
Contact:

Post by Andreas »

Hi,

you might want to have a look at www.sensobots.de/downloads.html and the Player.cpp from the source distribution. It is
not exactly what you want, but maybe helps anyway. I use three lines (2D from the centre of the screen) to keep track of
the normal, the current sight line and a target line. The code is basically:

Code: Select all

INITIAL SETUP:
------------------
[...]
// Setup lines for turret movement
vector2d<f32> pos(clientOptions->resolutionX/2, clientOptions->resolutionY/2);
vector2d<f32> normalEnd(clientOptions->resolutionX/2 -100, clientOptions->resolutionY/2);
        normalEnd.rotateBy(90, pos);
normal = line2d<f32>(pos, normalEnd);
sight = line2d<f32>(pos, normalEnd);
target = line2d<f32>(pos, normalEnd);


UPDATE EVERY FRAME:
---------------------------
[...]
// Next the turret rotation is computed. This is for now only done for the local player. Remote players
// send their turret rotation with shoot-Packets (see Constants.h->PACKET_BULLET)
float targetAngle = target.getVector().getAngle();
float sightAngle = sight.getVector().getAngle();
vector2d<f32> sightEndSaved = sight.end;

if (sightAngle - targetAngle < -1) {
        rotationAngle = -(sightAngle - targetAngle);
}
else if (sightAngle - targetAngle > 1) {
        rotationAngle = 360 - (sightAngle - targetAngle);
}
else {
        rotationAngle = 0;
}

[...]
// finally actually rotate the turret if everything went right:
if (rotationAngle != 0 && rotationAngle < 180) {
        matrix4 n, m;
        n.setRotationDegrees(vector3df(0,(-CL_DEFAULT_SPEED *10 * deltaTime),0));
        m = playerTopNode->getRelativeTransformation();
        m *= n;
        playerTopNode->setRotation( m.getRotationDegrees() );
}
else if (rotationAngle != 0) {
        matrix4 n, m;
        n.setRotationDegrees(vector3df(0,(CL_DEFAULT_SPEED *10 * deltaTime),0));
        m = playerTopNode->getRelativeTransformation();
        m *= n;
        playerTopNode->setRotation( m.getRotationDegrees() );
}


UPDATE IF TARGET (in my case the mouse pointer) MOVED:
---------------------------------------------------------------------
[...]
void Player::setMousePosition(int X, int Y) {
        target.end = vector2d<f32>(X, Y);
};
There is some code i didn't write because i block rotation at a certain degree. If someone finds an elegant way to handle
this, i would also be glad to hear about it. :)

so long,
Andreas
death_au
Posts: 38
Joined: Tue Apr 17, 2007 9:48 am
Location: Australia

Post by death_au »

You're right. Not exactly what I want, but it does help. The turret now seems to rotate (almost) correctly. I just have a few things to fix up, then I might post my code so that anyone with the same problem can see how I did it.
Thanks Andreas.
Image
Andreas
Posts: 166
Joined: Sun Oct 31, 2004 7:15 am
Location: Münster / Germany
Contact:

Post by Andreas »

No problem, i would be glad to see your solution. :)
death_au
Posts: 38
Joined: Tue Apr 17, 2007 9:48 am
Location: Australia

Post by death_au »

here's the code I used to rotate the turret around (this is only the rotation around the Y axis. The rotation of the gun would follow a similar principal)

Code: Select all

vector3df currentPos = turretTop->getAbsolutePosition();

line3df sight = line3df(currentPos, facingDirXZ);
line3df target = line3df(currentPos, targetPos);

f32 from = sight.getVector().getHorizontalAngle().Y;
f32 to = target.getVector().getHorizontalAngle().Y;

//The following code is taken from the "Rotate one angle to another by the shortest turn"
//code snipped on the irrlicht forums
//(http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=13357&highlight=normal+lower+inverse)

// Equal, do nothing
if(from==to) return;

// max and min
f32 max = max_<f32>(from, to);
f32 min = min_<f32>(from, to);

// Differences
f32 difN = max - min;
f32 difI = (360 - max) + min;

// If normal is lower than inverse
if( difN <= difI )
{
  if( from > to )
	 facingDirXZ.rotateXZBy(-speed,currentPos);
  else
	 facingDirXZ.rotateXZBy(speed,currentPos);
}
else
{
  if( from > to )
	 facingDirXZ.rotateXZBy(speed,currentPos);
  else
	 facingDirXZ.rotateXZBy(-speed,currentPos);
}

//do the rotation
turretTop->setRotation(vector3df(90.0f,0.0f,line3df(currentPos, facingDirXZ).getVector().getHorizontalAngle().Y));
Image
Post Reply