[Solved] getting body segments to follow head

I have 3 objects, oHead, oBodySegment, oTail. The player controls the direction of the head which currently only moves up, down, left, and right, but does not adhere to a grid. The number of body segments changes. I'm having trouble getting each segment to follow the head all the way to point where the head turns.
I'm very new. Any help would be greatly appreciated! Thanks!
 
R

robproctor83

Guest
Well, do you want it to follow immediately or kind of stagger in the animation?
 

Nidoking

Member
I can see two sensible ways of doing this. One way would be to have a parent object for all of the objects you've got, and give each oBodySegment and oTail the id of an oPart that it will follow. Each move, it will grab the coordinates of the instance it's following and then move to that location next. The other way would be to maintain a queue of positions and push the head's location to all of the queues, then pop each queue to figure out where each part should go.
 
Well, do you want it to follow immediately or kind of stagger in the animation?
I want the segments to follow the same exact path as the head at the same exact speed, with a distance of 40 pixels between each object. For example, when the head goes from moving right to moving up, I want each segment to move to the point where the head changed direction, and then turn and move up.
 
Thanks for your responses! I've almost got it, only there is a problem I don't understand...
When the head turns, I create an object instance, something like an arrow, that points to where the body and tail should turn when they reach it. The tail destroys that instance. However, if the head turns before that instance is destroyed, it creates a new instance, which renders the first instance inoperable. The remaining segments that haven't turned yet continue on their path until off-screen.
 

Alexx

Member
Another approach is to set an alarm when each segment is created and remove it after a set amount of time.
I have an example if you'd like to look at it.
 

Nidoking

Member
When the head turns, I create an object instance, something like an arrow, that points to where the body and tail should turn when they reach it. The tail destroys that instance. However, if the head turns before that instance is destroyed, it creates a new instance, which renders the first instance inoperable. The remaining segments that haven't turned yet continue on their path until off-screen.
It sounds like you're using the object name to refer to the instance instead of getting the id of a particular instance and using that. Always use an instance id instead of an object id for any non-unique object.
 
It sounds like you're using the object name to refer to the instance instead of getting the id of a particular instance and using that. Always use an instance id instead of an object id for any non-unique object.
That is exactly what is happening, but I don't know how to do that. I think I've been able to get the instance ID of either the arrow or the body segment, but I'm completely lost on how to get both. Is that even necessary? I've been scouring for tutorials, but nothing really seems applicable.
 

Nidoking

Member
You're creating the arrows using instance_create_depth or instance_create_layer, right? The return value of that function is the id you need. You just store it somewhere. If you're checking to see which arrow one of your instances is touching, you use instance_place (for example), and the return value of that is the id. If you need more help than that, you're going to have to provide more information about what you're doing.
 
I feel like I'm getting close following your advice, Nidoking. Thanks! I didn't fully understand how "with" worked. I still don't, I guess. I thought it cycled through each instance of the object, but it doesn't seem to. The last segment and the tail follow the head, but the rest of the segments do not.
I create the body segment instances....
Code:
for(i=1; i<=PlayerLength; i+=1){
    BodySegment = instance_create_layer(x + (XPosSetup * i), y + (YPosSetup * i), layer, obj_Player1Body);
        BodySegment.image_xscale = global.PlayerStartingScale;
        BodySegment.image_yscale = global.PlayerStartingScale; 
etc.
I used ds lists for the values, which, like I said, works for the last segment and the tail...
Code:
with (BodySegment){
    for(i=0; i<ds_list_size(obj_Player1Head.ArrowListX); i+=1){
        if (x = ds_list_find_value(obj_Player1Head.ArrowListX, i)) && (y = ds_list_find_value(obj_Player1Head.ArrowListY, i)){
            image_angle = ds_list_find_value(obj_Player1Head.ArrowListAng, i);
            direction = image_angle;
        }
    }
}
I don't know. I appreciate your help everyone. I guess I'll keep pecking at it.
 

Joe Ellis

Member
Could you make oBodySegment point towards oHead and lerp its position towards oHead.pos - (angle * oHead.radius * oBodySegment.radius)
and do the same with oTail pointing towards oBodySegment?
 

Rob

Member
Thanks for your responses! I've almost got it, only there is a problem I don't understand...
When the head turns, I create an object instance, something like an arrow, that points to where the body and tail should turn when they reach it. The tail destroys that instance. However, if the head turns before that instance is destroyed, it creates a new instance, which renders the first instance inoperable. The remaining segments that haven't turned yet continue on their path until off-screen.
Well I did recently make a video for something similar as a request - hopefully it will help you too!

 

Nidoking

Member
I didn't fully understand how "with" worked. I still don't, I guess. I thought it cycled through each instance of the object, but it doesn't seem to.
Not the way you're using it, no. The problem is that first you do this:
BodySegment = instance_create_layer(x + (XPosSetup * i), y + (YPosSetup * i), layer, obj_Player1Body);
And then you do this:
with (BodySegment){
BodySegment is a variable that stores only the most recently created instance. You're overwriting it every time you create a new one. There's only one "BodySegment", so that's what you're looping over. A single thing. Now if you do with(obj_Player1Body), then you'll loop over all of the obj_Player1Bodys that you've created.
 
Great video Rob! I'll definitely be bookmarking that for future reference.
Nidoking... Thank you for explaining that so well! That completely worked, and now it makes so much sense. And I'm sure the red mark on my forehead from the massive facepalm will be gone before I know it.
 
Top