*You can find the links to the previous parts at the bottom of this tutorial.
Now that we have our level progression set up, we’re going to create our game over screen that will be made visible when our players’ lives fall below 1 (zero or less). This part will be a repetition of things that you’ve done before, which means that this section will be quick to do and easy to understand!
STEP 1: GAME OVER UI
In your Player scene, underneath your UI node, add a new CanvasLayer node called “GameOver”.
Then, go back to your LevelDoor scene and copy the entire Menu node with all of its children.
Paste this copied branch underneath your GameOver node in your Player scene.
In your Player’s AnimationPlayer node, add a new animation called “ui_visibility”.
Add a property track and assign it to your Menu node underneath your GameOver layer. We’re doing the same as we did in our LevelDoor scene, where we make our Menu node go from invisible to visible.
Assign this track to the modular value.
Then, change your track length to 0.5 and add two keyframes.
Change the keyframe at point 0’s Color value to “ffffff00”. This will make it transparent. Change the keyframe at point 0.5’s Color value to “ffffff”. This will make it visible.
Now if you play your animation, your Menu should be made visible.
Change your Label node (which says, “Level Complete!”) to say, “Game Over!”. Also, change its horizontal and vertical alignment to be centered.
Delete your ContinueButton node.
Then, also detach your RestartButton node’s pressed() signal from all its connections. We need to do this because it’s still connected to our LevelDoor script. We will need to re-attach this signal to our Player script since we want to restart the game if this button is pressed.
Now, change your RestartButton node’s position to (x: 404, y: 390).
Hide your Menu node by changing its visibility to hidden. You can do this in the Inspector panel underneath Visibility, or you can just click on the eye icon next to the node itself.
Let’s change our AnimatedPig node to show a different animation in our Player’s GameOver screen. This isn’t necessary, but it does provide our screen with some variety! Delete all the existing frames in its animation panel, and swap them out with the frames inside the “res://Assets/Kings and Pigs/Sprites/02-King Pig/Idle (38x28).png” spritesheet. Change the FPS to 12, and leave the looping on.
Do the same for the AnimatedKing node. Delete all the existing frames in its animation panel, and swap them out with the frames inside the “res://Assets/Kings and Pigs/Sprites/01-King Human/Dead (78x58).png” spritesheet. Change the FPS to 5, and turn the looping off.
Finally, we also need to change the Processing Mode of our GameOver node since we want our player to press the restart button when the game is paused. Change its processing mode from “Inherit” to “Always”, which will allow our screen to show when the game is unpaused, and allow input when the game is paused.
We also need to change our AnimationPlayer’s Processing Mode to be “Always”, since the ui_visibility animation should play when the game is paused.
It should now look similar to this:
STEP 2: GAME OVER FUNCTIONALITY
In our Player script, let’s restart the game if our RestartButton is being pressed. We’ve done the same in our LevelDoor script.
### Player.gd
#older code
#restarts game
func _on_restart_button_pressed():
#unpause scene
get_tree().paused = false
#hide menu
$GameOver/Menu.visible = false
# Restart current scene
get_tree().reload_current_scene()
Then, in our take_damage() function, we want our player’s death animation to play when our lives fall below 1. This will trigger our _on_animated_sprite_2d_animation_finished() function, which will then show our GameOver screen after our death animation has played.
### Player.gd
#older code
# takes damage & death
func take_damage():
#deduct and update lives
if lives > 0 and Global.can_hurt == true:
lives = lives - 1
update_lives.emit(lives, max_lives)
#play damage animation
$AnimatedSprite2D.play("damage")
#allows animation to play
set_physics_process(false)
is_hurt = true
#decrease score
decrease_score(10)
if lives <= 0:
$AnimatedSprite2D.play("death")
In our _on_animated_sprite_2d_animation_finished() function, we will check if our death animation has played, and if true, we will show our UI values and make our Game Over screen visible.
### Player.gd
#older code
#reset our animation variables
func _on_animated_sprite_2d_animation_finished():
if attack_time_left <= 0:
Global.is_attacking = false
set_physics_process(true)
is_hurt = false
if $AnimatedSprite2D.animation == "death":
# pause game
get_tree().paused = true
# show menu
$GameOver/Menu.visible = true
# make modular value visible
$AnimationPlayer.play("ui_visibility")
#hide the player's UI
$UI.visible = false
#get final values
final_score_time_and_rating()
# show player values
$GameOver/Menu/Container/TimeCompleted/Value.text = str(Global.final_time)
$GameOver/Menu/Container/Score/Value.text = str(Global.final_score)
$GameOver/Menu/Container/Ranking/Value.text = str(Global.final_rating)
Your code should look like this.
Now if you run your scene, and your player’s lives deplete down to 0, your death animation should play and your game over screen should show. You should be able to restart the level by pressing the restart button.
Congratulations on stopping your player from having an infinite lifespan! We are so close to the end now, and in the next part, we will create a pause and main menu that will allow our player to quit the game, as well as save and load their game — which will load them into their last saved level.
Now would be a good time to save your project and make a backup of your project so that you can revert to this part if any game-breaking errors occur. Go back and revise what you’ve learned before you continue with the series, and once you’re ready, I’ll see you in the next part!
Next Part to the Tutorial Series
The tutorial series has 24 chapters. I’ll be posting all of the chapters in sectional daily parts over the next couple of weeks. You can find the updated list of the tutorial links for all 24 parts of this series on my GitBook. If you don’t see a link added to a part yet, then that means that it hasn’t been posted yet. Also, if there are any future updates to the series, my GitBook would be the place where you can keep up-to-date with everything!
Support the Series & Gain Early Access!
If you like this series and would like to support me, you could donate any amount to my KoFi shop or you could purchase the offline PDF that has the entire series in one on-the-go booklet!
The booklet gives you lifelong access to the full, offline version of the “Learn Godot 4 by Making a 2D Platformer” PDF booklet. This is a 451-page document that contains all the tutorials of this series in a sequenced format, plus you get dedicated help from me if you ever get stuck or need advice. This means you don’t have to wait for me to release the next part of the tutorial series on Dev.to or Medium. You can just move on and continue the tutorial at your own pace — anytime and anywhere!
This book will be updated continuously to fix newly discovered bugs, or to fix compatibility issues with newer versions of Godot 4.
Top comments (1)
Thanks!