Hello everyone,

I am new to Godot and I am reading tutorials and watching youtube videos. I'm currently learning the basics on a small platformer project. Now I have the movement with friction etc. and an enemy who can be stomped on. After that I wanted a vanish animation. But there is the first problem because queue_free () is executed immediately and the animation cannot be seen. However I thought it would be cooler anyway if the opponent falls apart. But now I have absolutely no idea how to code something like this and can't find anything on the Internet.

Here's an example:

Enemy script: extends KinematicBody2D


export var velocity = Vector2(-100, 0)
var gravity = 1500


func _on_StompDetector_body_entered(body):
	if body.global_position.y > $StompDetector.global_position.y:
		return
		
	$AnimatedSprite.play("dissapear")
	queue_free()


func _physics_process(delta):
	velocity.y += gravity * delta
	
	if is_on_wall():
		velocity.x *= -1
		$AnimatedSprite.flip_h = not $AnimatedSprite.flip_h
		
	velocity.y = move_and_slide(velocity, Vector2.UP).y

So by calling queue_free, the object is essentially deleted, so you won't see the animation. What you could do is call queue_free at the end of the animation (you can make function calls as keyframes in an animation). This would be an easy and flexible way to do it. Or you can create a Timer, and on the timeout event you can call queue_free.

Or connect the "animation_finished" signal to a signal handler method and put the queue_free() call there.

@DaveTheCoder said: Or connect the "animation_finished" signal to a signal handler method and put the queue_free() call there.

This makes the enemy deleted immediately after the first walk animation. I think you have to pass the argument to the function after which animation it is executed but then I get an error:

    func _on_AnimatedSprite_animation_finished("dissapear"):
    	queue_free()

Error: Expacted an identifier for an argument

@cybereality said: What you could do is call queue_free at the end of the animation (you can make function calls as keyframes in an animation). This would be an easy and flexible way to do it.

I don't know how to do this :anguished:

Having it disappear is all right because you would probably want to replace it with 4 separate objects that are rigidbody2d. Give them an upward and outward force and let gravity pull them back down. They would be together and more or less in the shape of the object they replaced at the start. Also, in most cases a fade out looks better than an immediate destruction, so you would want an animation there. In this case you wouldn't want to fade it out though because it's being replaced. You would probably want to parent the 4 objects to a node or something for placement. I guess you would have to experiment with that.

Here is how to create a timer with code.

func _ready():
	var timer = Timer.new()
	timer.wait_time = 2.0
	timer.connect("timeout", self, "timer_done")
	add_child(timer)
	timer.start()

func timer_done():
	print("timer done")

However, in a real game it would be easier to just add a Timer node to your object (that way you don't have to be creating and deleting timers all the time). So you can add a Timer node as a child to the object, then set One Shot to on (so it doesn't loop) and set the Wait Time to the seconds you wish to wait.

onready var timer = get_node("Timer")

func _ready():
	timer.connect("timeout", self, "timer_finished")
	
func start_timer():
	timer.start()

func timer_finished():
	print("timer finished")

@DaveTheCoder said: Or connect the "animation_finished" signal to a signal handler method and put the queue_free() call there.

I was thinking that you were using AnimationPlayer. With AnimatedSprite, my suggestion might not work. It looks like AnimatedSprite's "animation_finished" signal doesn't provide the animation name.

Thanks for the help @cybereality. I succeeded with a timer. Nevertheless, I think the method with the function call after the animation is better. However, this only works with the AnimationPlayer and not with AnimatedSprite (if I understood that correctly). But then you could also use @DaveTheCoder's suggestion with an animation_finished signal because that way you would have a better overview of what happened in the script.

@fire7side said: Having it disappear is all right because you would probably want to replace it with 4 separate objects that are rigidbody2d. Give them an upward and outward force and let gravity pull them back down. They would be together and more or less in the shape of the object they replaced at the start.

That's exactly what I want to do. How do I make the objects appear after the enemy has disappeared? Or is it better to leave the objects in the enemy node and then fade in the objects and fade out the enemy sprite?

@shIxx said:

That's exactly what I want to do. How do I make the objects appear after the enemy has disappeared? Or is it better to leave the objects in the enemy node and then fade in the objects and fade out the enemy sprite?

No, you don't want to fade in or out because it has to look like the same object so you just have it wink out and then you create an instance of the other objects and give them a force upwards and outwards. Probably you would make a scene of the 4 objects with a node for placement and get the position of the deleted object and give it to the instance. They would be set up so they looked like the other object. You probably need to experiment with it in a separate project till you get it worked out. What I would do is just make 4 square sprites at first, or just use the godot head sprite and assemble them in a scene and give them the forces in the ready function. Then instance it from a main scene with a ground. Make sure you position the 4 objects at the 0,0 of the scene so it works out when you instance it.

a year later