How can I achieve set_pos as a parable with tween node?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By kedv
:warning: Old Version Published before Godot 3 was released.

The challenge is to create a damage animation that sputter out of his monsters head.

With the following syntax I can achieve a straight line between two points.

effect.interpolate_property(node, "rect/pos", node.get_pos(), Vector2(47, -45), 0.5, Tween.TRANS_QUAD, Tween.EASE_OUT)

Damage label pos as parable

But I have no idea how to calculate a parable to the pos value?
Have anyone a clue to how can I achieve this?

:bust_in_silhouette: Reply From: mollusca

Here’s one way:

    effect.interpolate_property(node, "x", start_x, end_x, 1, Tween.TRANS_LINEAR, Tween.EASE_IN)
    effect.interpolate_property(node, "y", start_y, end_y, 0.5, Tween.TRANS_QUAD, Tween.EASE_OUT)
    effect.interpolate_property(node, "y", end_y, start_y, 0.5, Tween.TRANS_QUAD, Tween.EASE_IN, 0.5)

x and y are member variables in the node you want to move. You also have to manually update the position of the node with set_pos(Vector2(x, y)).

You can update the position (set_pos) on tween_step signal.

eons | 2017-05-16 16:54

Yes this work really great. I have a similar solution in mind but I’am not sure this is the right way. Thank you so much.

@eons
Thank you for the tween_step tip, really interesting. I have try it with tween_step but x and y be two function requests. I found it convenient to set the pos in the node itself.

kedv | 2017-05-17 07:51

Thanks folks – I ended up using both @mollusca’s and @eons’ suggestions. Here it is.

Max Aller | 2017-10-22 18:04

Here’s my implementation. :slight_smile:

extends Node2D

onready var container = get_node("container") # Node2D
onready var label = get_node("label") # Label
onready var effect = get_node("effect") # Tween

var x = 0
var y = 0

func _ready():
	label.hide()

func set_damage(dmg):
	var d = label.duplicate()
	container.add_child(d)
	d.set_text(str(dmg))
	d.show()
	
	var x = 0
	if (randi() % 2 == 1):
		x = d.get_pos().x - 50
	else:
		x = d.get_pos().x + 50
	var start_x = d.get_pos().x
	var end_x = x
	var start_y = d.get_pos().y
	var end_y = d.get_pos().y - 50
	effect.interpolate_property(d, "x", start_x, end_x, 1, Tween.TRANS_LINEAR, Tween.EASE_IN)
	effect.interpolate_property(d, "y", start_y, end_y, 0.5, Tween.TRANS_QUAD, Tween.EASE_OUT)
	effect.interpolate_property(d, "y", end_y, start_y + 30, 0.5, Tween.TRANS_QUAD, Tween.EASE_IN, 0.5)

	effect.interpolate_property(d, 'visibility/opacity',
                                1, 0, 1,
                                Tween.TRANS_EXPO, Tween.EASE_IN)
	effect.start()

func _on_effect_tween_complete( object, key ):
	if (key == "visibility/opacity"):
		object.queue_free()

kedv | 2017-10-24 07:18

:bust_in_silhouette: Reply From: exuin

This is an old question, but people are still looking at this, so…

Now (3.2.3) you can tween node positions directly with “position:x” and “position:y”.

So you can have:

effect.interpolate_property(node, "position:x", start_x, end_x, 1, Tween.TRANS_LINEAR, Tween.EASE_IN)
effect.interpolate_property(node, "position:y", start_y, end_y, 0.5, Tween.TRANS_QUAD, Tween.EASE_OUT)
effect.interpolate_property(node, "position:y", end_y, start_y, 0.5, Tween.TRANS_QUAD, Tween.EASE_IN, 0.5)

Also, this is for animations where you want the ending y-position to be the same as the starting y-position only. Someone on Discord was trying to use it with a dynamic dropping system like in Enter the Gungeon and it didn’t work. If you want to dynamically set the ending y-position, use this code:

const JUMP_HEIGHT = 96
const ANIM_LENGTH = 0.5

effect.interpolate_property(node, "position:x", node.position.x, ending_pos.position.x, ANIM_LENGTH)
effect.interpolate_property(node, "position:y", node.position.y, ending_pos.position.y-JUMP_HEIGHT, ANIM_LENGTH/2, Tween.TRANS_QUAD, Tween.EASE_OUT)
effect.interpolate_property(node, "position:y", ending_pos.position.y-JUMP_HEIGHT, ending_pos.position.y, ANIM_LENGTH/2, Tween.TRANS_QUAD, Tween.EASE_IN, ANIM_LENGTH/2)
effect.start()

Note that ending_pos is a Position2D node here. You can change it to a Vector2 or whatever you want, though.

Very usefull, thank you.

How can I achieve the same this on a 3D scene?

I have th following aproach, but the result is a mess.

tween.interpolate_property(newBullet, "translation:x", origin.x, target.x, 1, Tween.TRANS_LINEAR, Tween.EASE_IN)
tween.interpolate_property(newBullet, "translation:z", origin.z, target.z, 1, Tween.TRANS_LINEAR, Tween.EASE_IN)
tween.interpolate_property(newBullet, "translation:y", origin.y, target.y, 0.5, Tween.TRANS_QUAD, Tween.EASE_OUT)
tween.interpolate_property(newBullet, "translation:y", target.y, origin.y, 0.5, Tween.TRANS_QUAD, Tween.EASE_IN, 0.5)

punkomalo | 2021-04-30 20:19