DEV Community

Cover image for Learn Godot 4 by Making a 2D Platformer — Part 17: Level Progression #2
christine
christine

Posted on

Learn Godot 4 by Making a 2D Platformer — Part 17: Level Progression #2

*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).

Godot 2D Platformer

Godot 2D Platformer

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).

Godot 2D Platformer

*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).

Godot 2D Platformer

2. Level

Copy and paste your Time node and rename it to “Level”. Change its position to (x:930, y: 20).

Godot 2D Platformer

Godot 2D Platformer

Delete the Sprite2D node and replace it with a Label node. Rename your second Label node to “Value”.

Godot 2D Platformer

The Label node should have the text “LVL:”. Change its position to (x: 10, y: 9).

Godot 2D Platformer

The Value node should have the text “0”. Change its position to (x: 50, y: 9).

Godot 2D Platformer

Your final UI should look like this:

Godot 2D Platformer

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"
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

Now if you run your scene, your time label should update with the seconds that passed!

Godot 2D Platformer

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode

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!

Godot 2D Platformer

Godot 2D Platformer

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!

Godot 2D Platformer


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!

Godot 2D Platformer

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)

Collapse
 
jameshubert_com profile image
James Hubert

Really quality blog posts Christine! Keep it up 🔥🚀

Collapse
 
christinec_dev profile image
christine

Thank you! 😊

Collapse
 
leor_bester_a6a49c406f467 profile image
Leor Bester

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.