Build your first game
Pt.6 Adding fun stuff!
Published: Tue May 27 2025 00:44:17 GMT+0000 (Coordinated Universal Time)
Fun
Explanation:
Moving around should feel pretty comfortable now. We have a simple map, can get coordinates, and our checkpoints call us forward, but the world is empty.
So next we will add three scenes that are focused on fun and allowing creative level design.
- A floor trap that is always on and makes player respawn when touching it and makes a noise.
- A scene that moves the player up
- A timed trap that recharges and has multiple zones to give players warning of danger.
Instructions:
CTRL+F8
CTRL+N
CTRL+A
Aread2D
Enter
Enter, rename to Electric, Enter
CTRL + = , Enter to open script editor
Press enter to save script with default name
Code Snippet 1
@onready var game = get_parent()
var electric_sfx =AudioStreamPlayer2D.new()
const elec = preload("res://audio/electric.wav")
func _ready():
electric_sfx.stream = elec
GM.create_collide_rect(64,8,self)
collision_mask = 2
#gmap put things in the middle of the 64x64 cell, so we move it down so it's on the floor.
global_position.y +=32
#telling it how much it should pan. Adjust until it sounds good to you.
electric_sfx.panning_strength = 10
#How many pixels away it will start being heard, with closer = louder
electric_sfx.max_distance = 150
add_child(electric_sfx)
electric_sfx.play()
func _process(_delta):
if game.player.global_position.x+48 > global_position.x and game.player.global_position.x-48 < global_position.x:
electric_sfx.volume_db = 4
print("loud")
else:
electric_sfx.volume_db = -4
func _on_body_entered(body: Node2D) -> void:
if body.has_method("die"):
body.die()
Attaching Signal
With the script entered we want to attach the signal
CTRL+ F10
Press down until “body_entered” is focused
Press enter twice to attach to _on_body_entered, so that function will run when a body enters this area.
Ctrl+s to save if you haven't saved yet.
With signal attached, press CTRL+SHIFT+O to open scene picker
Type in Game, press Enter
Press F2 to go to GMAP
Add electric somewhere to your map,
Press F5 to test, then make sure you can hear it, and running into it sends you back to respawn!
Wind lift
Explanation:
Next we are going to make something that makes the player go up vertically. The options on how to do this are limitless and depend on your game. For this simple example we are making a “wind lift” where when the player walks into the Area2D they will hear a sound and be lifted up by being given a set velocity.
Two easy options to implement a change if you don’t like this way of vertical movement are:
Turn it into a ladder by making it only apply movement when holding a button. Could make it thin and put it against a wall to enable wall climbing.
Turn it into a spring or jump pad where it’s much smaller, and when the player touches it they get launched with a much higher velocity.y.
There is also easy support for “jump through” platforms and moving platforms. So plenty of options for moving the player around are easy to implement.
Instructions:
Exactly the same process as Electric, as this is a stand alone Area2D, but larger.
CTRL+F8
CTRL+N
CTRL+A
Aread2D
Enter
Enter, rename to WindLift, Enter
CTRL + = , Enter to open script editor
Press enter to save script with default name
Code Snippet 2
#We can use this in different places if we want!
@export var height:int = 300
@onready var game = get_parent()
var wind_sfx =AudioStreamPlayer.new()
const sfx = preload("res://audio/wind.wav")
func _ready():
wind_sfx.stream = sfx
var collider = GM.create_collide_rect(64,height,self)
collider.position.y -= (height/2) -32
#gmap put things in the middle of the 64x64 cell, so we move it so the bottom of the wind lift is touching the ground.
collision_mask = 2
add_child(wind_sfx)
func _process(_delta):
if has_overlapping_bodies():
var body = get_overlapping_bodies()
body[0].velocity.y = -300
if wind_sfx.playing == false:
wind_sfx.play()
else:
if wind_sfx.playing == true:
wind_sfx.stop()
Test
Place it in GMAP, F2 after selecting Game, directly above the ground. Based on the way we moved the collision box it will be placed flush against the floor of the cell it’s placed in.
This one works right away, so press F5 to test! I put another floor with a checkpoint near the top, so the player hears where to go. Allows easy movement to next level or for fallen players.
Fire trap!
Description:
Next we are going to make a trap that has an on and off state.This is going to be more complicated as we will want it to have a few different features!
We will want the player to know when they are over a disabled fire trap so they don’t think they are safe then take damage, have control over its on/off state, the player to know when it’s on, and the player to know when they are very close to the activated trap. So we will need our fire trap to be an Area2D with a collision box, then for it to have another Area2D with a collision box. One for the “damage” area and another for the “warning” area. The warning area will make a different sound based on if the trap is on or not.
By delaying the start times of the trap, we can make patterns! For the example I’m making it so they have a cascade effect. Where each one turns off a second after the one behind it. Then when the last of the 4 turn off, the first one turns on. So the player has to move through at the correct pace to not get hit.
Instructions:
ctrl+f8 (If not in scene tab yet)
Ctrl+N (Go to new scene tab)
Ctrl+A (opens node menu)
Type Area2D, press enter to create the new root node.
Press enter, rename to FireTrap
Create another Area2D as a child of FireTrap and name it WarningBox.
Create 2 children of FireTrap. Name them TimerActive and TimerRecharge.
Create a script with Ctrl + =
Enter, enter to create a script with default name.
Enter the following code! There is a lot, but nothing really new!
Code Snippet 3
#when the trap is active, how long it will be on for
@export var active_time:float = 4
#it will be on for active time, then turn off for recharge time.
@export var recharge_time:float =4
#How long to wait after the game starts for this to start processing. Can make patterns!
@export var delay:float =0
@onready var timer_recharge: Timer = $TimerRecharge
@onready var timer_active: Timer = $TimerActive
@onready var game = get_parent()
#letting the player know if they are just a few steps away from active fire
@onready var warning_box: Area2D = $WarningBox
var active = false
var fire_sfx =AudioStreamPlayer2D.new()
const flame_mp3 = preload("res://audio/flame_trap.mp3")
var fire_close_sfx =AudioStreamPlayer.new()
const fire_close_mp3 = preload("res://audio/fire_close.wav")
var idle_sfx =AudioStreamPlayer.new()
const idle_mp3 = preload("res://audio/trap_idle.wav")
func _ready():
fire_sfx.stream = flame_mp3
#telling it how much it should pan. Adjust until it sounds good to you.
fire_sfx.panning_strength = 10
#How many pixels away it will start being heard, with closer = louder
fire_sfx.max_distance = 200
fire_close_sfx.stream = fire_close_mp3
idle_sfx.stream = idle_mp3
add_child(fire_close_sfx)
add_child(fire_sfx)
add_child(idle_sfx)
GM.create_collide_rect(16,64,self,true,Color.RED)
GM.create_collide_rect(48,64,warning_box)
collision_mask = 2
warning_box.collision_mask = 2
#start after a “delay” number of seconds. Allows desyncing of the traps.
timer_recharge.start(delay)
#We don't want these to restart automatically, but to wait for the other to fire to turn on.
timer_active.one_shot = true
timer_recharge.one_shot = true
func _process(_delta):
#checking if player is over the damage area
if has_overlapping_bodies():
#kill player if active
if active == true:
get_overlapping_bodies()[0].die()
elif idle_sfx.playing == false:
idle_sfx.play()
else:
idle_sfx.stop()
if warning_box.has_overlapping_bodies() and active == true and fire_close_sfx.playing == false:
fire_close_sfx.play()
elif warning_box.has_overlapping_bodies() == false or active == false:
fire_close_sfx.stop()
func _on_timer_active_timeout() -> void:
active = false
timer_recharge.start(recharge_time)
fire_sfx.stop()
visible = false
func _on_timer_recharge_timeout() -> void:
visible = true
fire_sfx.play()
active = true
timer_active.start(active_time)
Attaching Signals
Highlight one of your timers
CTRL+ F10
Go down to “Timeout”
Press enter twice to automatically connect it to the code we created.
Do this for the other timer.
Test!
Add your new traps to the map, tinker with delay and length of each one until it’s fun, make sure you hear noises when in danger, can walk over it safely when not, and respawn when hit.
Then build your level! You are done with this tutorial!
If you want to keep working on this and make a big platformer, you can make more GMAP scenes and build a bigger level and change the starting scene, or make a special check point that when space is pressed on it teleports the player to a new room.
Or take what you learned and try totally new stuff!
I hope you enjoyed and would love to hear your feedback!