*You can find the links to the previous parts at the bottom of this tutorial.
With our level completion menu set up, we also need to add those final tweaks to our Player’s UI to notify our player of the current level that they’re in, and the time that has passed since they started the level. This allows them to better keep track of the time so that they can estimate which ranking they will get.
WHAT YOU WILL LEARN IN THIS PART:
- UI creation.
- Further practice with the String object.
STEP 1: LEVEL & TIME UI
1. Time
In your Player scene, copy and paste your Score node and rename it to “Time.” Change its anchor-preset to “top-right”, and then only its position to be (x: 930, y: 70).
Change out the Sprite2D node’s icon to “res://Assets/clock.png”. We also need to scale it down to a smaller value such as “0.057”. Change its position to (x: 22, y: 20).
*Please download the clock.png here as I forgot to add it to the original assets folder.
Change the Label node’s position to (x: 50, y: 9).
2. Level
Copy and paste your Time node and rename it to “Level”. Change its position to (x:930, y: 20).
Delete the Sprite2D node and replace it with a Label node. Rename your second Label node to “Value”.
The Label node should have the text “LVL:”. Change its position to (x: 10, y: 9).
The Value node should have the text “0”. Change its position to (x: 50, y: 9).
Your final UI should look like this:
STEP 2: TIME DISPLAY
To actually show the time that has passed since the level started, we need to create a new function in our Player script that will calculate this time based on our level_start_time. We’ve done this before in our final_score_time_and_rating() function, but now we’ll just create a new function that we will call in our process() function to update our label at every second.
### Player.gd
#older code
# Update the time display label every second since the game started
func update_time_label():
var time_passed = (Time.get_ticks_msec() - level_start_time) / 1000.0 # in seconds
$UI/Time/Label.text = str(round(time_passed)) + "s"
Then, at the end of our process() function, let’s call our newly created function.
### Player.gd
#older code
func _process(delta):
#older code
# Update the time label
update_time_label()
Now if you run your scene, your time label should update with the seconds that passed!
STEP 3: LEVEL DISPLAY
Our Main and Main_2 scenes do not currently have a level value assigned to them. Luckily for us, we don’t have to assign them with a level, since we can use our Global function to assign them with a level value (1, 2, 3, … n) based on their current_scene_name!
Since our scenes are named Main, Main_2, etc., we can extract the number from the scene name — and thus give the level that number derived from the scene name. In other words, our “Main” scene will have “1”, and our Main_2 will derive the “_2” from it, hence giving it the level “2”.
In your Global script, we will create a new function that will hold a conditional statement that will assign our “Main” scene with the value of 1. Any scene thereafter that starts with “Main_”, will be split apart using the get_slice() method to derive the number value assigned to it (_2 = 2, _3 = 3, _n = n).
### Global.gd
#older code
# Current level based on scene name
func get_current_level_number():
if current_scene_name == "Main":
return 1
elif current_scene_name.begins_with("Main_"):
# Extract the number after "Main_"
var level_number = current_scene_name.get_slice("_", 1).to_int()
return level_number
else:
return -1 # Indicate an unknown scene
Then, in your Player.gd script, we can use this number returned from our function to update our Value node to show the current level. At the top of our Player script, let’s define a new variable that will hold the reference to our Value node inside of our Time ColorRect.
### Player.gd
#older code
#level value
@onready var level = $UI/Level/Value
Then, at the end of our script, let’s create a new function that will assign the value of our Global get_current_level_number() function to our Value node (only if it is valid).
### Player.gd
#older code
# Update the level label to display the current level
func update_level_label():
var current_level = Global.get_current_level_number()
if current_level != -1:
level.text = " " + str(current_level)
else:
level.text = "err!"
Your code should look like this.
Now if you run your scene, your level should show, and if you progress to your second level, the level value should increment to 2!
Congratulations on creating your level progression system! It’s easy to progress to the next level and get x amount of score points if your player never dies. Currently, our player’s lives can be depleted and we can still go ahead and gain score points. We need to stop this tomfoolery by giving our players a Death/Game Over screen! In the next part, we’ll implement this feature to stop our game if our player’s health runs out, which will force our player to replay the current 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 (3)
Really quality blog posts Christine! Keep it up 🔥🚀
Thank you! 😊
Greetings to you nerdy folk.
I need some help please.
I followed all of the instructions up to this point and no problems.
But on this step, I am running into two issues.
First, the transition from Main to Main_2 keeps giving me the error "Attempt to call function 'play' in base 'null instance' on a null instance." and then refers me to the line of code "bomb_animation.play("bomb_movement")"
It is currently under the func_ ready(), should it be somewhere else? Is this something to do with a version change in Godot?
Second, the UI level label does not update according to my level scene. I don't know if this has to do with my first problem stated above, but it just shows 0 instead of 1 or 2.
Thank you for any help on this subject.