Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.
Visual Easing Function13eckI found [this site](https://easings.net/) that show animated values for the various easing + transition combos (also linked in the Godot docs for tweens)211Mar. 01, 2024
Position and scale at the same timeIxillowWhen we were testing the tween animations in _ready function the gem first changed position, and when reached final position it starts to grow.
Is posible to change the scale while is moving?78Feb. 25, 2024
How to tween object's opacity?FumoI wanted to tween the object so it'll disappear slowly on touch, by changing it's visibility, i couldn't find a "opacity"/"transparency" property so i wonder how you would go about doing that.
i did that with scale so it'll disappear by decreasing it's size to 0.
```gdscript
func _on_area_entered(area: Area2D) -> void:
play_disappearance_animation()
func play_disappearance_animation():
var tween := create_tween()
var sprite := get_node("Sprite2D")
var target_size := Vector2(0.0, 0.0)
var duration := 0.5
tween.tween_property(sprite, "scale", target_size, duration)
tween.finished.connect(queue_free)
```83Mar. 31, 2024
Make the Collision trigger visible in play?MartinBI wanted to see if the CollisionShape2D node was moving **with** the sprite2D node when it floated.
Though it's probably not because it's not a child of the Sprite2D node if I'm right?33Mar. 03, 2024
Mac bug fix typo?arhinostormI'm on mac running 4.2.0 so I can run the lesson plugins. The fix for the tween bug has a typo in it. I think it should be:
`sprite_2d.position = -1.0 * position_offset`
instead of:
`sprite_2d.position.y = -1.0 * position_offset`
Trying to apply the vector to the y property was crashing Godot for me.
63Feb. 21, 2024
Tween_property()BoomsquallyFor the last two lines of code in the play_floating_animation function, in the tween_property function argument, why is position in quotations?
I keep thinking quotations are when something is a string or, if in brackets, we're getting something from the scene dock.12Mar. 08, 2024
Could I use the animation tab, instead of Tween?Lucas88Hi Nathan
Thanks for the course it has been incredibly helpful so far.
I wanted to ask if is there a reason why we use Tweens in this lesson instead of using the animation tool that Godot has in its interface(Using an AnimationPlayer node)?
Thanks21Aug. 19, 2024
Difference with tween on area2d vs tween on sprite.TechosHello! This chapter made me want to try and implement moving the area2d collision along with the sprite as the tween animation plays out. While doing so the Gem/HealthPack would fly to (0,0) first, and then act out the tween properly. I realized after looking through another comment on this forum that it was because I didn't include the position when initializing the position_offset variable like shown.
```gdscript
var position_offset := Vector2(0.0, 4.0) # Missing "global_position +"
var negative_offset := Vector2(0.0, 4.0) # Missing "global_position -"
var duration = randf_range(0.8, 1.2)
tween.tween_property(area2d, "position", position_offset, duration)
tween.tween_property(area2d, "position", negative_offset, duration)
tween.set_loops()
```
Still I thought it'd make for a good question since I'm not sure why it goes to (0,0), or why we specify the position for the area2d and not the sprite like how it is shown in the course.11Jul. 11, 2024
Speed difference the first time the item goes downiDieHello,
I have noticed that the item goes down at a slower speed the first time, which seems to make sense since the duration remains the same but the distance is half of the subsequent times.
I tried to solve this by dividing the duration by 2 and use those tweening properties:
```gdscript
tween.tween_property(sprite_2d, "position", position_offset, duration).set_trans(Tween.TRANS_SINE)
tween.tween_property(sprite_2d, "position", Vector2.ZERO, duration).set_trans(Tween.TRANS_LINEAR)
tween.tween_property(sprite_2d, "position", -1.0 * position_offset, duration).set_trans(Tween.TRANS_SINE)
tween.tween_property(sprite_2d, "position", Vector2.ZERO, duration).set_trans(Tween.TRANS_LINEAR)
```
Is that a good solution or is there a better way to do this?
Thanks in advance!11Feb. 28, 2024
set_loops() function, How it exactly works?unhappy-dolphinHello,
For the set_loops function, you said "This function only affects animations created after it". However, when I write it at the end of the code, the animations still loops, why is that?
Also, how can I pick which animation to loop and which not?
```gdscript
func play_floating_animation() -> void:
var tween := create_tween()
tween.set_trans(Tween.TRANS_SINE)
var sprite_2d := get_node("Sprite2D")
var position_offset := Vector2(0.0, 4.0)
var duration = randf_range(0.8, 1.2)
tween.tween_property(sprite_2d, "position", position_offset, duration)
tween.tween_property(sprite_2d, "position", -1.0 * position_offset, duration)
tween.set_loops()
```41Feb. 25, 2024
Question about tweens.EasySpeedsFor nodes that are no longer needed, we use `.queue_free()` Tweens have a `.kill()` method. Is this used for the same purpose as queue_free() or are tweens automatically taken care of? My example below is to tween a health bar to dynamically fade in/out when health changes. The node is not removed, but multiple tweens are made each time the health changes.
```gdscript
func fade_in() -> void :
_reset_fade_timer() # on timer.timeout, fade_out() if health == MAX_HEALTH
var tween = create_tween()
tween.tween_property(self, "modulate:a", 1, FADE_DURATION)
tween.finished.connect(tween.kill) # is this necessary?
```10Oct. 22, 2024
Using a sine wave instead of tweensJohnyWuijtsNLBefore doing the lesson, I tried adding the animation myself. I ended up doing this:
```gdscript
var timer := 0.0
func _process(delta: float) -> void:
timer += delta
get_node("Sprite2D").position.y = sin(timer * 3) * 10
```
Then I did the lesson and was surprised that there was a whole tween system for that, is there a benefit to using that instead of just using a sine wave? I get that it is handier to use tweens when making more complex animations, but in this case I don't see the advantage.10Oct. 20, 2024
Skip last part of a loopill-fated-heronHi,
I'm trying to apply a similar logic on another project. The idea is I have an axe that switch from left to right. Then it switch back to left. After 2 loops, I want to axe to disapear. The following code is working fine. However, the axe disapear when she is rotated to the left, I would like that she disapear when she his rotated at the right position. In other word, skipping the last tween property for the last loop but I didn't find a way to achieved that, any suggestion?
```gdscript
var tween := create_tween()
var duration = randf_range(0.4, 0.7)
tween.set_loops(2)
tween.set_trans(Tween.TRANS_BOUNCE)
tween.tween_property($Axe, "rotation_degrees", 0.0, duration)
# SKIP this for the last loop
tween.tween_property($Axe, "rotation_degrees", -90.0, duration)
tween.finished.connect(func() -> void:
queue_free())
```10Oct. 16, 2024
How to make death animationglaring-hippopotamusI'm trying to make a death animation for items, and just have them fade out. Currently they are freed before the animation really plays. is there a way to wait for the animation to finish before running the next lines of code?
```gdscript
func play_death_animation():
var tween := create_tween()
var sprite := $Sprite2D
var duration := 2
tween.tween_property(sprite, "scale", Vector2(0, 0), duration)
func _on_area_entered(area_that_entered: Area2D) -> void:
play_death_animation()
queue_free()
```20Sep. 17, 2024
How can I use a custom Curve resource that I created in a tween?next-craneI don't want to use the built-in curves; I want to create a custom curve and use it in the tween. Is that possible?10Sep. 16, 2024
why create_tween()evil-reindeeri know this is more towards the game engine developers question, sorry but coming from web development i wondered why not new Tween(), those function names seems hard to remember for me 😂10Sep. 11, 2024
When to start own project?davidakWe already learned a lot to this point. I'm questioning when would be a good point to start with own projects.
I plan to start simple with a game where you click a button and a number increases. That should be straight forward. But we haven't used buttons yet.
So, from an educational perspective, would it be best to finish this course before creating own projects or would it be OK to look stuff up like buttons?10Aug. 26, 2024
Movement isn't synced with monitor?exciting-tarsierHi, so I've been really happy with the course overall, but I'm having an issue that doesn't seem to be addressed at all - and that is when I'm moving, there's a very visible "afterimage", it's very unpleasant to look at. If I tie the camera to the ship the ship itself behaves well, but if I fly around the pickups, it's hard not to notice that the pickups smudge.
It certainly is related to the monitor somehow since the effect is much more visible on one monitor than it is on the other - but it's present on both. Thanks in advance10Jul. 05, 2024
Multiple question about courseHazlarGood evening,
I wanted to know in our examples of tweens, since we modify the `sprite2D` node but which is part of `Area2D` and a `CollisionShape` is the interpolation widened with the elements in which it evolves (as if my body was an area2d+colShape and if I increase the size of my liver, the whole body grows in order to keep the same proportions). I have the impression that no but is it possible to do it?
Either in the script of the scene itself by creating parallel interpolations? or by using the gem scene instantiated in the space level scene with a script attached to the level node? (If `gem` is instantiated in another scene, are these nodes "merged" so that a single interpolation is enough?)
Thnaks 10Jul. 04, 2024
Ship teleports randomly or disappears when running space_level.tscnPixelbladeI completed the "Make The Items Float" lesson and all works well when I run the item.tscn. The gem animates correctly as expected. When I run the space_level.tscn, all appears normal at first but then the ship starts to randomly jump. When I collect a gem or health pack, the ship will teleport across the screen. Sometimes, the viewport will shift entirely when collecting an item. The code appears identical to the lesson reference.
What did I miss? I captured video of the issue if there is a way to upload it.
Below is my code for each scene. Thank you!
**ship.gd**
```gdscript
extends Area2D
# Declare member variables
###########################################
var max_speed: float = 500.0
var velocity: Vector2 = Vector2(0, 0)
var steering_factor: float = 3.0
var health: int = 10
var gem_count: int = 0
# Initialize variables and connect signals
###########################################
func _ready() -> void:
area_entered.connect(_on_area_entered) # connects signal at game start
set_health(health) # set's healthbar to match health variable at game start
# Calls for every frame
###########################################
func _process(delta: float) -> void:
# User input
var direction := Vector2(0, 0)
direction.x = Input.get_axis("move_left", "move_right")
direction.y = Input.get_axis("move_up", "move_down")
if direction.length() > 1.0:
direction = direction.normalized()
# Ship turning smoothing
var desired_velocity := max_speed * direction
var steering := desired_velocity - velocity
velocity += steering * steering_factor * delta
position += velocity * delta
# wrap ship position around viewport screen
var viewport_size: Vector2 = get_viewport_rect().size
position.x = wrapf(position.x, 0, viewport_size.x)
position.y = wrapf(position.y, 0, viewport_size.y)
# turn ship in direction of travel
if velocity.length() > 0.0:
# rotation = velocity.angle() -> this roated the Ship: Area2D and all child nodes
get_node("Sprite2D").rotation = velocity.angle() # this rotates Sprite2D and child nodes only
# Set signal responses
###########################################
func set_health(new_health: int) -> void:
health = new_health
get_node("UI/HealthBar").value = health # value property in healthbar is assigned value in var health
func set_gem_count(new_gem_count: int) -> void:
gem_count = new_gem_count
get_node("UI/GemCount").text = "x" + str(gem_count)
# signal callback function
func _on_area_entered(area_that_entered: Area2D) -> void:
if area_that_entered.is_in_group("gem"):
set_gem_count(gem_count + 1)
elif area_that_entered.is_in_group("healing_item"):
set_health(health + 10)
```
**gem.gd**
```gdscript
extends Area2D
func _ready() -> void: # called once when node is loaded. good place to connect signal
area_entered.connect(_on_area_entered)
play_floating_animation()
func play_floating_animation():
var tween: Tween = create_tween()
tween.set_trans(Tween.TRANS_SINE)
var sprite_2d: Sprite2D = get_node("Sprite2D")
var position_offset: Vector2 = Vector2(0.0, 4.0)
var duration: float = randf_range(0.8, 1.2)
tween.tween_property(sprite_2d, "position", position_offset, duration)
tween.tween_property(sprite_2d, "position", position_offset * -1.0, duration)
tween.set_loops() # no arguments makes it loop indefinitely
func _on_area_entered(signal_arguments_bucket: Area2D) -> void:
queue_free()
```
**health_pack.gd**
```gdscript
extends Area2D
func _ready() -> void: # called once when node is loaded. good place to connect signal
area_entered.connect(_on_area_entered)
play_floating_animation()
# create the tween
# create values for each of the tween arguments, except the property
# tween takes several arguments: node affected, node property to animate,
# target value, duration of animation
# animate the property using tween_property() function
func play_floating_animation():
var tween: Tween = create_tween()
tween.set_trans(Tween.TRANS_SINE)
var sprite_2d: Sprite2D = get_node("Sprite2D")
var position_offset: Vector2 = Vector2(0.0, 4.0)
var duration: float = randf_range(0.8, 1.2)
tween.tween_property(sprite_2d, "position", position_offset, duration)
tween.tween_property(sprite_2d, "position", position_offset * -1.0, duration)
tween.set_loops() # no arguments makes it loop indefinitely
func _on_area_entered(signal_arguments_bucket: Area2D) -> void:
queue_free()
```
**random_item_placer.gd**
```gdscript
extends Node2D
# preload the scenes to make them available as resources
var item_scenes: Array = [
preload("gem.tscn"),
preload("health_pack.tscn"),
]
# connect the timer signal
func _ready() -> void:
get_node("Timer").timeout.connect(_on_timer_timeout)
# signal callback - add random item
func _on_timer_timeout() -> void:
var random_item_scene: PackedScene = item_scenes.pick_random()
var item_instance := random_item_scene.instantiate()
add_child(item_instance)
# place random item at random location
var viewport_size: Vector2 = get_viewport_rect().size
var random_position: Vector2 = Vector2(0,0)
random_position.x = randf_range(0.0, viewport_size.x)
random_position.y = randf_range(0.0, viewport_size.y)
item_instance.position = random_position
```10Jun. 21, 2024
Overall errorswell-groomed-seahorseI managed to get all the end. The only problem I have is that the item's random placer and the warping of the ship both seem to have the centre offset to the bottom right of the screen. When I start the space level, the items spawn only in the bottom right corner. I like the centre of the screen. Is like the top right corner of the spawner. Furthermore, when I move the ship, the same thing happens: it only appears in the bottom right corner and nowhere else on the screen.
I have checked the code, and it's the same. I have also tried moving the different objects' locations or offsets, but it still happens. I think it might be something to do with accidentally pressing something in the engine. Would be nice to know what it is. 30Jun. 21, 2024
Is it okay to tween the Area2D position so the collision shape would follow the animation?Lucas PscheidtI experimented making this code for tweening the Area2d node:
@onready var sprite_2d: Sprite2D = $Sprite2D
func play_floating_and_sacling_animations() -> void:
var tween:= create_tween()
var target_position := global_position + Vector2(0.0,4.0)
var neagtive_target_position := global_position - Vector2(0.0,4.0)
var animation_duration := 1.0
#Tween position:
tween.tween_property(self, "position", target_position, animation_duration)
tween.parallel()
tween.tween_property(self, "scale", Vector2(1.05, 1.05), animation_duration)
#Tween scale:
tween.tween_property(self, "position", neagtive_target_position, animation_duration)
tween.parallel()
tween.tween_property(self, "scale", Vector2(0.95, 0.95), animation_duration)
tween.set_loops()
func _process(delta: float) -> void:
global_position = sprite_2d.global_position
--
Is it a good ideia or could it cause some issue/performance issues? Is there a better way?30May. 30, 2024
Questions about Sprite and Collision Shape movementMuseDoesHi, love the lessons they are super helpful!
I have some questions about collision shapes, so please forgive me for the long post.
I noticed while playing around with the position offset values that there would be times when the ship didn't pick up the collectible. After reading through the comments to see if anyone else had a similar issue, I saw one that mentioned how to turn on collision shapes in debug menu, but not how to get them to move together.
After a LOT of trial and error, I finally managed to get it to work, though I'm not sure if there is a better way. Along the way I came up with some questions:
Q1:
When I made the Collision Shape a child of the Sprite2D, they do move together, but the collision shape no longer detects the ship. Why?
Q2:
When I changed the sprite_2d variable to include the collision shape node.
var sprite_2d := get_node("Sprite2D") and get_node("CollisionShape2D")
I got an Invalid Argument error saying that Argument 1 should be an "Object", but is a "bool". I don't understand how using two objects in a variable becomes a boolean.
Q3:
This question is more about best practices. How do you decide when the code your working on is good enough? Like, how do you determine when you no longer need to try to simplify or streamline your work?
By the way, this is the code I used to get the Sprite2D and CollisionShape2D to move together:
func play_floating_animation():
var tween := create_tween()
tween.set_trans(Tween.TRANS_SINE)
var sprite_2d := get_node("Sprite2D")
var collision_2d := get_node("CollisionShape2D")
var position_offset := Vector2(0.0, 40.0)
var duration := randf_range(0.8, 1.2)
tween.tween_property(sprite_2d, "position", position_offset, duration)
tween.parallel()
tween.tween_property(collision_2d, "position", position_offset, duration)
tween.tween_property(sprite_2d, "position", -1.0 * position_offset, duration)
tween.parallel()
tween.tween_property(collision_2d, "position", -1.0 * position_offset, duration)
tween.set_loops()30May. 21, 2024
Tween up and down after - how does the code handle this?hefty-alpacaHi All, great lesson once again! I just had one question regarding the tween. So first the tween brings the icon down and then up, we call each direction after each other.
My question is, how does the code know that there's an order of operations here? I'm asking because just looking at the code, to me it says: When the node is ready, call the play_floating_animation() function -> the function calls the two tweens. Does it call the second tween only after the duration of the first one is over?10May. 20, 2024
Tween Bug on windowsalanlovesgamesI also have the position reset when looping the tween, it first goes in diagonal to the initial position before the tweens and only then starts floating, im on windows 10 using the 4.2.1 version.
Fixed it by resetting the nodes positions to 0,0: i might have moved the node scenes around individually at some point so maybe thats what was causing it, this means both the 2d sprite and the collision shape had to be reset to 0,0.
I think because we tell the sprite to tween from a specific vector it first has to go there and only then start tweening, though why it doesnt just automatically start at that point is beyond me. hope that helps! :)
10May. 09, 2024
tween_property rotationperiodic-skunkJust a friendly reminder to folks who want to mess with rotation. The unit will be in radians so you have to convert it. n*180/**π**10May. 03, 2024
set_loops() orderingill-fated-heronHello,
When you are explaining the `set_loops()`, you are writing the following:
We can use tween's set_loops() function to loop the float animation. It takes a single optional argument: the number of times to repeat the animation. If you pass no argument, the animation loops indefinitely. That's what we want!
This function affects all animations in the tween. **In other words, whether you call this function before or after adding properties to tween, it will affect all animations the same way.**
Then, while explaining the `set_trans()`, you are writing the following:
I'll explain the transition types in a moment. **But first, like the set_loops() function, we must call it before calling the tween's tween_property() function.**
So, I'm a little bit confused, does calling `set_loops()` before or after matters or not?50Apr. 25, 2024
Var creation in functions. Why not outside?irate-conquerorWe made all our vars in the play_floating_animation function. Would there be any detriment to making in outside this and putting it just below "extends Area2D"?
I was thinking of adding a vanishing animation followed by a queue_free(), and it seems like having an object var for tween or sprite_2d could be helpful.
Another instance I saw of this would be in ship.gd, creating a viewport_size var at the top instead of in _process (unless the viewport is going to change sizes?).40Apr. 24, 2024
Small inconsistency on the example codejavipastUnder the **Use a transition function** section, the example code suggests to set the transition type after the `set_loops()` call, which following the steps probably is set at the end of the method, after the `tween_property` definitions:
```gdscript
func play_floating_animation() -> void:
var tween := create_tween()
tween.set_loops()
+ tween.set_trans(Tween.TRANS_SINE)
# ...
```
It won't make the tweens apply that easing function (at least that's my experience on v4.2.1).
`set_trans` must be called before `tween_property` in order to make them use the transition. This is already correct in the code reference, but could lead to confusion initially while going step by step.
Keep the great job! 40Apr. 09, 2024
Gem and HealthPack don't have the same tweek at the endLhukHey! I don't know how to explain that but I correctly follow all the instructions but at the end my gems move as intended but my healthpack move diagonally before stopping and tween as they normally do first. It's pretty funny to see it. 20Apr. 07, 2024
Does the tween_property() "add" the position_offset value ?LymoHello guys, I thought during the first example with "target_position" that the tween_property() would set sprite_2d.position **=** target_position as the animation progressed, but in the final use with "position_offset" i realized that it seems to do sprite_2d.position **+=** position_offset.
I'm not sure to understand well, could you help ?20Apr. 03, 2024
Sine not explained.NoneApplicableGamesOkay so this chapter does a great job of introducing tweens with a practical example. However I am a little concerned that users might not know what TRANS_SINE or what a sine wave is. maybe it would be good to create a sidebar explaining this?30Mar. 21, 2024
Typo: NewwerJankiKhan"Godot 4.2.1 fixed this issue, but 4.2.1 and and newwer versions of the engine are known to have some crashes on macOS."
There's a typo in "newwer".40Mar. 19, 2024
Correction for macOS workaround...edmunditoThe code shows:
```gdscript
+ sprite_2d.position.y = -1.0 * position_offset
# But it should be position_offset.y:
+ sprite_2d.position.y = -1.0 * position_offset.y
```30Mar. 09, 2024
This is my 1st animation.tesfalconThis tween animation is the 1st animation that I've used in my game. After some tweaking it looks good. How do I make it stop later in code?10Mar. 09, 2024
How can i make the tween values randomize each loopMlemilyHow can i make the tween values randomize each loop?
So im trying to add the sparkles with tweens and i want the sparkle to go to a different direction each loop.
I added a sprite_2d with the sparkles png under the gem's sprite_2d.
I managed to loop it so the sparkle will move and scale up a bit and then return to its original position but it keeps the same numbers that i generated each loop, so the sparkle will go to the same direction each loop, i tried using the process function but it happens there aswell, i tried generating the numbers inside the tween property instead of a variable, i tried generating the numbers outside the sparkles functions and still the same, i also tried using normal loops like for and while but looks like they dont really work with tweens.
code:
```gdscript
func play_sparkles() -> void:
var tween := create_tween()
tween.set_trans(Tween.TRANS_SINE)
tween.set_loops()
var sprite_2d := $Sprite2D/Sparkles
var duration = randf_range(0.8, 1.2)
var ran_scale = randf_range(0.4, 0.8)
var ran_pos := Vector2(randf_range(-10, 10), randf_range(-40.0, -50.0))
#sprite, what to animate, size, duration
tween.tween_property(sprite_2d, "position", ran_pos, duration)
tween.parallel()
tween.tween_property(sprite_2d, "scale", Vector2(ran_scale, ran_scale), duration)
tween.tween_property(sprite_2d, "position", $Sprite2D/Sparkles.position, 0)
tween.tween_property(sprite_2d, "scale", $Sprite2D/Sparkles.scale, 0)
```20Feb. 27, 2024
Object restarts its position after each loopVohajusHey Nathan,
On my end, the item seems to "restart" its position after each loop.
It comes down, up and then suddenly back to Vector2(0.0,0.0). Then, down, up, back suddenly to Vector2(0.0,0.0), so on and so forth...
It does this, even when i copy paste your code reference on my script.
Any ideas on the subject ?
Thanks for this great lesson !50Feb. 20, 2024
Lesson Q&A
Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.