Sign in to follow this  

"Realistic" 2d missile homing

Recommended Posts

Hello, I am working on a top-down game that has missiles in it. I am writing in c++ using the Box2d engine. I want the missiles to steer only by applying torque and forward force, hence "realistic." As it is I have it turning correctly only if it starts at certain angles, and at other angles it turns away from the target. A video might help demonstrate. There's two examples in the clip, one where the missile starts facing right and one where it starts facing left. As you will see, it hits the target (the red circle) perfectly when facing right, but when facing left it goes in the opposite direction. I hope the video is not too unclear. The thick, short white line is the missile, the long lines indicate direction and such.


Here is the relevant function (called each frame):

void Missile::update() {
if (!active) {

// Begin direction calculations
b2Vec2 pos = body->GetPosition();
b2Vec2 vel = body->GetLinearVelocity();
b2Vec2 wp = *currentWaypoint->point;

float currentAngle = body->GetAngle();
float turnSpeed = body->GetAngularVelocity();

float targetAngle = pointAngleR(pos, wp);

float driftCompensationAngle = targetAngle - (angleDifferenceR(vectorToAngleR(vel), targetAngle));

targetAngle = driftCompensationAngle;

float aDiff = angleDifferenceR(currentAngle, targetAngle);

float desiredTurnSpeed = -((aDiff) * maxTurnSpeed);

* The constant determines the time it takes for the missile to stabilize itself.
* A lower constant means it takes longer.

float turnSpeedCorrection = (desiredTurnSpeed - turnSpeed) * 20000;

// End direction calculations

b2Vec2 force = getDirectionVector();
force *= -300.0f;

body->ApplyForce(force, body->GetWorldCenter());

#ifdef DEBUG

// Draw lines for debugging
line(screen, pos.x, pos.y, pos.x+force.x, pos.y+force.y, makecol(255,255,255));

line(screen, pos.x, pos.y, pos.x + (vel.x * 10), pos.y + (vel.y * 10), makecol(255,0,0));

line(screen, pos.x, pos.y, pos.x + (getDirectionVector().x * 100), pos.y + getDirectionVector().y * 100, makecol(0,0,255));

line(screen, pos.x, pos.y, pos.x + (angleToVectorR(driftCompensationAngle).x * 100), pos.y + (angleToVectorR(driftCompensationAngle).y * 100), makecol(0,255,255));

b2Vec2 targetAngleVector = angleToVectorR(targetAngle);
targetAngleVector *= -500;

line(screen, pos.x, pos.y, pos.x + targetAngleVector.x, pos.y + targetAngleVector.y, makecol(0,255,0));


// Check if we've reached our target
if (abs((pos - wp).Length()) < 5) {
if (currentWaypoint->next != NULL) {
currentWaypoint = currentWaypoint->next;
} else {
active = false;


Thanks for any help!

Share this post

Link to post
Share on other sites
it would probably be very useful to start the simulation in a situation where the code does the wrong thing and look at variable values using a debugger. My guess is that some of the angle computations don't work well around the point where the angles change from 180 to -180 or from 360 to 0.
I would implement the whole thing without using angles. Thinking about these things in terms of angles might seem more intuitive at first, but it's easy to make mistakes. If you write the code using vectors, it generalizes to 3D naturally and it's easier to get right. Code that doesn't use angles even executes faster, although that should only be an argument if it matters.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this