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.
[SOLVED] rotate turret to aim at target
[SOLVED] rotate turret to aim at target
Last edited by death_au on Wed Jul 04, 2007 1:39 am, edited 1 time in total.
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:
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
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);
};
this, i would also be glad to hear about it.
so long,
Andreas
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));