2

Flicky

I am using Godot v3.42-v3.45 to make an implemetation of the boardgame Citadel. In order to make a card move, I develop a tween system. But sometimes the original card node will be "queue_free()"ed immediately after the tween starts, and the card will be gone from the screen and I don't want to wait till it's finished. So I try to make a copy node for just animation, hide the original one, set the final values on the original node, run the tween, show the original node and hide the copied node. But it gets flicky, the copied node seems to blink when the tween is finished. I try a lot of measures but it still blinks. Could anybody help me? Please run the ani_flip_move() function.

extends Node2D

onready var TimerGlobal = get_node("/root/Main/Timer") # a global timer stick to the main scene
onready var Data = get_node("/root/Main/Data") # Data.XXX is just some constants, Data.FAR_AWAY = Vector2(99999, 99999)
onready var Signal = get_node("/root/Main/Signal") # a signal bus stick to the main scene


class Trans:
    var motion_list: Array
    var copies: Dictionary

    func _init() -> void:
        motion_list = []
        copies = {}

    func add(node: Node2D, prop_name: String, start_val, end_val, ani_time: float = 1) -> void:
        var copy
        if node in copies:
            copy = copies[node]
        else:
            copy = node.duplicate(node.DUPLICATE_USE_INSTANCING)
            copies[node] = copy
        node.set(prop_name, end_val)
        motion_list.append([node, copy, prop_name, start_val, end_val, ani_time])


class Interval:
    var wait_time: float

    func _init(times: float) -> void:
        wait_time = times
 

func animate(action_list: Array) -> void:
    var _useless
    
    var tween = Tween.new()
    add_child(tween)
    for action in action_list:
        if action is Trans:
            for motion in action.motion_list:
                var orgi_node = motion[0]
                var copy_node = motion[1]
                var prop_name = motion[2]
                var start_val = motion[3]
                var end_val = motion[4]
                var ani_time = motion[5]
                orgi_node.set(prop_name, end_val)
                orgi_node.set_visible(false)
                if not copy_node.is_inside_tree():
                    add_child(copy_node)
                
                _useless = tween.interpolate_property(
                    copy_node,
                    prop_name,
                    start_val,
                    end_val,
                    ani_time,
                    Tween.TRANS_CUBIC,
                    Tween.EASE_IN_OUT
                )
                
            _useless = tween.start()
            yield(tween, "tween_all_completed")
            
            for motion in action.motion_list:
                var orgi_node = motion[0]
                var copy_node = motion[1]
                if is_instance_valid(orgi_node):
                    orgi_node.set_visible(true)
                    orgi_node.set_z_index(0)
                if is_instance_valid(copy_node):
                    copy_node.set_z_index(0)
                    copy_node.queue_free()
                
        elif action is Interval:
            TimerGlobal.set_wait_time(action.wait_time)
            TimerGlobal.start()
            yield(TimerGlobal, "timeout")
    
    remove_child(tween)
    tween.queue_free()
    Signal.emit_signal("all_ani_completed")

 
func ani_flip_move(
    obj: Node2D,
    end_pos: Vector2 = Data.FAR_AWAY,
    end_scale: Vector2 = Data.FAR_AWAY,
    end_visible: bool = true,
    end_face_up: bool = true,
    ani_time: int = 1
) -> void:
    if end_scale == Data.FAR_AWAY:
        end_scale = obj.scale
    if end_pos == Data.FAR_AWAY:
        end_pos = obj.global_position
    
    var a1 = Trans.new()
    var z_index = obj.z_index
    a1.add(obj, "global_position", obj.global_position, end_pos, ani_time)
    a1.add(obj, "scale", obj.scale, end_scale, ani_time)
    a1.add(obj, "z_index", 1, 1, ani_time)
    if "face_up" in obj:
        a1.add(obj, "face_up", obj.face_up, end_face_up, ani_time)
    animate([a1])
    

Ron
  • 21
  • 2
  • Hey, why would the original card be queue_freed? I think duplicating the Scene is just a bandage over the underlying problem, have you tried connecting the TweenAllCompleted signal to a new function? Sometimes I've had unexpected results using the yield function. – NautMeg Aug 16 '22 at 19:11
  • I can yield and put two stacks of code into one function. So sometimes there is removal of the card objects if the user discards or something. – Ron Aug 26 '22 at 11:16
  • @NautMeg Do you mean yield behaves differently when putting inside or outside of a function? – Ron Aug 26 '22 at 11:17

0 Answers0