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!

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 :-)

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 :-)

2 years later