How to manipulate acceleration to make projectile take the same time no matter the distance?

Godot Version

4.3

Question

I have a boomerang type projectile that flies a max distance before returning. I want the process to take a similar amount of time no matter how far the projectile is thrown.

Here is the current behavior:

Demo

Here is the code where the boomerang object is immediately in motion as soon as it is instantiated.

class_name WeaponThrow extends Node2D

enum State {
	INACTIVE,
	THROW,
	RETURN
}

var player : Player
var direction: Vector2
var speed: float 
var state
var destroy
var distance : int = 250
var throwLocation

@export var acceleration: float = 400.0
@export var max_speed: float = 400.0

func _ready() -> void:
	visible = false
	state = State.INACTIVE
	player = PlayerManager.player

func _physics_process(delta: float) -> void:
	if state == State.INACTIVE:
		var mousePos = get_global_mouse_position() #direction of dash
		var rotationF = atan2(mousePos.y-position.y,mousePos.x-position.x) #rotation of line between player and mouse
		throwLocation = Vector2(distance*cos(rotationF)+position.x,distance*sin(rotationF)+position.y) #calculation of the point to where should be dashed
		if position.distance_to(mousePos) < distance:
			throwLocation = mousePos
		state = State.THROW
	if state == State.THROW:
		rotation += .3
		speed -= acceleration * delta
		position = position.move_toward(throwLocation, speed * delta)
		if position.distance_to(throwLocation) <= 10 or speed <= 0:
			state = State.RETURN
	elif state == State.RETURN:
		rotation += .3
		speed += acceleration * delta
		position = position.move_toward(player.position, speed * delta)
		if position.distance_to(player.position) <= 10 or speed <= 0:
			queue_free()

func throw( throw_direction : Vector2) -> void:
	direction = throw_direction
	speed = max_speed
	visible = true

func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
	destroy = true
	await get_tree().create_timer(2).timeout
	if destroy:
		queue_free()


func _on_visible_on_screen_notifier_2d_screen_entered() -> void:
	destroy = false

You should be able to solve this with formula

distance / speed * acceleration = totalTime / 2

Maybe?

You know the distance to the target. You know the speed. And you know the total time it should take. Since you want the deceleration and acceleration to be linear, it is easy to solve with basic math. Which is also the only math I know.

Edit: Even if you wanted the approach to be smoother, once you have the average deceleration, it is easy enough to shift some values from end to beginning to make a kind of a janky curve. No one will know…

This is a (fortunately simple) calculus problem. Distance traveled under constant acceleration is d = (a*t2)/2, so via algebra, a = 2d/t2, if I did it right. In the end, you just need to calculate 2/t2 once based on your desired one-way travel time; if this is the constant N, your acceleration should be d*N.

Sweet, I’m having a little trouble understanding where or how to implement the formula. Would it be when I first instantiate the object or repeatedly in the process function?

Because the acceleration is constant, you’ll only need to calculate it once each time the distance changes. You can calculate N = 2/t2 once in _ready or just as a default variable, and calculate a = N*d whenever you decide how far to throw the boomerang.