The Godot Community Forums are back up and running! Please read the the announcement post for important information on what happened. Thanks!

Making a 2D object pulsate using scaling

Hi,

In my 2D platformer, I want a particular object to shrink and grow, to appear as if it's breathing/pulsating. I know I can do this by using an animated sprite (that would seem the best/easiest way)... but I'm now intrigued by the fact that I can't figure out how to do it using the scale.x and scale.y properties.

What I'm trying to make it do is this: start at 0.5 scale, increase the scale by .01 until you get to 1.0, then decrease until you get back to 0.5... then repeat ad infinitum.

Here's my best shot so far:

extends Area2D

onready var bling = get_node("bling")
onready var size_min = 0.5
onready var size_max = 1.0
onready var reverse = false
onready var rate = 0.01

func _process(delta):
    if reverse:
        shrink(rate)
        if scale.x < size_max:
            reverse = false
    else:
        grow(rate)
        if scale.x > size_min:
            reverse = true

func shrink(amount):
        $Sprite.scale.x -= amount
        $Sprite.scale.y -= amount

func grow(amount):
        $Sprite.scale.x += amount
        $Sprite.scale.y += amount

In this state, it shrinks down to 0 (why not 0.5?), then starts growing... but never reverses again and just keeps growing and growing forever, rather than reversing.

Thanks!

Best Answers

  • UnknownUserUnknownUser Posts: 0
    Accepted Answer

    I'm new to Godot myself, but I believe that

    iyour if on line 12 should be "if scale.x < size_min"
    and your if on line 16 should be "if scale.x > size_max"

    when it is growing, you want to reverse when it gets greater than you size_max (and now you compare it with size_min).

    Another option without code (or animatedSprite) is using an animationPlayer.
    You can 'key' the scale.x and scale.y on each frame and let that loop.

    Hope this helps.

  • UnknownUserUnknownUser Posts: 0
    Accepted Answer

    you are comparing the scale of your node, but updating the scale of sprite.

    In your current script:
    line 17 and 22
    if $Sprite.scale.x ....

Answers

  • UnknownUserUnknownUser Posts: 0
    Accepted Answer

    I'm new to Godot myself, but I believe that

    iyour if on line 12 should be "if scale.x < size_min"
    and your if on line 16 should be "if scale.x > size_max"

    when it is growing, you want to reverse when it gets greater than you size_max (and now you compare it with size_min).

    Another option without code (or animatedSprite) is using an animationPlayer.
    You can 'key' the scale.x and scale.y on each frame and let that loop.

    Hope this helps.

  • @aipie love the keyframe suggestion! Will try that if I can't coax it into incrementing until it hits max, then decrementing until it hits minimum.

    Regarding your note on the logic in 12 and 16, that's what I meant to type in my original post, actually! I had it backwards, and I fixed it in my own code after posting.

    And in that state it shrinks down to 0 (ignoring my size_min) and then appears to expand forever... but what I just found is that it's actually just continuing to shrink forever, into negative numbers... apparently Godot takes negative values for scale and uses their absolute value, so it just keeps getting bigger the farther below zero it goes.

    So obviously I have a case of my "if" statements not catching the overshoot on either end...

    Current script:

    extends Area2D
    
    onready var bling = get_node("bling")
    onready var size_min = 0.5
    onready var size_max = 1.0
    onready var should_shrink = true
    onready var rate = 0.02
    
    func _ready():
        $Sprite.scale.x = 1
        $Sprite.scale.y = 1
    
    func _process(delta):
    
        if should_shrink:
            shrink(rate)
            if scale.x <= size_min:
                should_shrink = false
    
        if not should_shrink:
            grow(rate)
            if scale.x >= size_max:
                should_shrink = true
        print ($Sprite.scale.x)
    
    func shrink(amount):
            $Sprite.scale.x -= amount
            $Sprite.scale.y -= amount
    
    func grow(amount):
            $Sprite.scale.x += amount
            $Sprite.scale.y += amount
    

    Time to give my brain a break! Thanks in advance to anyone who can show me where my dumb mistake is :-)

  • UnknownUserUnknownUser Posts: 0
    Accepted Answer

    you are comparing the scale of your node, but updating the scale of sprite.

    In your current script:
    line 17 and 22
    if $Sprite.scale.x ....

  • @aipie I actually posted this yesterday after discovering it myself... or at least I thought I did. I'm not seeing my post now.

    In any case, thanks for sticking with it and noticing the error! It works perfectly now that I'm testing the same thing I'm changing :-)

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file