animationgodotgdscripttween

How to loop tweens without repeating similar code segments?


I'm oscillating my character between 2 positions as such:

Idle -> Run & move right -> Idle -> Run & move left -> (Repeat)

extends Sprite

func _ready():
    var tween = get_tree().create_tween().set_loops()

    ## Idle 1 ##
    tween.tween_callback(animation_player,"play",["Idle"]) # plays idle animation 
    tween.tween_interval(2)
    ##

    ## Running 1 ##
    tween.tween_callback(animation_player,"play",["Running"]) # starts running animation
    tween.tween_property(self,"flip_h", false, 0)
    tween.tween_property(self,"position:x", 500.0, 2) # move position to 1000
    ##
    
    ## Idle 2 ##
    tween.tween_callback(animation_player,"play",["Idle"]) # plays idle animation 
    tween.tween_interval(2)
    ##
    
    ## Running 2 ##
    tween.tween_callback(animation_player,"play",["Running"]) # starts running animation
    tween.tween_property(self,"flip_h", true, 0)
    tween.tween_property(self,"position:x", -500.0, 2) # move position to 1000
    ##

and it works fine but the issue is that I have to write the Idle & Run Segment twice, which is really annoying

I tried this:

func _ready():
    var tween = get_tree().create_tween().set_loops()

    ## Idle ##
    tween.tween_callback(animation_player,"play",["Idle"]) # plays idle animation 
    tween.tween_interval(2) # pause for 2 seconds
    ##

    ## Running ##
    tween.tween_callback(animation_player,"play",["Running"]) # starts running animation
    tween.tween_property(self,"flip_h", !flip_h, 0)
    tween.tween_property(self,"position:x", position.x*-1, 2) # move position to 1000
    ##

but it seems that the literal value of the variable gets passed instead of the new one each time the loop runs

Is there anything I'm missing? or is there no work-around for this?


Solution

  • This is working as intended. When you create the tweens the values are recorded. So that !flip_h is recorded, and that position.x*-1 is recorded.

    As per workaround… This is what I have been able to come up with:

    var flip_position:float
    
    var advancement:float setget set_advancement
    func set_advancement(mod_value:float) -> void:
        advancement = mod_value
        position.x = flip_position + mod_value * (-1.0 if flip_h else 1.0)
    
    func do_flip() -> void:
        flip_h = !flip_h
        flip_position = position.x
        advancement = 0.0
    
    
    func _ready() -> void:
        var tween := get_tree().create_tween().set_loops()
    
        ## Idle ##
        tween.tween_callback(animation_player,"play",["Idle"])
        tween.tween_interval(2)
        ##
    
        ## Running ##
        tween.tween_callback(animation_player,"play",["Running"])
        tween.tween_callback(self,"do_flip")
        tween.tween_property(self,"advancement", 500.0, 2)
        ##
    

    Here I'm using a do_flip method so flip_h can change value. Furthermore, I'm using flip_h to know what direction it should run, and in flip_h I store from where it should run. Then I can make an advancement property which moves the character from the recorded position.