These are the basic principle of the godot game engine.
A common place element in game development is the game loop. This is a code that gets executed every frame to update the game world, check user input, and draw the result to the screen. Godot has two types of game loops: Idle and Fixed. The Idle process is so called because every frame is drawn as fast as possible. The Fixed processing has a fixed timestep that is synchronized with the physics loop, with a default of 60 FPS (Frames Per Second).
Custom Nodes and Resources
It is possible to create your own node types by creating new editor plugins. Custom nodes and Resources appear in the dialog list, so they behave like core types. How to do this won’t be covered in this book, but it can be found in Godot engine’s official documentation.
Resource Locations and Uniqueness
Resources in Godot can either be saved inside the scene file or as its own separate file. There are advantages and disadvantages in both workflows, and it’s usually best decided case by case. In general, if you reuse the Resource across scenes, it is best to save as a separate file so it can be load in multiple places.
You need to understand that Resources are shared by default. If you duplicate a node in the tree, the Resources they use will be shared, and if you edit one, it’ll affect all instances that use it. Usually, this behavior is desired (Godot ensures that the Resource is loaded only once from the disk, increasing performance), but if you want to have two different copies of the Resource, you need to make them unique.
When you change the original scene on the disk, all instances will be updated to reflect the new values. Note that if you change a property of an instanced scene, it won’t affect the original, and if the original ever changes, this property won’t be updated. To revert the property to its original value, you need to click the Revert button beside the property in the Inspector dock.
You can consider the Viewport as a Cartesian plane where the (0,0) position is the top left corner and the Y axis goes downward
Nodes are drawn in the tree order.
Note that you have some other options, such as setting the Z-index of the node (higher Z values are drawn on top) or enabling the Show Behind Parent property. But the latter option is limited, and the Z value is less performant than the tree order.
Remember that the position and scale of a node is affected by its parent. Sometimes you want that to happen but also want that node drawn before other nodes above it in the tree. For this use, there’s the RemoteTransform2D node. You can add it as a child of the node, which applies the transform and targets the node you want to draw behind. Then you can leave the node higher in the tree and have it affected by another node’s transform.
the Region property allows you to show only a part of the texture in the game. This is very useful if you have a sheet image with many items and want to display a single one without slicing the image.
In the bottom panel, you can find a Texture Region editor. This tool can be used to visually slice the image and select exactly the portion you want to show. Note that this tool is only available when a Sprite node is selected.
It is not uncommon for a game to have levels bigger than the window. In an RPG, the player usually has a large world to explore. That’s where Cameras come in. Instead of moving the whole world to fit the viewport, you can simply add a Camera and make it follow the player.
Now that you have a TileSet resource ready, let’s use it to make a game stage. Using a TileMap is very simple; you just need to add a TileMap node to the scene and set its TileSet property to the file you just created.
Create your TileSet
Grab your favorite tile set image(s) and learn how to make your own TileSet resource by following these steps:
Third-party TileSet and TileMap Tools
There are several third-party tools to make TileSets and TileMaps, such as the Tiled Map Editor. While Godot does not support those out of the box, you can find plugins in the Asset Library. There are also plugins to split your tile set image automatically into a TileSet resource.
Another interesting and useful node is the ParallaxBackground. It allows you to easily make the parallax effect, in which distant objects seem to move more slowly than closer ones. This effect is common in side-scrolling games and gives another depth to the visual aspect of your game.
The node itself is a helper for you to achieve the desired effect.
The ParallaxBackground works by having multiple ParallaxLayer nodes as its children
Scale: This is how much this layer moves relative to the background offset. Lower values make it go slowly, and it’s used for further layers. You can set different scale values for each axis.
Offset: This is the starting offset of this layer. This makes the layer start in a different position.
- Mirroring: This is the size of the layer frame. Once it passes the size defined here, the layer will start repeating. Note that if this property is less than the screen size, it may not work as intended.
- The filtering of textures may cause artifacts if the Sprites are close together. This can be fixed either by disabling the filter of the texture in the Import dock or enabling the Filter Clip property of the Sprite.
- Try to avoid complex computations in
_processruns on every frame the engine renders; if
_processis still busy following an algorithm, the engine won’t be able to start working on the next frame.
This means if you have huge computations on every, or some, frames, the frame rate will drop.
- get_node() is using unix-style paths. To access a child node called A, you would do
get_node("A"), to get the child B of A, you would do
get_node("A/B"), and to get the sibling node C, you would do
- Try to avoid using get_node in _process and save a reference in a variable instead.
- Signals are an implementation of the observer design pattern.
- An object can emit multiple possible signals. When a signal is emitted, all the “listeners” (or observers) will get notified (or more specifically, a method gets called). It can also be seen as providing a callback to the object that is emitting the signal.
- In a game project, it often is advantageous to define your own signals to reduce coupling between objects.
- Signals are also very useful for managing scene changes, achievement systems, game-progress systems, and many more things to reduce complexity in the code base.
- There’s a method in the Scene Tree that allows you to call a method in every member of a group. This is like the reverse of signals: instead of emitting for anyone who’s observing it, this will broadcast the information to everyone in the group. You can use this by calling
Mode property: 2D and viewport.
The 2D mode renders the game at the current desktop resolution while stretching it to fit the screen.
The viewport mode renders the game precisely at the specified resolution in the Width and Height properties into an off-screen image, then stretches that image to full screen.
This might superficially sound very similar, but it has very different implications on the look and feel of the game. We encourage you to play with these modes after you finish making the game to get a better feel for it.
To simulate a more retro look and feel, prefer viewport mode.
Pixel art-friendly settings for Imports
Select an imported image, click on the Import tab, click on the Preset button, select the 2D Pixel preset and click on Reimport below, Godot will reload the image with .
After changing to a desired preset, you can choose Set as Default for ‘Texture’ after clicking on the Preset button. This applies your preset for every future image you bring into the project.
Godot has a notification system through which objects can send messages to other objects.
A “notification” is just a number that corresponds to a constant defined somewhere else.
To send a notification to an object, the method
Object.notification(int what, bool reverse=false)is used
_notificationmethod receives all notifications sent to an object.
- Most of notifications can be treated by overriding methods (
Example of notifications without an associated overridable method:
NOTIFICATION_PARENTED: the node gets assigned a parent node.
NOTIFICATION_TRANSLATION_CHANGED: the selected language in a game gets changed (by using
TranslationServer.set_locale). This gets used to update all the texts that can be localized.
NOTIFICATION_UNPAUSED: the node gets unpaused.
NOTIFICATION_INSTANCED: a scene gets instanced and all the nodes in it are created.
NOTIFICATION_UNPARENTED: the node’s parent gets removed (it no longer has a parent, but it still exists).
- NOTIFICATION_PAUSED: the node processing is paused (using
Example of of Main Loop Notifications
NOTIFICATION_WM_MOUSE_ENTER: the mouse cursor enters the window.
NOTIFICATION_WM_FOCUS_OUT: the window loses focus.
NOTIFICATION_WM_QUIT_REQUEST: the game should close.
NOTIFICATION_WM_MOUSE_EXIT: the mouse cursor leaves the window.
- NOTIFICATION_WM_FOCUS_IN: the window gains focus.
GDscript has a simplified syntax for accessing singletons (that are C++ classes). Instead of calling a method to access the singleton, it knows which singletons exist, and lets you access them by writing the name of the class as if it were the object
Commonly used singletons:
- ResourceLoader: Has methods for loading resources from the file system.
- OS: Has methods for using operating system functions
- Engine: Has methods for getting information about some properties of the running engine,
- ClassDB: This class has all the information about Godot classes you can use in any scripting language. It can be used to create instances of classes you only know at runtime,
- ProjectSettings: Can be used to set and get values from Project Settings
- InputMap: The programmatic counterpart to the Input Map tab in the Project Settings window.
- Performance: Can be used to get information about various processes in the engine, such as the number of draw calls used in the last frame, how many objects currently exist, how many nodes exist,...
- Input: Used to get information about all kinds of user input methods
An autoload is a node that gets loaded at startup and stays loaded for the entire runtime of the application/game.
Autoloads can also be scenes loaded from a path to a scene file. This means the scene can be created from the editor and have a scene tree (multiple nodes), and a root of a specialized type (not just a Node).
An autoload is always located in the scene tree as a child of the root node . The node itself is a simple Node node and the name of the node is the name of the autoload. So, an autoload named “GlobalGameState” would be located in
To create an autoload, you have to create a script that extends the Node and saves it somewhere in the project directory . Then add it using the AutoLoad tab in the Project Settings window.
The tool mode lets a script run in the editor instead of just when you run the scene.
Every script that gets executed in the editor must have the
tool keyword at the top of the file.script.
There are two common ways to use tool mode scripts: creating an EditorPlugin or an EditorScript.
Both share a common interface, so learning about using EditorScript will also help when trying to write an editor plugin.
If a script inherits from EditorScript, it can run in the editor, make changes to the current scene, and perform other actions that the editor can do, such as importing files or saving scenes and resources...
EditorScript has access to the editor interface through the
To run an editor script inside the editor, open it in ScriptEditor, then click “run” in the “file” menu (or Ctrl + Shift + X).
There are two ways to get user input:
1. Input Functions (callbacks)
These functions are called every time when the user makes a change
This is mostly useful when the input of interest involves changes to the input device; for example, choosing button press or release, mouse move or click, and screen touch or drag. You might want to get the input this way when dealing with user interface or game actions, such as attacking, shooting, using an item, etc.
_input(event) is a virtual function of a generic Node type that is called every time there is a change involving input devices. The node lowest in the hierarchy is called first.
eventis an object of the InputEvent class containing information related to the received input. Most important are the subclasses that derive from this class
- When a node responds to the input, it should call
get_tree().set_input_as_handled()to prevent other nodes from responding to it again.
falseto stop getting callback. Setting it to true will resubscribe the node to receive input events.
_unhandled_input(event) is similar to
_input (event) and is also a virtual function of a generic Node type. However, it is called in every node in the tree when an input event passed to
_input is not marked as handled
falsestops the node from getting callback.
2. Input Singleton (Querying the device)
Input is a singleton that manages inputs at global level.
This is useful when you want to know if a specific button is being pressed at the time. You might want to do this every frame (in _process callback) to make the player character move when a player holds a button down.
Note: Mouse-wheel scrolling cannot be reliably detected by querying Input singleton
InputMap singleton keeps a list of Actions and events associated with each of them. Here you can add an Action, add an event to an Action, and check if an event matches an Action. It is very useful when you want to save or load user-defined controls
InputEventAction can be used to simulate player actions. For example, a game has
move_up Action, associated to
KEY_UP, defined in the Input Map. You can to simulate this action by using