Ping pong ball trail not working

I’ve been trying to use a line2d to make the ball look better as its moving but the line2d instantiates way off of the ball. It still follows its movements, but it does so offscreen despite me setting its position to parent.position to make sure it stays on track. I also tried global_position but that didn’t work either. Heres my ball script.

class_name Online_ball
extends StaticBody2D


var screen_size: Vector2
var dir = get_ran_dir()
var speed = 100
var out_bounds: bool = false
var middle = Vector2()
var high: bool
var low: bool
const MAX_SPEED = 600
const MIN_SPEED = 100
@onready var physics: Node = $Ball_physics
@onready var slow_timer: Timer = $slow_timer
var reference_speed: float = 0
var velocity := Vector2.ZERO
var old_position = position
var speed_up: float
@onready var impact_animation: AnimatedSprite2D = $impact_animation
var paddles: Array = []
@onready var spawner
var can_collide := true
@onready var trail: Line2D = $Trail2

func _ready() -> void:
	if !is_multiplayer_authority(): return
	spawner = get_parent().get_node("MultiplayerSpawner")
	screen_size = get_viewport_rect().size
	position = Vector2(screen_size.x / 2, screen_size.y / 2)
	old_position = position
	impact_animation.play("Default")


func _physics_process(delta: float) -> void:
	if !is_multiplayer_authority(): return
	trail.add_point(position)
	if trail.points.size() > 50:
		trail.remove_point(0)
	var new_position = position
	paddles = get_tree().get_nodes_in_group("paddle")
	velocity = (new_position - old_position) / delta
	var collision = move_and_collide(dir * speed * delta)
	if can_collide and collision:
		var collider = collision.get_collider()
		var normal = collision.get_normal()
		if !collider.is_in_group("paddle"):
			speed = min(speed * 1.2, MAX_SPEED)
			dir = dir.bounce(normal)
			reference_speed = min(reference_speed + 15, reference_speed + 15)
			print(reference_speed)
		elif collider.is_in_group("paddle"):
			if collider == paddles[0] or collider == paddles[1]:
				if collider.speed_up > 0:
					speed = min(speed + collider.speed_up + 300, MAX_SPEED)
					impact_animation.play("impact_animation")
			else:
				speed = min(speed * 1.2, MAX_SPEED)
				impact_animation.play("Default")
			position += normal * 4
			dir = dir.bounce(normal)
			reference_speed = min(reference_speed + 15, reference_speed + 15)
			slow_down()
			spawner.temp_pause()
	position_tracking()


func slow_down() -> void:
	if !is_multiplayer_authority(): return
	slow_timer.start(.2)

func _on_slow_timer_timeout() -> void:
	if !is_multiplayer_authority(): return
	speed = clamp(speed - 25, MIN_SPEED + reference_speed, MAX_SPEED)
	slow_timer.start(.2)


func get_ran_dir() -> Vector2:
	var new_dir = Vector2()
	new_dir.x = [1, -1].pick_random()
	new_dir.y = [1, -1].pick_random()
	return new_dir.normalized()


func position_tracking() -> void:
	if !is_multiplayer_authority(): return
	high = position.x >= screen_size.x / 1.01 or position.y >= screen_size.y 
	low = position.x <= -60 or position.y <= -screen_size.y
	middle = Vector2(screen_size.x / 2, screen_size.y / 2)
	screen_size = get_viewport_rect().size
	if high or low:
		print(screen_size.x)
		reference_speed = 0
		position = middle
		speed = MIN_SPEED

Line2D is-a Node2D and its position is relative to its parent.

So when adding a new point after moving the ball, you would want to add Vector2(0, 0), but then of course you would need to loop over all the other existing ones in the array and offset them by pos - old_pos.

Alternatively, you could move the Line2D out of the ball (into the ‘level’ scene) and have an @export var trail: Line2D in your ball scene, hook it up in the editor and just use global positions, no need to loop and adjust.

1 Like

Thanks for the help. I went with your first solution, and it worked. Here’s my new code:

	var new_position = position
	var offset = new_position - old_position
	if offset != Vector2.ZERO:
		for i in range(trail.get_point_count()):
			trail.set_point_position(i, trail.get_point_position(i) - offset)
		trail.add_point(Vector2.ZERO)
		if trail.points.size() > 25:
			trail.remove_point(0)
		old_position = new_position