Squash and stretch the player between an idle and a walk. The animations live in the scene, not the code.
Loading the game engine. This takes a moment the first time.
The animations are NOT in the code. They are saved in the scene file. Open simple_animation.tscn in Godot and click the AnimationPlayer node to see the two of them: "idle" and "walk". Each one squashes and stretches the player's size over time.
■ UI node · ■ 2D node · % unique name · .tscn instanced scene
extends Node2Dextends CharacterBody2D
## How fast the player moves. "@export" puts "speed" at the top of the
## Inspector panel, so you can change it there instead of in this file.
@export var speed: float = 200.0
# "%AnimationPlayer" means "the node named AnimationPlayer in this scene."
@onready var anim: AnimationPlayer = %AnimationPlayer
@onready var sprite: Sprite2D = %Sprite
# "_physics_process()" runs about 60 times a second. Godot calls it for you.
func _physics_process(_delta: float) -> void:
# "Input.get_vector(...)" checks all four keys at once and hands back
# an arrow pointing where to go.
var direction: Vector2 = Input.get_vector(
"move_left", "move_right", "move_up", "move_down"
)
velocity = direction * speed
move_and_slide()
# The warrior picture only faces right. Walking left mirrors it.
if direction.x != 0.0:
sprite.flip_h = direction.x < 0.0
# "direction.length()" is how long the arrow is. When no key is held
# down the length is 0, which means the player is standing still.
if direction.length() > 0.0:
# Only call "anim.play("walk")" if "walk" is not already going.
# Without this check we would restart the animation 60 times a
# second, and it would look frozen on its first frame.
if not anim.is_playing() or anim.current_animation != "walk":
anim.play("walk")
else:
if not anim.is_playing() or anim.current_animation != "idle":
anim.play("idle")