I have a function called animate_sprite. As the name suggests, it's used to animate the sprite.

The problem is that when a jump is interrupted by releasing the jump key, it will play idle animation for a moment. It's quite... jarring.

It happens because when the jump key is released, the velocity.y becomes 0. In animate_sprite, when velocity.y != 0, it will play jump animation. Because velocity.y = 0 for a moment, it plays idle animation.

I need a way to show jump animation smoothly without being interrupted by idle animation. Any idea how?

func _physics_process(_delta) -> void:
	var is_jump_interrupted = Input.is_action_just_released("ui_up") and _velocity.y < 0.0
	var direction = get_direction()
	_velocity = calculate_move_velocity(_velocity, direction, _speed, is_jump_interrupted)
	_velocity = move_and_slide(_velocity, floor_normal)
	animate_sprite(_velocity)
	return

func get_direction() -> Vector2:
	return Vector2(
		Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left"),
		-Input.get_action_strength("ui_up") if is_on_floor() and Input.is_action_just_pressed("ui_up") else 0.0
	)

func calculate_move_velocity(
		linear_velocity: Vector2,
		direction: Vector2,
		speed: Vector2,
		is_jump_interrupted: bool
	) -> Vector2:
	var new_velocity = linear_velocity
	new_velocity.x = direction.x * speed.x
	if direction.y != 0.0:
		new_velocity.y = direction.y * speed.y
	if is_jump_interrupted:
		new_velocity.y = 0.0
	return new_velocity

func animate_sprite(velocity: Vector2) -> void:
	if velocity.x == 0.0:
		$AnimatedSprite.play("stand")
	elif velocity.x > 0:
		$AnimatedSprite.play("walk")
		$AnimatedSprite.flip_h = false
	elif velocity.x < 0:
		$AnimatedSprite.play("walk")
		$AnimatedSprite.flip_h = true
	if velocity.y != 0:
		$AnimatedSprite.play("jump")
	return

hi, im new in Godot, but i will try to help.

maybe you should make a RayCast2D or and Area2D under your player and emit a signal everytime the ground collisionshape hit the raycast or area. and play the stand animation

if you choose RayCast as your card if $RayCast2D.is_colliding(): $AnimatedSprite.play("stand")

if you choose Area2D as your card func _on_body_area_entered(): $AnimatedSprite.play("stand")

sorry for my bad English, not a native speaker

Hi, not sure how your 'idle' is called, but it might be something as simple as

if velocity.y == 0 AND is_on_floor = true do the idle bit.

That way, if your jumping and you do get to the y = 0, its is_on_floor should be false, so in theory it shouldnt snap in an idle animation while your jumping. Still getting my head round coding, so just a thought how I would approach it!

That's it. Thanks, BingBong.

I should have added is_on_floor. Basically...

func animate_sprite(velocity: Vector2) -> void:
	if velocity.x == 0.0 and is_on_floor():
		$AnimatedSprite.play("stand")
	elif velocity.x > 0 and is_on_floor():
		$AnimatedSprite.play("walk")
		$AnimatedSprite.flip_h = false
	elif velocity.x < 0 and is_on_floor():
		$AnimatedSprite.play("walk")
		$AnimatedSprite.flip_h = true

	if velocity.y != 0 or !is_on_floor():
		$AnimatedSprite.play("jump")
	return
2 years later