What is the best way to smoothly move text at speeds that dynamically vary?

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

I’m working on a Teleprompter in Godot. For this I need to move text on the screen smoothly with precise timing and with speeds that need to be able to vary on the fly.

To do this, I’ve been using the Label control, and I’m moving it’s position with rect_position. I’m not using Tween or AnimationPlayer since I need to be able to programmatically vary and adjust the movement speed dynamically during movement, which as far as I know, Tween and AnimationPlayer don’t allow for. The Label I’m moving is not large (the Label rect_size.x is 1800 pixels) since I wanted to insure the size of the Label didn’t have a negative impact on the movement.

The problem I’m running into is that the text movement is not smooth, regardless of how I set the Timer or adjust the rect_position increment changes of the Label.

Below is a snippet of my relevant code. Note I have rect_position.x - 20, which moves the Label by large increments and not smoothly. However, If I set it to -1 the Label moves smoothly but not quickly. If I set the timer to timeout more often, I would expect to be able to set the Label movement to -1 and still have it move quickly and smoothly, however that is not the case (it moves smoothly but not quickly).

var timer = Timer.new()

# timer wait time set to 30 times a second
timer.wait_time = (float(1) / float(30))

timer.connect("timeout", self, "_on_timer_timeout")
add_child(timer)
timer.start()

func _on_timer_timeout():
    if $LabelA.rect_position.x >= 0:
        $LabelA.rect_position = Vector2($LabelA.rect_position.x - 20, $LabelA.rect_position.y)

Is there a better way to move text? Keep in mind I need to be able to adjust speed dynamically during movement and still have smooth movement. Perhaps I should be doing this another way entirely, without a Label and a Timer? Feel free to suggest a better implementation and disregard my code.

Any help is greatly appreciated! Thanks.

Upon further testing and found that increasing/decreasing rect_position.xwithinfunc _process(delta):which is called every frame of the main loop, results in much smoother movement of a Label than using a Timer.

Any further advice/improvements are welcomed. Thanks.

nitro | 2021-02-11 09:01

you can also try multiplying the speed by delta

rect_position.x -= 20 * delta

bloodsign | 2021-02-11 19:00

Thanks! Good advice since multiplying by delta will insure consistent movement.

nitro | 2021-02-12 09:11

:bust_in_silhouette: Reply From: yrtv

Can animate any property https://youtu.be/18Em80Bfjp4?t=255

Thanks. I’m not sure the AnimationPlayer will work for my purposes, since I need to be able to dynamically change the movement speed on the fly. So for example, if AnimationPlayer is used, can the animation speed be adjusted dynamically based on the movement of an analog joystick input during the animation?

nitro | 2021-02-12 09:15

technically yes, since you can actually edit Animation Track Properties via script.

$AnimationPlayer.get_animation(“YourAnimationName”).track_set_key_value(track_key_index:int, key:int, value:Variant)

track_key_index is the track of your animation that you want to edit, since animation can have several tracks(starting from 0). Key is the index(starting from 0) of the Animation key in the timeline (the diamond thingies you set)
and finally the value, that you want to change.

For example, let’s say I have an animation that moves a square sprite and scale it.
the track would be:

Sprite
  [/] <> position:     <0>                                   <1> <2>     <3>
  [/] <> scale:                             <0>              <1>         <2>

position’s track_key_index would be 0,
and scale’s track_key_index would be 1,

I would then access the Keys(the diamond thingies on the timeline) starting at index 0 from left to right. Then change their value to however I want. Likeso:

var anim = $AnimationPlayer
#code....code#
anim.get_animation("MoveSprite").track_set_key_value(0, 0, Vector2(2,4))

As for Animation Speed, although I haven’t found a situation to use it yet. Under Playback Options in the [Inspector] Tab of your AnimationPlayer, there are properties such as Process Mode, Default Blend time and Speed, which we can probably access and modify via script.
(whispers: To be honest, I’ve only messed with the AnimationPlayer via script for my global background music tracks in order to dynamically change their volume. I kinda have an autocrossfade when changing scenes using the AnimationPlayer, so I had to acess the volume properties and make sure they don’t exceed the current set volume in the settings…anyways I digress)

bloodsign | 2021-02-12 11:53

You can manipulate text speed in many ways. For simple cases playback_speed will be enough. (movement occurs in frames adjust between frames)

yrtv | 2021-02-12 22:34