Build your first game
Pt.5 Checkpoints
Published: Tue May 27 2025 00:40:36 GMT+0000 (Coordinated Universal Time)
Explanation:
As our game is taking shape, we now want to create objective markers. Something that plays directional audio to help guide the player. We will make use of the ability to assign variables to instances so we only have to make one scene for the marker, then tell the game what order to do play themin.
To start, let’s make our checkpoints do this. That way the next checkpoint in our game is making noise. This could also be anything. Could be an annoying fairy saying this way, could be the sound of an enemy you are chasing, a computer assistant, or just a UI beep that only plays when the player presses a button.
To do this we will give each checkpoint a sequence number, have the game room track the current sequence, and the only ones that will make noise are the ones right after. So at first beacon 1 will make noise, then once we touch it, beacon 2 will, and so on.
Instructions:
Earlier on, in game.gd we added the following variable:
var current_sequence = 0
We are now going to use it to keep track of which check point the player last touched, so the next check point will make a noise.
So we will now navigate to the code for checkpoint.gd to make that happen.
Alt+shift+O
Checkpoint.gd
In the class body, after the extends but before _ready(), add these new variables:
Code Snippet 1
#Making an audio stream player 2d,this will play in relation to our audio listener that is glued to our player
var guide_sfx =AudioStreamPlayer2D.new()
# a pretty glowy sound that should pull the player
const OBJECTIVE = preload("res://audio/objective.mp3")
Modifying ready function
In the _ready() function, add this code below what you already have. We’ve covered this already, but do review it if you're interested in learning how the code works!
Code Snippet 2
#assigning stream to our new item
guide_sfx.stream = OBJECTIVE
#telling it how much it should pan. Adjust until it sounds good to you.
guide_sfx.panning_strength = 10
#How many pixels away it will start being heard, with closer = louder
guide_sfx.max_distance = 400
add_child(guide_sfx)
#Audio attenuation. 1 is linear, 2 means most of the volume incresae happens in the final 50% of the distance. Below one means it reaches near max volume before reaching the source.
guide_sfx.attenuation =2
New functions
Then we will add a new function as we will try to keep things separated. Once again the goal is to make errors more useful, and the ability to jump between functions more helpful. So keeping functions as seperated as possible usually pays off.
Code Snippet 3
func audio_beacon():
#checking with the game room if it's this beacons turn
if game.current_sequence+1 == seq:
if guide_sfx.playing == false:
guide_sfx.play()
#making the pitch higher if above player, lower if below.
#By default, up is negative!
if game.player != null:
#moving pixels around so it's not always lower or higher. If we are within 64 pixels up or down, audio does not change.
if game.player.global_position.y+32 < global_position.y:
guide_sfx.pitch_scale = 1.2
elif game.player.global_position.y-32 > global_position.y:
guide_sfx.pitch_scale = 0.8
else:
guide_sfx.pitch_scale = 1
elif game.current_sequence != seq+1:
guide_sfx.stop()
Small adjustments
If your checkpoint code does not have a _process yet, simply add one: func _process(_delta):
Then add audio_beacon()” under the “_process” function in checkpoint.gd.
Now if the games current_sequence is 1 less than a check points seq, it should play a directional audio.
Edit gmap
Ctrl+o
Game.tscn
Ctrl+f2
We will now assign seq id’s to our check points.
Assigning variables to an instance is easy.
After the name of your instance, do a bar, variable name = value.
To assign check points their order we simply do this:
checkpoint|seq=1
checkpoint|seq=2
checkpoint|seq=3
Try it out! Add them in a chain in such a way that each check piont leads to the next.
Then test!
Sign posts:
Explanation:
Next we will make a sign post mechanic, where when you are at a checkpoint, if you press space, you will be read a message. The ability to assign a value to an instance will also be used here.
Without the ability to edit a placed instance, it would require making a new scene for every different sign.
You can do this without the GMAP editor if you place an instance in the tree view of Game, then go to the inspector for that instance and set a location and its text.
Or if you place it via code you can assign the instance the values there.
But I find editing it much easier on the map as there is minimal risk of getting mixed up which instance you are assigning a value to.
Instructions:
Ctrl + F3 if not in script editor tab
Ctrl+alt+o to open quick script pick
checkpoint.gd
Add this to your _process() code:
Code Snippet 4
#checking if overlapping with player and spaceboar/enter is pressed.
#with a collisoin mask of 2, we are only reacting to the player who is on collision layer 2 and 1 with a layer value of 3.
if has_overlapping_bodies() and Input.is_action_just_pressed("ui_select"):
get_parent().send_message(text,self)
If you add them as instances in the game room via scene tab, you can edit them in the inspector. But you can also change attributes using GMAP.
Editing instances with GMAP
Ctrl+f2 to get to GMAP
CTRL+SHIFT+O to open scene picker
Type in game and press enter to open our first screen
Find your first check point and add this:
|text = I am the first checkpoint! I hope you don't come back here too much!
Each variable assignment needs to be sepearted by a | . So my first check point now reads this.
checkpoint|seq = 1| text = I am the first checkpoint! I hope you don't come back here too much!
If you'd rather it be reversed that's fine too. Only ordering concern is name of the Scene you want to create an instance of is first.
I then created a second checkpoint near the first ledge a player should run into:
checkpoint|seq = 2|text = Careful! If you walk forward too much you’ll fall. But don’t worry your danger sense will tell you when. Take a few steps forward and listen! The louder, the more danger you are in.
You can’t write full scripts in this field, but you can assign values to attributes, and execute scripts with passed arguments. The arguments will be strings though, so be mindful! Simply break up each script/variable assignment with a bar | and it will work.
If you put quotes around the text, the quotes will show up in the message. Since text is a string attribute, our value will convert to that.
Press F5 and play your game, go to your checkpoints, press space, and confirm your messages play!