Making a Sprite Explode in Godot: A Godot 4 Tutorial

 Do you want to explode a game sprite? I know I do. So lets start setting this scene up.

Create a new project. In the scene tree add a Node2D and name it Main.



Attach a script. We will need it. Then save the scene, and try to play the scene. This will give you the option to select this scene as the "Main Scene" or entry point of the game.

Next we need to make a sprite we can blow up. Click "Scene" -> "New Scene".



We are going to create an Area2D and add two children nodes. A Sprite2D and a CollisionShape2D.



Select the Sprite2D and look in the Inspector dock. Look where it says "Texture <empty>". Click on the little arrow and select "Load..."



For this tutorial I chose to load "icon.svg"


Next, select the CollisionShape2D. In the Inspector dock, set the Shape to RectangleShape2D.



You will notice a group of red dots in the 2D window. Click on these to expand your shape over the sprite.



Save the scene and name it something like "victim". In the scene tree pick the Area2D node and attach a script.



In the Inspector dock you will see a tab called "Node".



Double click on the input_event signal. Click "Connect". You should now see in the script a new function called _on_input_event. We will modify the script to this...


extends Area2D

signal die
var dying := false

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass


func _on_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton and event.button_index == 1:
		emit_signal("die")


What we did was make it to where, when we click on the sprite, a "die" signal is emitted. We will later use this signal to explode the game sprite.

But first we need to create our explosion animation.
I have an explosion sprite sheet I made in Gimp.





You can use my sprite sheet if you want. But drag your sprite into the FileSystem dock and drop it in.
Then right click in the FileSystem choose Create New and then Resource...


In the search bar type "spriteframes". Then select SpriteFrames and click Create.


Name it something like "explosion.tres" and click save.

Now we need to set up this SpriteFrames resource. Select "explosion.tres" in the FileSystem dock and you will see an animation dock.


Click the Add frames from sprite sheet button.


The select your explosion sprite sheet.
For my sprite sheet I have 8 frames, 4 frames on top and 4 on bottom. So I need to adjust the Horizontal and Verticle count to match my sprite sheet.


Now my sprite sheet is divided properly.


Next, click on each frame.


Then click the add frames button at the bottom.

Since I have 8 frames to my sprite sheet, I will change the speed to 8.0 FPS.

I also uncheck the Animation Looping button.


Our animation resource is ready and we can now create a new scene. Create a Node2D. Lets call it explode. Add an AnimatedSprite2D as a child.


Save the scene as "explode.tscn"

Next we select the AnimatedSprite2D and look at the Inspector dock. Under Animation it has Sprite Frames <empty>. Click on the little check mark.



Click Load...

Then select our animation resource called explosion.tres and click Open.


Select the explode Node2D and attach a script.


We will modify the script like so...

extends Node2D


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	$AnimatedSprite2D.play("default")
	$AnimatedSprite2D.animation_finished.connect(queue_free)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta: float) -> void:
	pass

Now our explode animation is ready to be called upon. Lets go back to our main.tscn scene.
You will notice that Main does not have any children nodes. That is perfect because we will dynamically call upon the other scenes we have created.

Lets start by adding these lines to Main scene's script.


extends Node2D

@export var victim_scene: PackedScene
@export var explosion_scene: PackedScene
var victim : Node2D


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass

Now look in the Inspector doc. You will see Victim Scene <empty> and Explosion Scene <empty>.



Click the small check box to load your scenes. Set Victim Scene to victim.tscn and Explosion Scene to explode.tscn respectively.

Lets modify Main's script again.


extends Node2D

@export var victim_scene: PackedScene
@export var explosion_scene: PackedScene
var victim : Node2D


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	victim = victim_scene.instantiate()
	victim.position = Vector2(200.0, 200.0)
	add_child(victim)
	
	#connect to victim's "die" signal
	if victim.has_signal("die"):
		victim.die.connect(_on_die)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass
	
func _on_die() -> void:
	pass


You notice I added a new function called _on_die()

Lets change it to do more than pass.


extends Node2D

@export var victim_scene: PackedScene
@export var explosion_scene: PackedScene
var victim : Node2D


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	randomize()
	victim = victim_scene.instantiate()
	victim.position = Vector2(200.0, 200.0)
	add_child(victim)
	
	#connect to victim's "die" signal
	if victim.has_signal("die"):
		victim.die.connect(_on_die)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass
	
func _on_die() -> void:
	if victim.dying:
		return
		
	victim.dying = true
	victim.get_node("Sprite2D").visible = false
	
	for i in range(6):
		var explosion = explosion_scene.instantiate()
		explosion.scale *= randf_range(.25, 1.25)
		var offset = Vector2(randf_range(-30.0, 30.0), randf_range(-30.0, 30.0))
		explosion.global_position = victim.global_position + offset
		add_child(explosion)
		await get_tree().create_timer(0.05).timeout
	
	await get_tree().create_timer(2.0).timeout
	if victim:
		victim.queue_free()

If you followed all these steps carefully then you should get a satisfying explosion animation when you click on the victim sprite.

I hope you have enjoyed this tutorial even though I threw a lot of new concepts at you that I have not yet previously covered, like emitting custom signals and instantiating scenes dynamically.

It is important to remember that Godot is not just a game engine. It is a community. We all learn from each other. So if you have written an article of your own, please leave a link to it in the comments. I would love to read it. Thank you.

Comments

Popular Posts