KowalewskajA
KowalewskajA

Reputation: 23

Tweening a Rect2 in Godot 4.1

I wanted to tween the size of a Rect2 in Godot. But as Rect2 is not on Object tween_property() is not working. Hence I decided to tween it via tween_method().

The tween_method() is working and I can see the animation via draw_rect(). But as the object has more than one Rect2 I want to give a reference to what Rect2 to tween to the method call via .bind().

But when I .bind() I only receive a copy by value. So I alter the size ob the copy and not the original Rect2. Is there a way around to make it work in a dynamic way?

Here is the code of Cross.gd that you can use to instanciate a Cross object in you root scene via:

cross = Cross.new()
add_child(cross)

Cross.gd:

class_name Cross extends Node2D

var rect_1:Rect2
var rect_2:Rect2
var tween:Tween

func _init(r1=Rect2(400, 300, 50, 200), r2=Rect2(400, 300, 200, 50)):
    rect_1 = r1
    rect_2 = r2

# Called when the node enters the scene tree for the first time.
func _ready():
    tween = create_tween()
    tween.set_ease(Tween.EASE_IN_OUT)
    #tween.tween_method(change_width, 50, 0, 1)
    tween.tween_method(change_width_dyn.bind(self.rect_1), 50, 0, 1)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    queue_redraw()

func _draw():
    draw_rect(
        Rect2(
            rect_1.position.x - rect_1.size.x/2,
            rect_1.position.y - rect_1.size.y/2,
            rect_1.size.x,
            rect_1.size.y
        ), Color.WHITE
    )
    draw_rect(
        Rect2(
            rect_2.position.x - rect_2.size.x/2,
            rect_2.position.y - rect_2.size.y/2,
            rect_2.size.x,
            rect_2.size.y
        ), Color.WHITE
    )

func change_width(val:int):
    rect_1.size = Vector2(val, rect_1.size.y)
    print(rect_1)

func change_width_dyn(val:int, r:Rect2):
    r.size = Vector2(val, r.size.y)
    print(r)
    print(rect_1)


Refactored Cross.gd:

class_name Cross extends Node2D

var rect_1:Rect2
var rect_2:Rect2
var tween:Tween

func _init(r1=Rect2(400, 300, 50, 200), r2=Rect2(400, 300, 200, 50)):
    rect_1 = r1
    rect_2 = r2

# Called when the node enters the scene tree for the first time.
func _ready():
    tween = create_tween()
    tween.set_ease(Tween.EASE_IN_OUT)
    tween.tween_property(self, "rect_1:size:x", 0, 1.0)
    tween.tween_property(self, "rect_2:size:y", 0, 1.0)
    tween.tween_property(self, "rect_1:size:x", 50, 2.0)
    tween.parallel().tween_property(self, "rect_2:size:y", 50, 2.0)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    queue_redraw()

func _draw():
    draw_rect(create_printable_rect(rect_1), Color.WHITE)
    draw_rect(create_printable_rect(rect_2), Color.WHITE)

func create_printable_rect(r:Rect2):
    return Rect2(
        r.position.x - r.size.x/2,
        r.position.y - r.size.y/2,
        r.size.x,
        r.size.y
    )

Upvotes: 1

Views: 333

Answers (1)

Theraot
Theraot

Reputation: 40295

You should be able to use tween_property. You pass the self as object, and then the name of the rect:

tween.tween_property(self, "rect_1", …)

In particular you seem to want to tween the y of the size, which I believe would be like this:

tween.tween_property(self, "rect_1:size:y", 50, 0, 1)

Yes, we could make it work over tween_method by binding the name of the rect and using get and set inside of change_width_dyn, but I don't see the point in doing so.

Upvotes: 0

Related Questions