Basics
Godot is a free and open source cross-platform game engine that supports game design for 2D and 3D games. It is a great tool for beginners and experts alike. It is also a great tool for teaching game design and programming. This guide will help you get started with Godot and teach you how to make a simple 2D game.
Getting started
There are several options for developing with Godot. The recommended way is to download the latest version from the downloads page for Windows/macOS/Linux. It will be what we use for this guide.
- Run the engine in a web browser with the Godot Web Editor (v4.1.1). This is the easiest way to get started, but it has documented limitations and is not recommended for large projects.
- Download the android app from the Google Play Store, while functional it is in early access and may not be stable. It is also difficult to use on phones, and tablets are still difficult without a keyboard and mouse.
- The Godot engine is, somewhat ironically, on Steam!. This is good for automatically tracking how long you use Godot and updating to newer versions. To opt into previous versions got to properties after downloading and join the beta branch you need.
- Many Linux distros will have Godot in their native app store, such as the Pop!_Shop, AUR, or Snapcraft. Please note these are sometimes unofficial and may be different or unsafe. More often than not it’s better to run the executable from the normal Godot downloads page.
For most platforms outside of the web editor, you should face an interface that looks similar to this upon opening the program:
Creating a project
Making a new project
Click the New Project button to create a new project, the following window will appear:
- Project Name: This is the name of your project, it can be anything you want. For this guide, we will use Godot Is Awesome!. You can use the Create Folder button to create an empty folder with the name of your project at the project path.
- Project Path: This is the path to the folder where your project will be stored. You can use the Browse button to select a folder or type in the path manually. It is recommended you use an empty folder for your project.
- Renderer: Godot has three renderer presets: Forward+, Mobile, and Compatibility. For this guide, we will use the Forward+ preset. Forward+ is only good for desktop and console platforms, and has the most features. Mobile is best for mobile platforms, but supports desktop, and has fewer features with better performance. Compatibility supports desktop, mobile, and web platforms, it has the fewest features and the best performance. It is not recommended to use compatibility for 3D projects.
- Version Control Metadata: This is used to store version control information in the project folder. It is recommended to leave this on Git even if you are not using version control. It is also recommended to use version control for your projects, but it is not required. To use git version contol, after creating the project navigate to the project folder and create a git repository.
Workspace
The next window that’ll open is the meat of the game engine, it is where you make your actual game. At first, it can be a little daunting, all the buttons and docks, but it’s simple to understand once you’ve used it a bit. For this guide, we will use 2D to introduce all the key concepts. But, if you’re already familiar with game development and want to start with 3D, we have a 3d guide as well. If you choose this you may miss out on core aspects like signals.
The interface
The interface is made up of several docks. The most important ones are the Scene dock (top left), the Inspector dock (right), and the FileSystem dock (bottom left).
The four main screens of Godot are the 2D screen, the 3D screen, the Script screen, and the AssetLib screen. You can switch between them with the buttons at the top of the screen.
Components of a game
There are a few key concepts to understand in Godot:
- Nodes
- Scenes
- Scripts
- Signals
Everything in your game will be contained in a scene. Everything in your scene will be a type of node. Scripts add functionality to your nodes. Signals communicate to scripts when something happens to a node.
Making the main scene
To start out with you need to make a basic scene, we’ll return to scenes later but for now one big scene will work just fine.
At the top left under Create Root Node: click the 2D Scene button. This will create a new scene with a Node2D root node.
This should be the core scene of your game, or the scene that you do the core of your development in.
At any time save your scene with Scene > Save Scene or save all scenes with Scene > Save All Scenes, we saved the scene as main.tscn.
Nodes - Making the player
Nodes are the building blocks of your game. They are the objects that make up your game. They can be anything from a sprite to a camera.
Nodes are organized in a tree structure, with the root node at the top and child nodes below it.
Nodes can have any number of child nodes, but only one parent node.
Adding the nodes to the scene
You can see all the types of nodes with the Add Child Node button in the top left of the Scene dock, or by right-clicking any node in the Scene dock and selecting Add Child Node.
It’s worth taking a look at your options, but for now we’ll start with CharacterBody2D. It can be hard to find since it’s nested inside several nodes, but you can search for it in the bar.
Add CharacterBody2D as a child of Node2D
CharacterBody2D is a node designed for objects that interact with physics that will be controlled by the player. When adding a script it provides a lot of information and functions to aid in making a character.
The CharacterBody2D node alone will not do anything.
We need the player to be able to see the player and let it collide with things.
The Sprite2D node will let the CharacterBody2D be visible.
The CollisionShape2D node will let it collide with other colliders so the player can land on the ground and not just sink through it.
We also need to have the camera center on the player so add a Camera2D node as a child as well so it moves with the player and makes sure it’s always in the center of the screen.
Add Sprite2D, CollisionShape2D, and Camera2D as children of CharacterBody2D.
To make sure a node is a child of another node check that your scene tree looks like this: This is what having CharacterBody2D as a child of Node2D, and Sprite2D, CollisionShape2D, and Camera2D as a child of CharacterBody2D.
Modifying the node’s properties
On the Sprite2D node, you can change the texture property to a new texture.
On the right side of the screen you’ll see the Inspector dock, this is where you can edit the properties of the selected node.
If you want to use an image and don’t have your own, save the little birdie image below to your device with right-click > Save Image As… and drag it into the FileSystem tab in the bottom left of the screen, alternatively you can make your own image and use that. Once it’s in the FileSystem dock, you can drag it into the Texture property of the Sprite2D node.
Otherwise if you don’t care about an image right now you can use PlaceholderTexture2D which is just a magenta box.
If you do use a New PlaceholderTexture2D you should change the CollisionShape2D’s shape to a RectangleShape2D so that it matches up.
Set the Sprite2D Texture property to an image or PlaceholderTexture2D.
The CollisionShape2D node has a warning icon, this is because it needs a shape to define its collision.
Select the CollisionShape2D and change the Shape property, to a New CircleShape2D if you used the bird and New RectangleShape2D if you used a placeholder.
Your scene should now look something like this:
The ‘viewport’ is the largest area of the screen that shows the scene. You can move around the viewport with the middle mouse button and zoom in and out by scrolling.
Zooming into the small circle where the red and green lines meet, if you have the birdie image you might notice the pixelated texture is fuzzy.
This is because the texture is being scaled up to fit the size of the sprite.
To fix this, go to the Sprite2D node and change the property CanvasItem > Texture > Filter to Nearest. Only do this for pixel art textures.
In the future, if you do not want to change the Filter property for every Sprite2D node, you can change any parent node’s Filter property to Nearest and all child nodes will inherit it if their Filter property is set to Inherit. For an all pixel art game you might as well set the root node’s (Node2D) Filter property to Nearest.
Scenes - Making platforms
Scenes are collections of nodes that make up a part of your game. They can be anything from a single node to a complex hierarchy of nodes. Scenes can be saved as files and reused in other scenes.
You should rename your CharacterBody2D to “Player”.
You can convert the current CharacterBody2D node into a scene by right-clicking it and selecting Save Branch as Scene.
Save it as player.tscn, it should have this by default if you named your CharacterBody2D as Player.
Rename CharacterBody2D to Player and save it as a separate scene saved as player.tscn.
You’ll notice that it removed all of the child nodes from the Main scene you made at the beginning. If you click the new Open in Editor icon that appeared on your player, it’ll open up the new player scene.
Go back to the main scene by using the tabs at the top of the screen, we’ll make platforms first.
Make a StaticBody2D with Sprite2D and CollisionShape2D as children, then give them PlaceholderTexture2D and RectangleShape2D as texture and shape, respectively.
Rename StaticBody2D to Platform and save it in its own scene.
Okay, now click on that new Open in Editor icon next to your platform node in the scene tree.
At the top of the screen you should notice there are now multiple tabs, one for Main.tscn and one for platform.tscn. All work you do in this scene will apply to every copy of this scene.
Currently there is one copy of this platform.tscn scene in your Main.tscn scene, we call that an instance of the platform.tscn scene.
Zoom into the CollisionShape2D and Sprite2D and click on each of them, pull the orange handles to make them about this large compared to the feint blue box and how zoomed out my viewport is.
Go back to the Main scene.
Go to your player scene and do the same thing, make it smaller than your platform.
Start your magnificent game by clicking the Run Project button in the top right of the screen or by pressing F5. You should see a window like this: Press Select Current if you are in your main scene. Now your gorgeous game should be running! Here’s what my version of this game looks like so far:
Close the game and go back to your Main scene, move your platform below your player.
Let’s get some interaction in there.
Scripts - Making a deathbox
Scripts are what make your game do things. They are written in GDScript, a language similar to Python if you squint hard enough. As mentioned before, you can write scripts in C# as well, but it is not recommended for beginners. If you are familiar with C# you can use the C# documentation to help you write your scripts.
Making a new script
To add a script to a node, select the node and right-click > Attach Script or press the Attach a new or existing script to the selected node button above the node tree. For now, add a script to the player node, it will open a new window that looks like: The defaults are fine, but let’s go over what each field means.
- Language: This is the language you want to write your script in, for this guide we will use GDScript, and it will most likely be the only one you have available, but this is where C# would show up as well if you have it installed.
- Inherits: This is the class that the script will inherit from, the player should inherit from CharacterBody2D.
- Template: This is a template for the script, often you might want to set it to the default node or empty object, but for this character we will use the CharacterBody2D: Basic Movement template since it has basic functions you might want for your player already setup.
- Built-in Script: Built in scripts don’t make a separate file for the scripts, they are stored within the node. This is useful for small scripts that you don’t want to make a separate file for just to keep things clean, but it is not recommended for larger scripts or scripts that will be used by multiple nodes. For the player, we will not use a built-in script.
- Path:
This is the path to the script file. If you are not using a built-in script, it will be replaced by a “Name:” field. For the player, we will use the default path
res://player.gd
. It is a good idea to make a folder just for scripts or just for scenes to make organization easier, but for this small project this is easier.
Click Create and you should automatically switch to the script screen. It should have the script you just made loaded in and look like this: You can make the script take up the whole window with the full-screen icon in the top right, and if you have a console open, you can close it by pressing Output at the bottom of the screen, and zoom in and out with Ctrl + +/-.
Now if you run the game with F5 the player should fall down.
Modifying the default script
If you have never programmed before, it is recommended you start with a simple language like Scratch. If you are familiar with programming, but not GDScript, you can use the GDScript documentation to help you write your scripts.
The default script that came with CharacterBody2D should look like this:
There are some simple things you can do without adding or removing lines of code.
- Change the fields at the beginning of the script, SPEED and JUMP_VELOCITY. What they do should be self-explanatory, try changing the numbers after the
=
and running the game until you get something that you like the feel of. - Change the gravity by going to Project > Project Settings then in the General tab, Physics > 2D > Default Gravity. You can also change the gravity in the script by changing the line
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
tovar gravity = n
where n is a number of your choice. - Change the input keys by going to Project > Project Settings tab Input Map and pressing Show Built-in Actions. By looking at the script we can see it is using the actions ui_accept, ui_left, and ui_right. If you want to use WASD instead of the arrow keys, scroll until you find the ui_left action, then double-click the Left input and press A on your keyboard and then press OK. Do the same for ui_right with D.
Some unclear things about GDScript that are good to know:
extends CharacterBody2D
means that this script inherits from CharacterBody2D, so it has all the functions and variables that CharacterBody2D has, which extends from PhysicsBody2D, which extends from CollisionObject2D, and so on until it reaches the root node Object. This script has access to every single function and variable from each of those nodes!- Functions that start with an underscore, like
_physics_process
, are called automatically by the engine. - You can use CTRL + Click on Windows or ⌘ + Click on macOS to go to the definition of a function or variable. This is useful for seeing what a function does.
- Multiply a variable by
delta
in the_physics_process
function to make it framerate independent. This is useful for making sure your game runs at the same speed on different devices. For example, if you want to move a node 100 pixels per second, you would multiply the velocity bydelta
, which is the time between the previous frame and this one measured in seconds:velocity.x += 100 * delta
. This is to make it so that when enough frames have passed so that 1 second has passed, it would’ve been100 * 1
but spread out across tens of frames to make the motion smooth instead of increasing the velocity by 100 pixels every frame, which is absurdly fast and may be faster or slower on different monitors or devices. move_and_slide()
uses the velocity of the node to calculate where the node should move to on this frame, which is why you don’t need to give it any parameters and run it after you have calculated the velocity.
Making a deathbox
Let’s add a deathbox to the scene.
You should copy paste your platform around the Main scene so that when you play the game you have a small obstacle course to jump around in.
For this we’ll just say if the player is below the Y coordinate of 500 we’ll reset the player to their reset_position.
This is pretty simple, we need 3 things.
- A variable saying where to reset to.
- Check if the player is below Y 500 every frame.
- Reset their position if the player is.
Take a look at the code already there as a guide. We can see:
- A variable being set with
var gravity =
. - The Y value of the velocity being changed with
velocity.y += gravity * delta
. - An if statement used several times.
These are the main ingredients we need.
Make a new variable and set it to
Vector2(0, 0)
.var reset_position = Vector2(0, 0)
If you haven’t moved where your player starts the game then the coordinates 0, 0 will reset it to the origin of the world, where the green and red lines meet in the viewport.
Make a new if statement among the other if statements and check the global Y position and if it’s over 500.
if global_position.y > 500:
If you put this in _physics_process
it will check this every frame. When the global Y position is over 500 the next indented line will run, if it’s not over 500 then it will not run.
Add an indented line (A line that is spaced to the right by pressing Tab before it) setting the player’s global position to the position it should reset at.
global_position = reset_position
In all likelihood, if you run the game and jump to your previously interminable fall, now you should reset to the beginning.
If you didn’t, check the positions, check the if statement.
If you’re not moving at all it’s most likely because you haven’t indented your global_position = reset_position
.
You can see the simple 3 lines of code that got this working:
Signals - Making checkpoints
Signals are the fourth building block of Godot. They are used to communicate when something happens between nodes.
Add Area2D as a child of Node2D, and CollisionShape2D as a child of Area2D.
An Area2D has some good built-in signals that communicate when a body like a CharacterBody2D enters it.
Move the Area2D to somewhere further along your obstacle course, then give the CollisionShape2D a rectangle shape and make it take a bit of the platform.
It should look something similar to this.
Click on your Area2D in the scene tree and on the right of the screen go to the Node tab.
Once here, double click the body_entered(body:Node2D ) signal. It is imperative you select the body_entered and not the area_entered one, otherwise it will not detect the player.
Once you get to this screen, change the Receiver Method to _on_checkpoint_entered just to make things clear.
Make sure you have the player selected from the list of nodes, then click Connect.
I want you to stop and think if you haven’t already seen the next couple lines. We have a variable that sets where the player resets to. This function, or rather this code where pass
is right now runs when the player enters the checkpoint. What should you put here?
This line is interspersed
with code snippets
so that the real answer is less visually distinctive and people who want to
give it a go can actually try thinking of the line they need
. The line needed is reset_position = global_position
but people need a good chance to try and form some brain connections naturally
.
Next steps
For a good introduction to writing your own scripts to control nodes, see the Godot documentation. At any time, you can also use the Search Help button in the top right of the Script screen to look up any function or variable.
If you have followed this entire guide, you know enough terminology and technique to make almost any 2D game! You will definitely need to look things up and reference the documentation, no one stops using google, but the more you create, the more you will develop muscle memory and gain understanding. 3D games aren’t much more difficult, read the guide on making a 3D game.
To test your skills, try adding some simple things almost all 2D platformers will have:
- Giving the player a double-jump.
- Try adding a parallax background (hint: Godot has a premade parallax background node), you will need your own art.
- Finally, give the player coyote time (hint: use Godot’s timer node in the player scene) If you don’t know what coyote time is in 2D platformers, look it up, it makes the game feel much better.
If you can do those things by looking up the documentation and using tutorials, then you have developed the skills to make anything you want in Godot.