How To Reverse An Animation In Godot
In this tutorial we will learn how to use the AnimatedSprite node to animate sprites. In particular, we volition animate our player past adding idle animations, walk animations and two types of attacks (sword and fireball).
Preparing player node
Permit's open the SimpleRPG project and selection up where we left off in the last tutorial. To get started, we need to import all the blitheness frames into the project. Download player sprites by pressing the push button below.
Download "SimpleRPG Thespian Frames" player_frames.zero – 35 KB
In the FileSystem panel, delete player.png, import all new images and put them in the Entities/Player folder.
Select all the images you merely added, go to the Import console, disable Filter and click on Reimport.
Back to the Scene panel, right-click on the Sprite node and choose Modify Type.
Select AnimatedSprite and press the Change button.
One time the node type is changed, a yellow triangle appears next to Sprite. This alert tells united states of america that we need to create a SpriteFrames resource to show something on screen.
SpriteFrames is a resource (i.e. a data container) that contains all the textures that we volition utilize as frames, too as the list of all animations with their backdrop (speed, loop playback, etc.)
To create a SpriteFrames resource, get to the Inspector, click on [empty] next to the Frames property and select New SpriteFrames.
Click on the newly created SpriteFrames resource. The SpriteFrames editor will open.
The SpriteFrames editor
The SpriteFrames editor console is divided into 2 columns. The left column lists all the animations, while on the right there is the listing of the frames that brand up the selected blitheness.
The left cavalcade has a toolbar with ii buttons, i to add a new animation and i to delete the selected animation. At the bottom of the column, yous can gear up the playback speed (in frames per second) and decide whether the animation should be looped or not.
In the toolbar of the right column in that location are 8 buttons:
- Load Resource: to add together a resource to the animation frames. More simply, sprites can be dragged and dropped from the FileSystem panel.
- Copy: copy the selected frame.
- Paste: paste the previously copied frame.
- Insert empty earlier: inserts an empty frame earlier the selected ane.
- Insert empty after: inserts an empty frame later the selected one.
- Motility before: move the selected frame back one position.
- Movement subsequently: move the selected frame forrard one position.
- Delete: deletes the selected frame.
To start, rename the default animation past clicking on it and call information technology down_idle. Drag the player_down_idle_1.png and player_down_idle_2.png files from the FileSystem panel to the right side of the SpriteFrames editor and then gear up Speed (FPS) to ane.
Now, in the Inspector, enable the Playing property. You will see the sprite animate with the newly created idle blitheness.
With the aforementioned process, create all the other animations. The table below contains all the information you need to create them.
| Animation proper name | Frames | Speed (FPS) | Loop |
| down_attack | player_down_idle_1.png player_down_attack_1.png player_down_attack_2.png | 7 | Off |
| down_fireball | player_down_idle_1.png player_down_fireball_1.png player_down_fireball_2.png | 7 | Off |
| down_idle | player_down_idle_1.png player_down_idle_2.png | 1 | On |
| down_walk | player_down_idle_1.png player_down_walk_1.png player_down_idle_1.png player_down_walk_2.png | ten | On |
| left_attack | player_left_idle_1.png player_left_attack_1.png player_left_attack_2.png | vii | Off |
| left_fireball | player_left_idle_1.png player_left_fireball_1.png player_left_fireball_2.png | seven | Off |
| left_idle | player_left_idle_1.png player_left_idle_2.png | 1 | On |
| left_walk | player_left_idle_1.png player_left_walk_1.png player_left_idle_1.png player_left_walk_2.png | 10 | On |
| right_attack | player_right_idle_1.png player_right_attack_1.png player_right_attack_2.png | 7 | Off |
| right_fireball | player_right_idle_1.png player_right_fireball_1.png player_right_fireball_2.png | vii | Off |
| right_idle | player_right_idle_1.png player_right_idle_2.png | i | On |
| right_walk | player_right_idle_1.png player_right_walk_1.png player_right_idle_1.png player_right_walk_2.png | ten | On |
| up_attack | player_up_idle_1.png player_up_attack_1.png player_up_attack_2.png | 7 | Off |
| up_fireball | player_up_idle_1.png player_up_fireball_1.png player_up_fireball_2.png | seven | Off |
| up_idle | player_up_idle_1.png player_up_idle_2.png | ane | On |
| up_walk | player_up_idle_1.png player_up_walk_1.png player_up_idle_1.png player_up_walk_2.png | 10 | On |
In the Inspector, you can prepare the Animation property to the animation you want to preview. When you've finished creating the animations, gear up it to down_idle. It will be the default animation when the game starts.
Playing animations with script
Open the Player script. To choose which blitheness to play, we volition write a new role named animates_player(). We volition call this part at the end of _physics_process(), after the role player's movement has been calculated.
Let'due south first by writing a simplified version of the animates_player() function to become familiar with how 2d sprite animation works.
Copy the following code into the script:
func animates_player(direction: Vector2): if direction != Vector2.Null: # Play walk animation $Sprite.play("down_walk") else: # Play idle animation $Sprite.play("down_idle") The function animate_player() takes a Vector2 argument that represents the direction of the role player motion.
The starting time line checks if the direction is different from zero (Vector2.ZERO is a abiding equivalent to Vector2(0,0)). If true, the player is moving and the play() method of the Sprite node is called to play the down_walk blitheness. If false, information technology ways that the actor is still, and then the down_idle animation is performed. The $ operator, as we saw in Godot Tutorial – Part 3: First project, is used to go the reference to a child node.
Alert! Fifty-fifty if the node is still called Sprite, I remind y'all that now information technology'south of AnimatedSprite blazon. Practice not confuse the proper name of the node with its type! play() is an AnimatedSprite method that is not bachelor in Sprite-blazon nodes.
At present, at the bottom of the _physics_process() part, add together this line to phone call animates_player():
# Animate player based on management animates_player(direction) If you try to run the game, you will encounter that when the actor is still, the idle blitheness is performed, while when it is moving, the walk animation is shown as expected.
Choosing the correct animation
Obviously, we don't want to show the player always facing down, but we want to choose which animation to play based on the management in which the actor is facing.
To do this, we first demand to declare a new variable at the get-go of the script:
var last_direction = Vector2(0, one) In this variable nosotros volition store the last direction in which the histrion moved before stopping. We gear up the initial value to Vector2 (0,ane) to indicate the histrion downwardly. This variable will help usa decide which idle animation to evidence.
Now, we have to write the lawmaking that chooses whether to apply the down, up, left or right animations, based on the direction vector. Since we will utilise this code on more than than one occasion, we volition write it in a new function, called get_animation_direction():
func get_animation_direction(direction: Vector2): var norm_direction = direction.normalized() if norm_direction.y >= 0.707: return "downwards" elif norm_direction.y <= -0.707: return "upwards" elif norm_direction.x <= -0.707: return "left" elif norm_direction.x >= 0.707: return "right" return "down" How does this lawmaking piece of work? First, it normalizes the management vector to brand sure it has length 1 (it can be less than 1 when using an analog stick). If we draw this normalized vector on a Cartesian aeroplane, it will always be on a point of the unit of measurement circle (i.e. a circumvolve with radius 1):
Let's divide the plan into 4 quadrants every bit in the following figure:
Each expanse contains a quarter of the unit circle. Each of these arcs corresponds to one of the 4 possible directions of the animations.
How practice nosotros decide in which of these arcs is our vector? I won't bore y'all with calculations, merely it can exist shown that all the points of the lower arc take the y coordinate greater than the foursquare root of two over 2, or nigh 0.707, while those of the upper arc all have a value of y less than -0.707. Same affair for left and correct, but in that case using the x coordinate.
Thus, the function only checks the values of the ten and y coordinates of the vector to determine in which of these arcs it'south located. Based on that, information technology returns the animation string prefix.
The return argument is used to stop the execution of the function call and render the result value of the office. You can get out from a function at any signal. If you don't employ the render keyword, the default return value is null.
Now, we can edit animates_player() to cull the right animation direction:
func animates_player(management: Vector2): if direction != Vector2.Cipher: # update last_direction last_direction = management # Choose walk animation based on motility direction var animation = get_animation_direction(last_direction) + "_walk" # Play the walk blitheness $Sprite.play(blitheness) else: # Choose idle animation based on last movement management and play it var blitheness = get_animation_direction(last_direction) + "_idle" $Sprite.play(blitheness) As you can meet, when the player is moving, we save in last_direction the current value of direction, and so that information technology can be used later to choose the correct idle animation.
We utilize get_animation_direction() to get the direction prefix, to which we suspend, with the + operator, the cord indicating which animation we desire (_walk or _idle). Then, equally before, we employ the play() method to play the animation.
If you try the game now, you lot will encounter that the player turns in the direction in which he walks. When the role player stops, it remains oriented in the last direction of motion.
Walking speed
If you are using a joypad with analogue sticks, you will accept noticed that when the player moves slowly, the walk animation is however performed at the speed of ten FPS nosotros initially set. This is visually unpleasant, because the speed of the animation is too high compared to the actual movement of the player on the map. Nosotros must therefore adjust the animation FPS based on histrion speed.
Doing information technology is quite simple, just add this new line to animates_player() before playing the walk animation:
$Sprite.frames.set_animation_speed(animation, 2 + 8 * direction.length()) This line accesses the SpriteFrame resource of the Sprite node and uses the set_animation_speed() method to set the FPS of the blitheness indicated by the first argument. The 2nd argument is the number of FPS, which we summate with a formula that returns a value from ii to x, depending on the length of the direction vector (which can range from 0 to 1).
Analog stick bounce problem
When using an analog stick, information technology tin happen that when the player walk in one direction and suddenly release the stick, he end up facing the opposite management. This tin happen or not depending on the controller and the fashion the player handle the stick.
This is due to the fact that, whenever you release the stick, it returns back to its center position. But the spring that causes this movement is so stiff, that the stick actually overshoots the heart, going beyond for a short corporeality of time.
To solve this trouble, nosotros must ensure that the last_direction vector is not updated instantaneously with every change of management, only that the change is gradual to filter out this "noise". To do this, supersede the line that updates last_direction with this:
# gradually update last_direction to counteract the bounce of the analog stick last_direction = 0.5 * last_direction + 0.v * direction Attack and fireball animations
The player, in addition to moving around the map, can attack enemies with his sword or casting fireballs. Since we have already created the animations for these deportment, we want to play them when the actor presses the attack keys.
First of all, we need to create input actions in the Input Map panel, which y'all tin access by clicking on Project → Project Settings → Input Map. We will create two actions:
- attack: to set on with the sword; nosotros will assign to this action the Infinite cardinal and the Button 2 of the joypad (which corresponds to the Ten button of the XBox controller and to the Foursquare button of the PlayStation controller)
- fireball: to cast a fireball; we will assign to this action the Control push and the Push 3 of the joypad (which corresponds to the Y button of the XBox controller and to the Triangle button of the PlayStation controller).
To add a new action, enter the name in the Action text field at the top of the panel, and press Add. We take already seen the procedure for mapping an input to an action in the Godot Tutorial – Office 5: Histrion motion, so refer to that if you don't remember how to do it. The result will be the following:
Close the Project Settings window, go back to the script and add together a new variable that we volition use to find out if there is an attack blitheness in progress:
var attack_playing = false We need this variable because animates_player() is called continuously by _physics_process(), so the set on animation would not have the time to exist executed because it would be immediately replaced by a walk or idle animation. Because of this, we need to edit the _physics_process() lawmaking to telephone call animates_player() only if attack_playing is false:
# Breathing player based on direction if non attack_playing: animates_player(direction) To handle attack input, we'll use the _input method inherited from Node. This function is called whenever any input event occurs.
Add this code to the script:
func _input(upshot): if event.is_action_pressed("attack"): attack_playing = true var animation = get_animation_direction(last_direction) + "_attack" $Sprite.play(animation) elif consequence.is_action_pressed("fireball"): attack_playing = true var animation = get_animation_direction(last_direction) + "_fireball" $Sprite.play(animation) If y'all followed Godot Tutorial – Part v.ane: Dragging the histrion with the mouse, then you lot already have this function in the script. Y'all can add this code next to the existing one without whatever problems.
The role works like this: if one of the cardinal/push assigned to the attack action is pressed, attack_playing is set to truthful, in order to bypass the animates_player() function. The correct animation is then chosen based on the final direction of the histrion and performed with the play() method. The same goes for the fireball activity.
If you run the game now, you volition come across that the attack animations are performed correctly, but then the sprite remains on the concluding frame of the animation and the walk and idle animations are no longer played. This happens because attack_playing is non reset to false anywhere. Nosotros must then add together some lawmaking that resets the variable when the animation ends.
Fortunately, AnimatedSprite provide the animation_finished() point, which is sent each time the last frame of an animation is played. We will link this signal to a part in our script that resets attack_playing.
Open the Node panel and, if it is non already selected, click on Signals to come across the list of signals.
Select animation_finished() and printing Connect. A window volition open to select the node to connect with the point. Select Player and printing Connect. The script volition open with the cursor positioned on the part that was just created. Edit it similar this:
func _on_Sprite_animation_finished(): attack_playing = simulated As a last thing, we desire the role player speed to decrease when it's simultaneously moving and attacking. To practise this, simply add these lines to _physics_process(), only before calling move_and_collide():
if attack_playing: movement = 0.3 * movement Conclusions
In this tutorial we learned how to utilise AnimatedSprite and SpriteFrames to breathing sprites and how to utilize scripts to run animations. Furthermore, nosotros have deepened our knowledge of the Godot input arrangement.
You lot can try what we've done so far by clicking hither:
In the next tutorial we will kickoff developing the game GUI.
Did yous enjoy this article? Then consider ownership me a coffee! Your support will help me comprehend site expenses and pay writers to create new blog content.
Source: https://www.davidepesce.com/2019/10/23/godot-tutorial-8-2d-sprite-animation/
Posted by: collinscapon1936.blogspot.com

0 Response to "How To Reverse An Animation In Godot"
Post a Comment