Build your first game
Pt.3 Building a level with GMAP Editor
Published: Tue May 27 2025 00:33:24 GMT+0000 (Coordinated Universal Time)
Building our level with GMAP
Explanation:
With our game scene, player, and floors created, we now have enough to make a level.
For this tutorial we are going to be using the GMAP editor, which adds a new tab specifically for editing GMAP 2D nodes. Its purpose is to replicate the basic features of the Cavas Editor, which is not accessible yet.
But it's in no way required to make games, many games don't care about placement at all. Even this game all the scenes could be instanced using code. But I personally find managing lots of instances in code difficult to understand.
So in this part we will start using the GMAP Editor to build our level and test our game.
Instructions:
Press Ctrl+f10 to get to “open scene tabs”, this is all the scenes we have opened recently. Then use right and left arrow keys to find "game" scene.
If that tab was closed, press CTRL+SHIFT+O to open the "quick scene picker" type in "game" then press "enter".
With "game" being our selected scene, we can now open GMAP Editor.
Press CTRL+F2, this takes us to the GMAP tab that replaced the 3D tab.
Press tab.
If it's not loading, select another scene, then reselect Game.
If you are in edit mode, press enter to leave edit mode.
You can navigate with arrow keys, then enter allows you to type. Here is where you can add items to the game room.
After pressing enter and you can type in the name of scenes, you can also press the down arrow key to access auto complete. If the box is empty and you press down, it will list all items that can be placed in it. If you type out a few characters, it will suggest based on that, or make a noise if it doesn’t match anything.You can also just copy/paste items if adding many of the same item like building a floor.
For now we only have our player and walls, so let’s build a small area to test. Build what you want, or follow along. The only requirement is not to put it at the very bottom, as we’ll want to put a death plane under our level!
Note:
The name you need to type/pick is the name the file is saved as, which by default will always be full lowercase and have_ instead of space.
Anything you put in GMAP that is not the name of a scene will be ignored, but still saved. So feel free to enter notes.
My level is small, with my character starting in the bottom left corner, with a wall directly to its left, floor for a couple tiles, a hole in the middle of the level, a few more floors, then 3 going upwards diagonally.
Drop focus from the Mapper to make sure it saves, but do not select another Scene.
Testing the game:
Press F5.
It will ask if you want this scene, which should be Game, to be the default. Press enter to confirm it as the default. Now whenever pressing F5 it will play the game starting from here.
As of now we can do the following:
Jump with W
Move around with AD
Press Escape to open our map that is generated by GMAP.
Pressing escape again will leave the map. The game will pause while in map. So you can even check while in air what is around you. This is a feature added with the GMAP Builder addon, to enable developers to more easily test. Developers can also choose to let players use it or keep it hidden depending on the game.
Close game when done making sure you hear running into walls, can jump, and walk correctly.
Adding ability to communicate with player:
With Game scene still being the active scene, let’s add a few nodes using the editor. CTRL+SHIFT+O opens scene picker if needed.
Ctrl+f8, goes to "Scene" tab
ctrl+A to create a new node
Type in “audiostreamplayer” , press up 3 times. This will get us the non 2d audio player, since this is for game alerts, then press enter. Pressing tab 3 times will get you to the list so you can explore the other options, but for this one we do not want the 2D one.
Press enter to rename, change name to AlertSFX
Ctrl+f6, ctrl+u, to get to the top of the Inspector, which lists all editable attributes of the node
Press tab until at "Assign Resource" button, then press enter.
Find "Quick load" in the list and press enter
Type in ping, press enter to attach.
Ctrl+f8, arrow down twice, then up once to make Game be the focused node.
Ctrl+A, type in canvaslayer, press enter to make a new node.
With Canvas layer focused, press Ctrl+A.
Type in label, press enter.
Press enter again and rename to “Updates”
Press up until Game is focused. Remember when pressing ctral+a or making a script, the item in this list with focus is what it will be attached to.
CTRL + = (equal sign) to create a script. Pressing shift tab twice from here will also get to the create/access script button.
Press enter.
Enter to create with default name.
As before, we do not want to modify the "extends" line. This extends line is special because we are not extending a standard built in node, but a custom GMAP node. So the top item should be extends "res://addons/gmap_viewer/game scripts/gmap.gd"
As a small hint, if after pasting code you get an error about mixed tabs/spaces, saving will auto convert. Some browsers do not send tabs across properly.
Below the “extends” line, enter the below code:
Code Snippet 1
#we'll put a reference to the player here for anything that needs to know what the player is doing.
var player
#since label is a grand child node, storing it in a variable makes referencing it easier.
@onready var updates: Label = $CanvasLayer/Updates
@onready var alert_sfx: AudioStreamPlayer = $AlertSFX
#used to help us make sure to not spam old messages, but we repeat a message if it's from a new source!
var previous = 0
#we will want to keep track of how far the player has gone. We will need this for later, unused for now.
var current_sequence = 0
func _ready():
#setting focus to label. So pushing a change to this location should always be picked up by screen reader.
updates.grab_focus()
#we will have children send messages to the player by passing the text to be read out, and their own ID
func send_message(message:String,source):
#playing if the message is the same, but from a new source. Such as a checkpoint or direction message.
if message == updates.text and source !=previous:
#making the message "different" so screen reader picks it up
updates.text = message + " "
previous = source
#play the alert that the message was updated. Only if it's not already going, don't wanna spam!
if alert_sfx.playing == false:
alert_sfx.play()
#same process, but if the message is new
elif message != updates.text:
updates.text = message
previous = source
if alert_sfx.playing == false:
alert_sfx.play()
#when receiving this, change the text of the label to make it retrigger
func resend_message():
updates.text = updates.text + " "
Changes to player script
Press ctrl+alt+O to open a different script, then type in player, enter. Remember, picking a new script does not change the scene. So the player script open, but the game scene should still be open.
Copy the below code to the very bottom of the page:
func ask_parent():
#this uses a different input method, where you don't have to make an event first, can just call it.
# reading out our current coordinates on the map using the GMAP function that builds the map, so using same system.
#Sine godots global_position can be confusing to players,rather use this one.
if Input.is_physical_key_pressed(KEY_SHIFT):
var loc = get_parent().gmap_get_cell(global_position)
get_parent().send_message("Current location is " + str(loc.x)+ " " + str(loc.y),self)
Final Changes
Anywhere in _ready() post the below code:
parent.player = self
Then directly below “Move_and_slide()” add the following line:
ask_parent()
Press ctrl+s to save, then F5 to run your code.
Pressing shift should read out your current location, which should help you get a better understanding of what is and isn’t working. Between that and ability to open the map, if anything doesn’t work out the way you want, you’ll be able to easily figure out source of the problem.
Close the game when you are ready to continue.