Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

What is a good technique to enable an object to move between to points in a nice curved motion?

The end position could also be in motion, such as the trajectory of a homing missile.

share|improve this question

4 Answers 4

up vote 11 down vote accepted

Assuming you want this to be a frame-by-frame thing (where the target could even be moving), and not a precomputed trajectory, this is actually incredibly simple:

Every frame, compare the velocity-vector of the missile to the vector (positiontarget - positionmissile); that is, the vector pointing from the missile to the target. Every frame, if the two vectors do not have the same direction, then rotate the veloity-vector a little bit towards the other vector, so every frame the missle gets a little bit closer to looking at its target.

You can determine whether to rotate clockwise or counter-clockwise by looking at the sign of the cross-product between the two vectors.


[Edit] XNA-ish code (I don't have XNA to test this):

//Once a frame:

//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;

//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);

//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;

//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
    rotationAngle = -0.05;
else if(crossProductSign < 0)
    rotationAngle = 0.05;

//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))

Note that, because rotationAngle has only three possible values, all possible values of Matrix.CreateRotationZ(rotationAngle) can be cached so you don't have to call it every frame.

share|improve this answer
    
Could you maybe provide some pseudo code as I am new to all this. I am currently only working in the 2nd dimension so that removes some complications. –  anonymouse May 7 '11 at 18:25
    
@anonymouse: sure, try this –  BlueRaja - Danny Pflughoeft May 7 '11 at 18:46

There are two possible techniques:

The first technique is to do a frame-based simulation. This is good if you are doing something like a homing missile in gameplay, that does not have to hit your target exactly.

In this case you want to track the object's position and velocity. Each frame look at the direction to the target and the current movement direction, and adjust the velocity appropriately.

If you snap the velocity instantly, your missile will always hit the target. But if you adjust the velocity by a small amount each frame, your missile will curve towards the target - and if it curves slowly enough, the target could dodge it.

The second technique is to use a parametric method. This is useful for animating things where you want to hit your target precisely and predictably. In this case you usually take "time" as your parameter and put it into a function of some kind.

A particularly useful set of functions are the Equations of Motion you learned in highschool physics. By applying these to both axis you can get ballistic trajectories. With a little bit of maths, you can determine the initial parameters to hit a target - even a moving one, if it moves predictably.

XNA also provides a number of interpolation and curved motion functions. Take a look at the documentation for Vector2 and for MathHelper. These provide some interpolation functions which you can use and even combine to do interesting things. For example, firing a missile: Lerp (linear interpolate) your missile's position from its start point to a target position, and also lerp that target position from some initial target to the target object's real (changing) position. This will give you a nice "locking on" effect.

(There are also some functions for producing curves, for example: CatmulRom, Hermite. These are probably harder to use successfully with a moving target, though.)

If you look into "easing" (in the context of animation), you can get some more interesting interpolation functions that can give you interesting effects like acceleration.

Now - you may say that this technique gives some odd results as your target moves around. However in practice, as long as your projectile is moving faster than your target, it usually looks fine. If it is a problem, you should probably be using a frame-based technique anyway.

share|improve this answer

You may want to look up sine waves or possibly Bezier Curves. I don't know whether the sine wave approach is normal, but I can't see why it would be that poor.

share|improve this answer
    
Using Bezier curves with B-Splines allows for fairly accurate representation of any curve. If you need precision, Cubic Hermit splines are slightly more accurate. Bear in mind, sometimes inaccuracy provides a welcome touch of organicness. –  Jonathan Hobbs May 7 '11 at 15:44
    
+1 for Bezier curves. For the use described, it's probably the easiest and the most controllable. –  ggambett May 7 '11 at 19:39

You can take a look at Steering Behaviors, as defined by Craig Reynolds: http://red3d.com/cwr/steer/

This is often used in AI to have NPCs move toward their target.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.