Make a public leaderboard in Godot 4 with Quiver Leaderboards
The focus of this post will be a demo/tutorial for implementing a simple leaderboard in your Godot 4 project. If that’s what you’re looking for, read on!
We recently participated in Kenney Jam 2024. Our entry was Circuit Snap, a slot car racer with a puzzle twist. It’s a fun little Jam game that we’re proud of, check it out!
While the jam isn’t the focus of this post, I bring it up because it introduced an opportunity to use a tool that we have been experimenting with for quickly building public leaderboards for our smaller games. For example, we also included a public leaderboard in our card game, “Take it, or Leave It!” (TIOLI).
Enter Quiver
Quiver is a growing company building resources and tools for Godot developers. Their two main tools at present are Analytics and Leaderboards.
When we started building TIOLI, we were looking for a quick and easy to implement leaderboard system without having to manage our own servers. As the lead developer for that game, I decided to try out Quiver Leaderboards and I was very happy with how quick and easy it was to use the Leaderboards API to implement my own custom leaderboard.
We tried it again with Circuit Snap, so I decided the time was right to demo our implementation to help new Godot developers implement simple leaderboards with custom interfaces even more quickly.
Let’s dive in!
The Demo Project
You can find a Github repository for this project here. In this demo/tutorial, I’ll point you to some resources for setting up Quiver Leaderboards in your project and then walk through how I constructed the leaderboard scene in this project using the Quiver Leaderboards API.
Note that as of writing, Quiver Leaderboards is still in Beta, and may change. We’ll do our best to keep this project and post up-to-date.
Setting Up Quiver Leaderboards
The first step is to set up your Quiver account, and create a project. Honestly, Quiver does a great job of providing clear instructions for setting up your account and getting the required plugins into your Godot 4 project.
If you prefer text tutorials, check out the leaderboards github page.
If you prefer video tutorials, check out the video on the Quiver website.
Overview of the demo project
Now that you have a Quiver account set up, and have created a project with a leaderboard on the Quiver site, you’re ready to go.
Our demo project already has the required Quiver Player Accounts and Quiver Leaderboard plugins added. As described in the Quiver Leaderboards tutorials, in the Project Settings of this demo (and your project) you’ll need to add your Project Token under Quiver > General > Auth Token.
Additionally, you’ll need to add your Leaderboard ID to the top of the leaderboard.gd
script. More on that below.
Here I’ll give you a quick overview of the structure of the project and then dive into the scene and code for the custom “Top 10” leaderboard that we built for Circuit Snap as an example.
The project contains the main godot project (project.godot
). Opening up that project, you should see four directories in the filesystem.
Here’s a brief description of each of these:
addons
contains the quiver plugins described above.assets
contains fonts and ui elements for styling the scenes.scenes
contains the four scenes used in this small demo project.game.tscn
is a very simple “game” consisting of typing a numerical score and hitting enter.leaderboard.tscn
is the leaderboard scene.menu_button.tscn
is used for the button in the leaderboard scene.leaderboard_row.tscn
is used for controlling each entry in the leaderboard.
scripts
contains GDScript scripts (.gd
) for each of the four scenes above as well asglobals.gd
singleton/autoload which is used for storing submitted scores.
The core game loop is quite simple:
A player score is entered by the player in
game.tscn
.
Hitting Enter/Return after entering that number signals the function
_on_line_edit_text_submitted()
ingame.gd.
In this function:We first check if the entered text is a number (float or int). In the event it is not,
_reset_user_input()
clears the text and sets the placeholder text to inform the user to enter a number.Then we convert the number to a float.
Then we store the score to Globals.score.
Finally, we change scenes to the leaderboard.
func _on_line_edit_text_submitted(new_text: String) -> void:
if new_text.is_valid_float() or new_text.is_valid_int():
var _new_score: float = float(new_text)
Globals.score = _new_score
get_tree().change_scene_to_file("res://scenes/leaderboard.tscn")
else:
_reset_user_input()
The leaderboard is updated and displayed to the player.
The player can go back to the score entry scene with a “Back” button.
Diving into the custom leaderboard
Setting the scene
The Leaderboard scene, leaderboard.tscn
, looks like this:
For the sake of brevity, I won’t thoroughly describe each node here. I encourage you to open up the project, click around, and see for yourself how the scene is constructed and where default settings have been changed.
For example, in the Inspector for a node, you can see at a glance where settings have been changed. In the case of the TopSection
node, which is a NinePatchRect
, you can see that I’ve updated the Patch Margins and the Layout settings.
Coding the leaderboard
Let’s take a look at leaderboard.gd!
First, as mentioned above, you will need to enter the Leaderboard ID for your Quiver project under LEADERBOARD_ID
:
There are a few variables set up in advance to hold player input data as well as data from the Quiver Leaderboards API.
All of the real magic happens in the _ready()
function:
Let’s take this step by step:
1) First, we update the text of the score label node, which shows in the upper right corner of the screen.
2) Next, we run _check_for_previous_player_score().
Note that this makes a call to the Quiver Leaderboards API, so we must await that function, since internally it awaits the API call. This function queries your leaderboard for any prior entries from the current user, limiting the results to the single best score from that user. If there is a prior score, the placeholders for the players initials are filled in with the initials they previously entered.
3) Next, we check if the _player_initials
variable has a length less than 3. Since it is initialized as an empty string, this will be true unless a previous score was found for the user on the leaderboard. If there are not prior scores (_player_initials
has a length < 3), we make the node called UserInput
, which is a LineEdit node, visible, grab focus on it so that the player can type without clicking into the edit box, and then await the valid_initials_entered
signal. That signal is emitted by the UserInput
node, when valid text is entered. Take a look at the _on_user_input_text_submitted()
function to see how that works.
4) Now that we have the player’s initials and their score, we next post the score to the leaderboard using Leaderboards.post_guest_score().
5) Then, we call await _update_current_leaderboard()
to retrieve the top 10 scores currently on the leaderboard. Remember that we have already submitted the current user’s current score, so if they made the top 10, it will be included in the response to this API call.
6) Next, we run _build_ranks_from_leaderboard().
This function grabs each of the top 10 scores and uses the name and score fields to update the data for the corresponding LeaderboardRow
node. These are children of the LeaderboardLabelsLeft
and LeaderboardLabelsRight
nodes in the Leaderboard scene. For each score in the top 10, it also checks “is_current_player”
in the leaderboard scores data. If the score belongs to the current player, that row is highlighted in gold color.
7) Finally, the player can click the “Back” button to return to the score entry scene. In your project, as in Circuit Snap, this might actually redirect back to the Title Screen or another menu.
Conclusions
And that’s it! Quiver Leaderboards makes it extremely easy to get started with public leaderboards for your project.
Just to mention it, you could even more quickly use the pre-built leaderboard_ui.tscn
scene that comes with the Quiver Leaderboards Plugin.
Typically I’m looking for a leaderboard that has similar design to the rest of my game, so I’ve found it useful to use the API to build my own leaderboard scenes.
While I haven’t walked you through every line of code and every scene in this project in detail, my aim is that the well-annotated demo project can help you see an example of implementing a custom leaderboard for your own project and help you on your way to creating your own.
I hope this is helpful to some of you newer Godot devs out there! Feel free to reach out if you have comments or questions on this demo project!
Links Recap
GitHub Repository for the Demo Project.
Quiver Leaderboards homepage.
Circuit Snap on itch.io.
Kenney.nl (Thanks to Kenney for hosting a great jam and for providing the assets for this demo project).