Is there a better way to make a PathFollow2D follow another PathFollow2D at a fixed distance?

Godot 4.4.1.stable

For a little railway game (just for personal entertainment, I’n not a programmer) I have a Path2D with two PathFollow2D nodes representing the bogies of a locomotive and these bogies should stay at a fixed distance. The front bogie moves along the path like this:

func _process(delta: float) -> void:
	progress += 30 * delta

The back bogie follows by increasing/decreasing the progress on the path by a tiny step until the distance is about right:

var fixed_distance = 50
var step = 0.1

func _process(delta: float) -> void:
	if position.distance_to(front.position) > fixed_distance:
		while position.distance_to(front.position) > fixed_distance:
			progress += step
	elif position.distance_to(front.position) < fixed_distance:
		while position.distance_to(front.position) < fixed_distance:
			progress -= step

It works fine, even with multiple bogies chained after each other, but is there a more efficient, faster, maybe more elegant way to achieve this? Also, do I need to use delta when setting the back bogie’s position?

Thanks for your help,
herwop

Edit: not enough coffee.

I think you can rewrite this as:

# front car

func _process(delta: float) -> void:
    progress += 30.0 * delta

# back car

const DIST_BETWEEN_CARS: float = 50.0

func _process(delta: float) -> void:
    position = front.position + DIST_BETWEEN_CARS

Thanks for your suggestion hexgrid, but I don’t think adding a float to a Vector2 works. I’ve tried it.

Enjoy your coffee!

1 Like

Thinko. Definitely not enough coffee. I meant:

# front car

const SPEED: float = 30.0

func _process(delta: float) -> void:
    progress += SPEED * delta

# back car

const DIST_BETWEEN_CARS: float = 50.0

func _process(delta: float) -> void:
    progress = front.progress - DIST_BETWEEN_CARS

You’ll potentially have to account for spacing at the ends, but it ought to work.

The idea being that since progress is the pixel distance along the path, subtracting a fixed amount of that ought to be a fixed number of pixels behind.

1 Like

Your’re right, but maybe my question was a little unclear.

Using the distance along the path (progress) is fine on a straight track, but in a curve the straight distance between the two bogies of a locomotive or car would be different from the length along the path. I want the straight distance to be constant, the bogies are fixed to the car body after all, that’s why I used distance_to for measuring before setting progress.

A short video of what I have - the dots are the bogies (PathFollow2Ds), the black lines are the constant distance between bogies.

I hope this makes more sense.

In that case, I’d still suggest looking into get_closest_point(), probably on a line projected from the first car’s position to the second’s.

@hexgrid I also thought about that, but if the curve is sharp enough (think an extreme 90 degrees turn with a long wagon), it won’t be in the correct place any way.
I think what @herwop is doing with the simulated while loop is the only correct approach if you want to be really accurate, I can’t think of any better solution honestly. It shouldn’t be that expensive to calculate anyway. Later you can maybe just check how many loops you are running each frame and try to reduce these by adjusting your calculations.

By the way, I had a similar problem to solve for my prototype game, see here a couple short fun videos I posted on Tiktok a while ago. But there I completely ignored accuracy, as I wasn’t handling the bogies directly, but a train car as a whole and I actually used get_closest_point() with a bunch of other trickeries.


2 Likes

@hexgrid When I tried running multiple, long trains at high speeds, the FPS went down dramatically, I guess because the leading bogie has moved far away and the while loop goes through many iterations.

So I added your suggestion progress = front.progress - DIST_BETWEEN_CARS as the first line in the follower’s _process to bring the following bogie at least close to the correct distance and only after that calculate the exact position, that brought the FPS back up again. Thanks!

@wchc That’s a nice looking game, very much like what I have in mind for my project. I’m eager to learn, so would you mind elaborating a little about your usage of get_closest_point() and those “trickeries”?

Sure, let me know your github username, I can share the project with you

Thank you, just created an account there, named: herwop