GML Object Trailing

samspade

Member
I'm trying to create an object which has other objects following behind it at a set distance along it's exact path. Following an object in its exact path is no problem, but I'm having trouble with the set distance. These are the things I've tried:
  • Put each objects x and y location into a queue and have its follower pull from that queue. This works just fine for following but distance is inconsistent. If the 'head' object moves faster or slower it's various parts bunch up or separate. If 'head' object moves fast enough then there will be a great deal of separation between each following object.

  • Store the movement vector and pass that along. Then have each follower placed at a set distance along that vector. This works, but looks weird. If the 'head' object makes a big loop, the followers will make that same loop but it will be smaller.

  • Create a particle trail. This is the worst of the solutions. Even if you do a fake particle trail and use objecs so you can interact with them, because you are always deleting them it causes a lot of problems.
Any ideas? I don't need code, unless you want to, I'm just stuck at how to think about it.
 

samspade

Member

Perhaps I'm looking at this wrong, but couldnt you clamp their positions relative to where they are?
e.g
Code:
bodypart.x/y = head.x/y - lengthdir_x/y(clamp(x/y,min/max),direction)
I'm sure I haven't written it correctly, but I think theres possibly a solution in there for you, or at least implement to make a solution
This doesn't really work. As written it will just make the worm a straight line pointing away from the direction it's going. I tried a modified version, but it also looks very weird at higher speeds (although it does a better job at lower speeds):

Code:
//get move coordinates parent
if (instance_exists(parent)) {

    if (ds_queue_size(parent.x_trail_queue) > trail_distance) { 
        ds_queue_enqueue(x_trail_queue, x);                             
        x = ds_queue_dequeue(parent.x_trail_queue);
    }
    if (ds_queue_size(parent.y_trail_queue) > trail_distance) {
        ds_queue_enqueue(y_trail_queue, y);
        y = ds_queue_dequeue(parent.y_trail_queue);
    }

    var x_min, x_max, y_min, y_max, angle;

    angle = point_direction(parent.x, parent.y, x, y);

    x_min = parent.x + lengthdir_x(20, angle);
    y_min = parent.y + lengthdir_y(20, angle);

    x_max = parent.x + lengthdir_x(30, angle);
    y_max = parent.y + lengthdir_y(30, angle);
   
    x = clamp(x, x_min, x_max);
    y = clamp(y, y_min, y_max);
}
Essentially this moves the part, and after moving the part, clamps it closer. It's still not very good.

After looking into it a little more it seems like one way to do this would be the physics engine (you could connect the objects with joints and apply forces to the head) but I don't want to turn on physics for one thing. Does anyone know enough of how the physics engine works under the hood that you could point me towards what I would need to learn in order to create a basic joint system?
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
After looking into it a little more it seems like one way to do this would be the physics engine (you could connect the objects with joints and apply forces to the head) but I don't want to turn on physics for one thing. Does anyone know enough of how the physics engine works under the hood that you could point me towards what I would need to learn in order to create a basic joint system?
DON'T use physics just for this... it opens a whole other can of worms, and even in the physics system joints can "stretch" and distances can vary depending on how it's set up.

So, here's what I'd do... Have the "head" instance (the first one created) create the "follow" instances, and in each one set them to follow the previously created instance, something like this:

Code:
var front;
front = id;                                                 // This will hold the previous instance id
repeat(max_tot)
{
parts[tot] = instance_create(x, y, FOLLOW_OBJECT);  // Create follow object
parts[tot].follow = front;                                  // Tell it who to follow
front = parts[tot];                                         // Set the follow id to new part for next instance
tot ++;                                                     // Add one to total followers made
with (front)
    {
    num = other.tot;                                        // Follower number
    }
}
Then in the main object that you want all others to follow, simply have something like this:

Code:
with(FOLLOW_OBJECT)
    {
    if instance_exists(follow)
        {
        if point_distance(x, y, follow.x, follow.y) > DIST // DIST here is the maximum distance from each other that you want the instances to be
            {
            direction = point_direction(x, y, follow.x, follow.y)
            x = follow.x - lengthdir_x(DIST, direction)
            y = follow.y - lengthdir_y(DIST, direction)
            }
        }
    }
I used something very similar to this for my (unfinished :( ) game Ataraxia and as you can see, it works perfectly.

 

samspade

Member
Then in the main object that you want all others to follow, simply have something like this:
Thanks Nocturne I actually stumbled upon nearly the same solution late last night. Sadly, I didn't see your post before. (Also the game looks cool.) Here's my solution, though it really is pretty much identical just arriving in a slightly different way. (also, I'm typing this from memory so I might have done it slightly wrong, I'll correct it if so)

Code:
if (instance_exists(parent)) {
    var _target_angle = point_direction(parent.x, parent.y, x, y);
    x = parent.x + lengthdir_x(-dist, _target_angle);
    y = parent.y + lengthdir_y(-dist, _target_angle);
}
It works just fine so long as the head keeps moving (my enemy has very similar movement to your video).

Edit: I'm also leaving this here for myself as I think this would be another way to do it if for some reason I decide this method doesn't work.

https://forum.yoyogames.com/index.php?threads/how-to-make-moving-tentacles.8264/#post-58155
 
Last edited:
Top