# How can I achieve a snake like motion where the body follows the head?

## Recommended Posts

Hi everyone, I have this erally annoying problem i can't figure out... I'm trying to achieve a sipmle movement type where I have a "snake" with a head and a body (let's say the body has 8 links), each represnted by a position vector. I want only the head to dictate movement (it moves randomly and chagnes velocity/direction), and the body is supposed to follow it fluently without dropping behind or overlapping itself) Currently I'm using a simple sin/cos on the angle between each link and the one it has to follow - but the results are not good enough as I cannot tell how "fast" the link has to go in order to stay exactly behind the one it's following. here's a screenshot of the problem: notice how the "head" has moved faster than the tail and also that the tail links ahve overlapped itself. Any ideas?

##### Share on other sites
If each segment of the tail is simply following in the path of the head, can you simply make each tail segment be a delayed version of the head? So the head is the current head, the first segment in the tail is the head 1 tick ago, the second is the head two ticks ago, etc. So use a queue system that just holds copies of the head for the last X ticks.

If the tail segments are varying from the head's previous positions, then you could probably still do that but just add variations to the delayed head positions.

##### Share on other sites
Well, the each 'Link' needs to be a certain distance from the one in front of it right?
so instead of calculating how 'fast' each link needs to move to catch up, just assume that the connections chaining them together are totally Solid, so it always moves the right distance (dont care about speed).

So, when the head moves, move the 1st link in a straight line towards the head to be the right distance.
then move the 2nd link towards the 1st link to be the right distance
and so on...
one at a time, in order, till you run out of links

Just a series of straight lines.
You don't even need to deal with Sin Cos functions, just use Vectors and the Distance Forumula.

What I mean to say is... Approach the problem Differently.
Rather than think of how Fast they need to move to keep up. Figure out Where they need to end up to maintain the connection.

##### Share on other sites
If you treat each body part as a physical particle, you can connect them with joints and then simulate the system. This will make your snake look a little ropey, but it sounds like that's what you're going for.

Using Verlet integration and infinitely stiff springs would probably take the least amount of time to code up.

Along the same lines, you could use an implicit integration scheme and connect the body parts with nearly infinitely stiff springs, or you could use a physics system that supports hard constraints and connect the parts with pin joints. If you're not into writing physics code, though, you're probably better off using the first option.

John Edwards

EDIT: I just understood haphazardlynamed's suggestion. I like that better. It'll give you a slightly different look than the physics route, but it's far simpler. I guess it's like the Verlet method in the case where each body part is much heavier than the one following it.

[Edited by - PistachioPro on June 12, 2006 4:12:58 PM]

##### Share on other sites
haphazardlynamed's solution is similar to the one I used recently for a snakelike creature, but for mine instead of having hard-joints (which looked robotic) I set a spring force toward the next position. It looks a bit more cartoony, but with tight enough springs it gives a very lifelike snake movement.

##### Share on other sites
First of all, thanks for taking the time to answer :)
There are several problems with both your aproaches:
Reana's method is the easiest to implement but what happens is that all the links just overlap each other and reach the head after about 10ms.
i cannot simply set the next link's position to it's neighbour's previous position because a link does not jump in whole width jumps (lets say the head is at (100,100) and the 2nd link is at (120,100), after the first iteration the
head would be at (101.5,99.2) and the 2nd link would be at (100,100)...
That quickly lead me to a different approach where i store only the deviation of the head (how much it moved each tick) and then use it to move the 2nd link the same amount in the next tick (and so on for all following links).
This led to another dead end, the effect of this being that the entire snake moves as if it's a solid rectangle made up of one chunk (since if the head moved 2px up, 1 left, this behaviour is then propogated to the 2nd link, then to 3rd and so on, resulting in the described effect).

Hope I'm making sense up till now, as this can be pretty hard to explain without actually seeing it in motion... ;)

on to haphazardlynamed's idea:
Unfortunatly, I think your method won't work as well ( if i understood correctly). It has the same problem I have exprienced so far - distance is not constant between links. let's say the head is moving left, and suddenly shifts direction 180 degrees - if I simply calculate the new position based on a fixed distance i will again end up with a stiff rectangle where all links would move with the head to the right (in effect making the head the tail).

I think a spring system is a good solution - However, it seems awfuly complex for such a simple task :)
Any more ideas?

thanks for everyone's help (and if i didn't make sense before, let me know and I'll try to explain it differently).

Ehud.

##### Share on other sites
A spring system isn't at all complex... Hookes Law:

x = -kv

Where V is the vector between the target position and the current position, and -k is a spring constant.

Not terribly complex, is it? :)

##### Share on other sites
Quote:

it sounds like you are setting your link's position to the guy before it Too Quickly. Try instead of moving the link to it's predecessors previous position, move it to the predecessors 10th previous position. Or something with a bigger delay.
Or since it sounds like your snakehead is analog motion... one of the other methods might help...

Quote:
 Original post by ehudroson to haphazardlynamed's idea:Unfortunatly, I think your method won't work as well ( if i understood correctly). It has the same problem I have exprienced so far - distance is not constant between links. let's say the head is moving left, and suddenly shifts direction 180 degrees - if I simply calculate the new position based on a fixed distance i will again end up with a stiff rectangle where all links would move with the head to the right (in effect making the head the tail).

I dont think you got it....
Links do not inherit the same delta motion as the one before them, they simply move Towards the guy in front until they are the correct distance from it(and no closer than that)
When the head suddenly changes direction, the 1st link will move towards it, but not Onto it, since it is meant to stop a distance away before overlapping.
Thus the 2nd link will head towards the 1st, which is Not the same spot as the Head. and as you go farther down the line each one is going to lag behind to an even further degree. The key being the Minimal Distance condition to keep links from overlapping, and introduce Lag so it acts 'snakey'.

Quote:
 Original post by ehudrosAny more ideas?

I think the ideas present so far are all very good, and that you should spend a little time trying them out and doing some debugging work on them before moving on.

##### Share on other sites
Quote:

I'm not sure how you're implementing it, but it sounds like you have all the links drawn to start with. So you are still treating them as X objects that each need to move around. But I was thinking more of just a list of all head positions. So there's just one object and you are displaying it's location (with some chosen rate and number of images shown). If it's not an issue, you can just start the snake with no length until the head first moves far enough. Then start displaying the head and the nth image in the past. Then as it moves further also show the 2*nth, then 3*nth, etc. Assuming constant velocity that would have them evenly spaced following the head. If you want to keep them evenly spaced with varying head speeds you'll have to select which past images to save based on speed. If the snake does needs to be drawn completely at initialization, you'll just need to create a fake past list of positions that displays it like you want at the start.

The spring solution should work too, and that may be more of what you want if you need to keep the snake links as independent objects. As I think haphazardlynamed said in the last post, each link moves relative to the one in front of it. For the quick 180 deg change, the problem is that for springs you are now compressing the spring (imagine a slinky or real spring - if you are pulling one direction, then instantly switch to the opposite, the spring can't loop around to where the head was - it simply compresses now).

My list of head postions solution shouldn't have direction issues, it's just a matter of figuring out how to choose which images to display based on the speed of the head. Maybe some interpolation between images would be needed too to handle speed changes, but if you save a fine enough list of positions I don't think that would be needed.

##### Share on other sites
Quote:
 Original post by reana1The spring solution should work too, and that may be more of what you want if you need to keep the snake links as independent objects. As I think haphazardlynamed said in the last post, each link moves relative to the one in front of it. For the quick 180 deg change, the problem is that for springs you are now compressing the spring (imagine a slinky or real spring - if you are pulling one direction, then instantly switch to the opposite, the spring can't loop around to where the head was - it simply compresses now).

My solution for that was to put minimum-distance springs between each body part and the other body parts, so that if they snake turns quickly, it actually would push it's tail outward. It looks pretty realistic.

##### Share on other sites
Ok, after a good nights sleep everything's making much more sense.
Thanks for all your insight and tips :)

What I have now a spring based system with a rest length of 20 (that's the links current size) and indeed there's a problem when the snake change direction drastically.
I will try to prevent it from acting like (making it only change direction in 90 degrees angles).

I'm still not sure i understand the difference between haphazardlynamed's method and a spring calculation.
I've adjusted the code in the link Pistachio supplied and I must say i'm not even sure if it's considered a spring simulation or simply calculating it the way haphazardlynamed suggested... :)
Here's the code i'm currently using:

for (i=1; i<MAX_LINKS; i++){	force_dir = Body[i-1] - Body[i];        // length is a sqrt of the dot product	CurrDistance = force_dir.length();	intensity = (CurrDistance-LINK_DISTANCE)/CurrDistance;	ComputedForce = force_dir*intensity;	Body[i]+=ComputedForce;}

So basically, it seems things are working pretty well now, i'm justn ot sure what i'm doing right :)

Thanks again for taking the time to help!
ehud.

##### Share on other sites
Holy Geometery Wars Batman!

##### Share on other sites
Quote:
 Original post by ehudrosI'm still not sure i understand the difference between haphazardlynamed's method and a spring calculation.I've adjusted the code in the link Pistachio supplied and I must say i'm not even sure if it's considered a spring simulation or simply calculating it the way haphazardlynamed suggested... :) Here's the code i'm currently using:

My suggestion is like a simple subcase of doing a spring calculation, in this case the springs are infinitly stiff and don't 'spring' at all. The overall algorithm is basically the same idea though, just leaves out the springiness calculations.
The code in Pistacio's link is also esentially the same idea: stiff springs.
The main difference between what I suggested and the Jakobsen article, is that the article is general purpose joints simulation; while my suggestion uses one-way constraints between the joints.(mainly because you wanted the head of the snake to be in control of the tail, with the tail being totally passive). Once again this can be considered a subcase situation.
They're all pretty closely related approaches.

## Create an account

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627662
• Total Posts
2978519

• 10
• 10
• 12
• 22
• 13