Build your first game
Pt.4 Detecting the player
Published: Tue May 27 2025 00:36:25 GMT+0000 (Coordinated Universal Time)
Detection methods
Explanation:
We have made 3 nodes so far. The GMAP 2D node we are using as a container and logic controller for the game as a whole.
The player, a solid, moving entity.
The floor, a solid unmoving entity.
Next we are going to focus on non solids called, mainly Areas and Raycasts.
These two are incredibly versatile, but we'll be using them for three things primarily:
1. Informing us when it detects something entering its area.
2. Informing us when something leaves its area.
3. Making certain things happen continously if another entity is detected.
Some of these nodes we will only ever want to detect the Player. Which is why our code has the player showing up in layer 1 and 2. By telling our detectors to only look for instances in layer 2, they will only ever trigger by the player.
Instructions
Editing Player script
Ctrl + alt+ o, type in player, press enter
Create three new functions for player, adding them to the bottom or wherever allows you to be organized:
Code Snippet 1
func die():
death_sfx.play()
global_position = spawn_point
func set_spawn_point(loc):
spawn_point = loc
#Keeping track of if we played the landing SFX yet
func land_check():
if is_on_floor():
if not grounded:
land_sfx.play()
grounded = true
if !is_on_floor():
grounded = false
Making new code work:
In _ready(), add this line, at the correct indent of course:
set_spawn_point(global_position)
At the bottom of your _physics_process() function, add this to run the check every frame if the landing sound needs to be played. Remember to keep the white space level correct:
land_check()
Press F5 to play your game and confirm it still runs, and that jumping causes the landing sound, nothing else should have changed yet.
Creating our death plane
Description:
Next we are creating our death plane using an “Area2d”. Area2ds get assigned collision boxes like our other game objects, but instead of blocking movement, they report when something enters or exits the range, allowing code to be ran when that happens.
First we will make an area 2D that detects when the player is below the level, and sends them to their respawn point when that happens.
Instructions:
Ctrl+f8, ctrl+n, ctrl+a
Press enter, type in Area2d, enter, press enter again to rename and rename to “DeathPlane”
Ctrl+a, type in collisionshape2d, press ENTER (Previously we have been using GMAP function for this, but this is a special case.)
Ctrl+U
Tab twice, ENTER, press down then select New WorldBoundaryShape2d
Ctrl+s and enter to save with default name
Ctrl+F8, press down and confirm DeathPlane has focus, then shift+tab twice, select, create script.
Enter the below code below the “extend” line:
Code Snippet 2
#Anything that has a function named die, will fire if they enter this range.
func _on_body_entered(body: Node2D) -> void:
if body.has_method("die"):
body.die()
Adding a signal
We are now going to attach a signal to this code. A signal detects when a specific event happens, then calls the code we choose.
Ctrl+f9, tab 4 times, then press down until you find body_entered, press enter, then enter again.
This now tells our boundray that whenever it detects a body, to run _on_body_entered().
Which will result in anything capable of doing so, dying.
We will now add our death plane to be below our level.
Ctrl+shift+o, type in game, enter
Ctrl+f2 to open GMAP Editor
Navigate in GMAP to below your level, and put in “death_plane”, or press down in edit mode and find it on the list and press enter. The name in the editor will be what it is saved as, which will be lower case and with _ if left at default. Or whatever you saved the .tscn as.
Press tab to make sure it saves.
Press f5 to test your game
Now if you jump into the abyss, you should go back to the spawn point!
Creating a check point
Description:
If things make the player respawn, we want a place for them to respawn. So we are going to create an area 2D to function as our check point.
We are going to add three useful features to our check point.
1. When touched, updates our respawn point.
2. The next check point we want the player to go towards will play a noise.
3. Function as a sign post the player can read by pressing space on it.
But we will do these one at a time, starting with our respawning!
Instructions:
Ctrl+f8, Ctrl+N, Ctral+A - going to scene tab, creating a new scene, opening the menu to pick a root node for the new scene.
Area2d, Enter.
Press enter, rename to Checkpoint.
Ctrl + = (equal sign), or shift tab twice, Enter, to create a new script.
Press enter to create a script with default name of checkpoint.gd
Below the “extends” line, enter this:
Code Snippet 3
#Adding for beacon SFX, we'll use this later!
@export var seq:int = 0
@onready var game = get_parent()
@export var text:String
func _ready():
# this is a function that came with the addons and is not part of Godot.
# it creates a CollisionShape2d, makes it a rectangle of x,y then attaches to self. Then the last argument is it should have a graphic or not. It is optional and defaults to false
GM.create_collide_rect(64,64,self)
#Only the player is on layer 2, and we only want to trigger for player
collision_mask = 2
Creating a Signal
Confirm Checkpoint has focus (Ctrl+f8, arrow down to Checkpoint)
Press Ctrl+ F9
Press down until body_entered is selected, press enter twice.
This will create a function for you that will auto be called when the event happens.
Right now it is empty.
Replace the default function with the below function:
Code Snippet 4
func _on_body_entered(body: Node2D) -> void:
if body.has_method("set_spawn_point"):
body.set_spawn_point(global_position)
#The second half the message is a lie. Guess what we are going to do soon!
get_parent().send_message("Checkpoint reached! Press space to read my hint!",self)
game.current_sequence = seq
Add checkpoint then test
Make Game the active scene using either ALT+f10 and left/right to find it if still open, or Ctrl + shift + o and type in “game”
Ctrl+f2 to go to GMAP
Type in checkpoint, or pick from the list by pressing down, wherever you would like a check point. I put mine by the edges.
Ctrl+S to save your game, then F5 to play it.
Activate the check point then jump off the edge to make sure your check points are working!
Scaredy cat Mechanic
Description:
We want the player to get a warning when they are close to the edge. We can do this using RayCasts.
They are like Area2Ds where we can use them to report collisions without changing movement, except they are a line going from point A to point B instead of a shape. So to make our detector work, we are going to have 3 short lines go out from the bottom of the player. One in the middle, then one on the left and right edge.
That way we know that the player has approached the edge if the right or left are not colliding with the ground, and the player is in danger of falling if the center is not colliding.
Instructions:
Ctrl+shift+o, type in player, press enter to open the player script.
At the top between the “extends” and “ready”, wherever helps you stay orgaznied, add the following:
Code snippet 5
#creating ray cast to help detect edges
var scared_left =RayCast2D.new()
var scared_right=RayCast2D.new()
var scared_middle=RayCast2D.new()
Code Snippet 6
Under the _ready function, add the following code.
#making our three vectors just go a few pixels facing down
scared_left.target_position = Vector2(0,2)
scared_right.target_position = Vector2(0,2)
scared_middle.target_position = Vector2(0,2)
#by using position, we are setting them relative to the player. We made our player 32x32, and everything is from the center of the player.
# so we want all our ray casts to be 16 pixels down, then one 16 to the left, the right, then center
scared_left.position = Vector2(-16,16)
scared_right.position = Vector2(16,16)
scared_middle.position = Vector2(0,16)
#bring them out of the void
add_child(scared_left)
add_child(scared_right)
add_child(scared_middle)
Adding Functions
Next, let’s make a new function. Anywhere outside any other function to be organized works.
Also, remember CTRL+ALT+F opens a list of all functions on the currently open script to jump that function.
Code Snippet 7
func near_edge_check():
var check= -99 #we'll make this the volume adjustments
#just keep it playing, we'll have it muted when not needed
if scared_sfx.playing == false:
scared_sfx.play()
# don't need to check if not touching the floor at all
if is_on_floor() == true:
#if the middle is not colliding, we'll set it to max volume, since it means we are more than half way hanging off the edge. Which simply will mean "not reduced"
if scared_middle.is_colliding() == false:
check = 0
# if either edges are hanging off, make it a little less loud
elif scared_left.is_colliding() == false or scared_right.is_colliding() == false:
check = -8
# otherwise, we are nice and safe. Make it inaudible.
else:
check = -99
scared_sfx.volume_db = check
#end code copy
Test
Finally anywhere in _physics_process, I recommend under move_and_slide() so all functions are together add this:
near_edge_check()
Press F+5 to play your game and test the new mechanic.
You should hear a low rumbling that gets louder if you get close to the edge.
Too loud? Not loud enough? Want there to be a different noise? Always feel free to tinker with the code to make it feel better to use!