How can I make my characters follow the main one in a line like in EarthBound?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MegamanXfangamer

Hi everyone, it’s been a long time since I asked anything here, and the truth is that I’ve been working on a personal project, but I’ve come here to ask you something, and it’s about how I can make a line formation like in EarthBound, I mean, I don’t know if I’m making myself clear, but I want my secondary characters to follow the main one (which in this case is “Ness”) in the same way as in EarthBound. I’ve been researching, and I still don’t know how to do it, I would really appreciate it if you could support me, thanks for your attention.

:bust_in_silhouette: Reply From: jahu00

I’ve been trying to make a multiplayer game recently and one problem with this kind of games is recreating smooth movement on multiple instances of the game. The best way I found so far (result wise) was to make a movement history for each synchronized entity (in my game monsters and players).

How does this relate to your problem? Well, you are trying to recreate the movement of your controlled character with the rest of the party (if I remember correctly from Earthbound). In my multiplayer game I’m constantly updating this movement history (maybe a little foolishly), but in your case, this history would only need updating when your character is moving (and then send past positions to other characters in the party). If your game has smooth framerate, you can skip interpolating those past positions.

You could place something like this, in your party leader’s node (there might be some errors, I’ve been mostly playing with Godot 4 lately).

extends Node2D

var position_history = []
var max_history_length = 20

signal history_updated

func _physics_process():
	var character_moved = false
	#move your character here and set character_moved if it did
	if (character_moved):
		add_position_to_history()
		emit_signal("history_updated", position_history)

func add_position_to_history():
	var past_position = {"x": position.x, "y": position.y}
	position_history.append(past_position)
	
	if (position_history.size() > max_history_length):
		position_history.pop_front()

Other party members would connect to the history_updated signal and try to set their position to certain index in the history array.

extends Node2D

var party_leader
var tracking_index = 10

# pass party_leader node and delay in physics "frames"
func follow(party_leader, tracking_index):
	self.party_leader = party_leader
	self.tracking_index = tracking_index
	party_leader.connect("history_updated", self, "on_leader_history_updated")

func on_leader_history_updated(position_history):
	if (position_history.size() < tracking_index + 1):
		return
	past_position = position_history[tracking_index]
	position = Vector2(past_position["x"], past_position["y"])

You might add extra information besides the position to the past position object (and use a resource or a node for that instead of a dictionary). If you need interpolation, you will need more information besides the position, like speed or delta in there. I used a dictionary, because I don’t remember if Vector2 can be simply passed using signals or not (maybe I’m confusing multiplayer limitations with signal ones). If Vector2 can be passed, make a copy of the position using var past_position = Vector2(position).

Thanks, but I don’t know in which part I should put these codes

MegamanXfangamer | 2023-04-01 18:07

This is just an example of how you could achieve this effect (you may need to change some things in my code for your game), but the first part goes into the script of your main character. The second goes into the script of the character that is following. Additionally if you have a scene that contains both characters, you would have to call the follow function from inside the script from that scene. For example:

func _ready():
	var leader = get_node("Leader")
	var follower = get_node("Follower")
	#10 is the number of "frames" that the follower lags behind the leader
	follower.follow(leader, 10)

jahu00 | 2023-04-01 21:09

:bust_in_silhouette: Reply From: stormreaver

I’m being really general here, but following is pretty simple at its core. Your character is walking in a certain direction, so you just project a ray behind your character, and generate a list of points every X meters along that ray.

Assign each of your secondary characters one of those points, and have them continuously follow that point. They will all eventually converge onto the line as they follow their respective points.