4
\$\begingroup\$

I want to set up paths for enemy characters in my game to patrol. I'd like to be able to define a list of waypoints and have the enemy follow the path from one point to another, but in a smooth curve.

How can I do this?

\$\endgroup\$
  • \$\begingroup\$ The Autonomous Agents chapter in The Nature of Code makes great background reading. It has a section on Path Following and even expands it to Path Following with Multiple Segments! (Even more of a plus: Its code samples are in Processing, which is extremely similar to Java.) \$\endgroup\$ – Anko Jan 18 '14 at 7:03
  • \$\begingroup\$ Ooh, Nature of Code even made videos about it. \$\endgroup\$ – Anko Jan 18 '14 at 7:29
4
\$\begingroup\$

If you want to take a precise mathematical approach, what you're looking for is an interpolation function.

If you have some random points...

random points

... and you want to interpolate (that is, fill in what goes in between). The first thing you're likely to think of is to draw straight lines:

linearly interpolated path

This is called linear interpolation, because the function describing how we interpolate between two points is a linear function; y = m * x + c kind of deal.

There's nothing stopping us from using a different function to interpolate. Here's an interpolation with a closed B-spline:

basis-interpolated path

It doesn't go through all the points, because basis B-spline control points only influence the shape of the curve.

Cardinal splines, for example, do pass through all points:

cardinal spline interpolation

I stole the implementations from D3: This is where you'd find the interpolations defined in the D3 source.

Bezier curves are a reasonably simple subset of B-curves (here are some pretty understandable graphics on how they work) and will give good results too. There are others you may want to use; we even have a list.

|improve this answer|||||
\$\endgroup\$
  • 2
    \$\begingroup\$ How do you calculate the points on a cardinal spline? \$\endgroup\$ – AturSams Jan 18 '14 at 9:17
  • \$\begingroup\$ @Arthur This page is the best implementation-focused explanation I've found. It has pseudocode too. I'll try to find time to summarise it here later. \$\endgroup\$ – Anko Jan 18 '14 at 15:22
  • 1
    \$\begingroup\$ This is a good explanation of how to draw smooth curves (and presumably this helped the asker, since this answer is accepted). However technically this doesn't actually answer the question, since the question asked about moving a character and this answer doesn't make any reference to a moving character. \$\endgroup\$ – jhocking Jan 25 '14 at 20:58
  • \$\begingroup\$ @jh My idea was that moving a character along a curve can be viewed as the same thing as drawing a curve. Find a point, find the next point, draw a line, repeat until done. Yeah, this is really rigid -- your answer is better when characters must be able to do other things besides exactly follow a predetermined path. \$\endgroup\$ – Anko Jan 26 '14 at 5:24
2
\$\begingroup\$

The other answers all discuss how to draw lines connecting the waypoints, presumably in order to then make the AI character follow the line. I guess that would work, but I prefer an approach where instead of forcing the AI to follow a drawn line, I simply define how the character moves and then use the waypoints as movement targets.

So in other words the waypoint system tells the AI character "walk toward this point" rather than "stick to this line."

For the simplest implementation of such a system, the path is an array of positions, and when the game starts the AI chooses the first position as it's movement target. Once it reaches that target, it switches to the next point in the array. repeat

The path the character takes will naturally smooth between the waypoints if the character's movement characteristics include turning slowly.


(btw if you're wondering what results you get with this technique, the flying puffballs in this demo were implemented in the way I just described)

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ How are you calculating intermediate points between the points that you have specified? \$\endgroup\$ – endrohat Jan 25 '14 at 21:07
  • \$\begingroup\$ I'm not. With this approach, there's no need for me to know the intermediate points ahead of time; the character just picks a direction to move to (ie. a waypoint) and then starts moving in that direction. \$\endgroup\$ – jhocking Jan 25 '14 at 22:15
  • \$\begingroup\$ Not ahead of time .If you are travelling from Point A to Point B, then how do you make the motion smooth? \$\endgroup\$ – endrohat Jan 26 '14 at 6:52
  • \$\begingroup\$ I think you're misunderstanding the concept here. The smoothness of the movement has nothing to do with the waypoints; those are just being used as target positions for the AI character. How exactly the character moves is a characteristic of the character, not of the path. So if I want the character's turns to be bigger loops, I just program the character to turn more slowly. \$\endgroup\$ – jhocking Jan 26 '14 at 13:12
  • \$\begingroup\$ For an analogy, imagine the waypoints are destinations in a big scavenger hunt, and the character is a car. The destinations don't define anything about how the car moves between destinations; that specific movement is a factor of the car itself. \$\endgroup\$ – jhocking Jan 26 '14 at 13:15
1
\$\begingroup\$

Take the average of each pair of sequential way-points. Use these as your new start and end point for bezier curves. Use the actual points as control points.

You could also use a weighted average if you only wish to avoid sharp corners.

See this for the complete explanation: How do I generate a smooth random horizontal 2D tunnel?

|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

I found this XNA path editor which does path Catmull-Rom spline calculation for you.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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