In this last part, we “load” existing scores from an array.
What you’ll see here is the foundation to saving and loading data, which you will learn to do for real later in the course.
We will use the same technique for the branching dialogue system.
Until now, we directly called functions to add scores to the scoreboard.
func _ready() -> void:
add_line("Athos")
add_line("Portos")
add_line("Aramis")
But if you quit the game and come back, the board will be empty every time as your nodes and variables only exist in the computer’s temporary memory.
To save scores, you need to write them to a file on the computer’s hard drive.
How do you do that? You store the scores in a variable as data.
Godot, like most languages, has built-in tools to write and load dictionaries, arrays, text, and more from a file.
In this case, we need to map players’ names to their scores, so we will use a dictionary.
Open the Scoreboard script. If you don’t have it handy, you can press Ctrl+Alt+O to use the Quick Open Script window.
We add a new member variable called player_scores
: a
dictionary that maps a player’s name to their score.
Each key is a player’s name, and the corresponding value is their score as an integer.
# This dictionary uses player names as keys and their max score as the value.
var player_scores = {
"Scrooge McDuck": 99999,
"Magicka De Spell": 700,
"Gyro Gearloose": 200,
"Daisy Duck": 120,
}
I’ll let you write a couple of names and score pairs like above.
To “load” the scores into the scoreboard, we define the
_ready()
function and loop over each score.
func _ready() -> void:
for name in player_scores:
add_line(name, str(player_scores[name]))
We add a line in the scoreboard for each name in our
player_scores
dictionary by calling the
add_line()
function.
We can get the score for each name using the dictionary access
notation you learned in the Learn GDScript From Zero app:
player_scores[name]
.
On top of displaying scores in our dictionary, we want to keep them up to date.
If a player beats their previous best score, or if a new player completes the game, we want to keep track of that.
We update the add_line()
function to store the new
player score.
func add_line(player_name: String, player_points: String) -> void:
#...
# If there's a key matching player_name in the dictionary, this line will
# update the corresponding score. If there's no key matching player_name, it
# will add an entry to the player_scores dictionary.
= player_points player_scores[player_name]
If you now run the ScoreForm scene, after entering a name and a score, you should see your name added at the bottom of the list.
Later, you will learn how to save and load data from a hard drive and structure it properly.
But we have to take things one step at a time.
You learned many new techniques in this project. In the following two projects, you’ll get to reuse and build upon what you’ve learned here.
Here is the complete code for this project.
ScoreLine.gd
extends HBoxContainer
# We first get the two label nodes and store them with onready variables.
onready var points_label := $PointsLabel
onready var name_label := $NameLabel
# For each of the labels, we define a function that we will call from the
# scoreboard.
func set_player_points(points_value: String) -> void:
# The function String.pad_zeros() adds zeros in front of the score to make
# every score the same size. In this case, 6 digits.
= points_value.pad_zeros(6)
points_label.text
func set_player_name(player_name: String) -> void:
= player_name name_label.text
Scoreboard.gd
extends PanelContainer
# This dictionary uses player names as keys and their max score as the value.
var player_scores = {
"Scrooge McDuck": 99999,
"Magicka De Spell": 700,
"Gyro Gearloose": 200,
"Daisy Duck": 120,
}
onready var scores_column := $MarginContainer/VBoxContainer/ScoresColumn
func _ready() -> void:
for name in player_scores:
add_line(name, str(player_scores[name]))
func add_line(player_name: String, player_points: String) -> void:
var line := preload("ScoreLine.tscn").instance()
add_child(line)
scores_column.set_player_name(player_name)
line.set_player_points(player_points)
line.# If there's a key matching player_name in the dictionary, this line will
# update the corresponding score. If there's no key matching player_name, it
# will add an entry to the player_scores dictionary.
= player_points
player_scores[player_name]
func _on_HideButton_pressed() -> void:
hide()
ScoreForm.gd
extends Control
onready var scoreboard := $Scoreboard
onready var name_field := $HBoxContainer/NameField
onready var points_field := $HBoxContainer/PointsField
func _on_OkButton_pressed() -> void:
# If either field contains no text, we stop the function.
if not name_field.text or not points_field.text:
return
show()
scoreboard.add_line(name_field.text, points_field.text)
scoreboard.= "" name_field.text