Godot Engine Memento

Tps de lecture estimé:13 minutes 36 secondes

Godot Engine Memento

These are the basic principles of the godot game engine.

References/Sources:

Part 1: "KidsCanCode Godot Recipes"

All the site is build to bring solution to common questions and issues with Godot.

This is the plan of all the explained subjects:

  • GODOT 101
    • Getting Started
    • What is Godot?
    • Godot's Editor: Finding your way around
    • Nodes: Godot's building blocks
    • GDScript
    • Intro to 3D
    • The 3D Editor
    • Importing 3D Objects
    • Creating a 3D Character
    • Using Areas
    • Edge Detection & Mouse Capture
    • Using CSG
    • First-person Character
    • BASICS
    • Understanding node paths
    • Understanding 'delta'
    • Saving/loading data
    • Circular movement
  • 2D
    • Entering/Exiting the screen
    • Platform character
    • Screen wrap
    • Splitscreen multiplayer
    • TileMap: detecting tiles
    • Top-down character
    • Grid-based movement
    • Car steering
    • TileMap: using autotile
    • KinematicBody2D: align with surface
    • Moving Platforms
    • TileMap: animated tiles
    • Screen Shake
    • Touchscreen Camera
  • 3D
    • Camera Gimbal
    • KinematicBody: Movement
    • 3D Unit Healthbars
    • Click to move
    • KinematicBody: align with surface
  • INPUT
    • Input Actions
    • Mouse Input
    • Adding Input Actions in code
    • Capturing the Mouse
    • Customizing the Mouse Cursor
    • Mouse: Drag-select multiple units
  • ANIMATION
    • Spritesheet animation
    • Melee attacks
    • Controlling animation states
  • UI
    • Labels
    • Containers
    • Cooldown Button
    • Heart Containers: 3 Ways
    • Object Healthbars
    • Floating combat text
    • Minimap/radar
  • GAMEDEV MATH
    • Interpolation
    • Transforms
    • Noise
  • MISC
    • Inheritance
  • PHYSICS
    • Using KinematicBody2D
    • Using Rigid Bodies
    • Kinematic Friction
    • RigidBody2D: Drag and Drop
    • Kinematic to Rigid Body Interaction
    • Using 2D Joints
    • Conveyor Belt
  • AI/BEHAVIOR
    • Chasing the player
    • Path following
    • Changing behaviors
    • Homing missile
  • SHADERS
    • Shaders: intro
    • Interacting with Shaders
    • Greyscale (monochrome) shader
    • Blur shader
  • EXPORTING
    • empty section
  • GAMES
    • Mobile Game: Circle Jump

Part 2: "Godot Engine Game Development in 24 Hours"

Scene System

Game Loop

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.

Instancing Scenes

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.

2D Graphics

Drawing

Viewport Coordinates

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

Draw Order

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.

Remote Transform

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.

Sprites

Sprite Regions

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.

Cameras

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.

TileMaps

Using TileMaps

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.

ParallaxBackground

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.

ParallaxBackground Node

The node itself is a helper for you to achieve the desired effect.

ParallaxLayer Node

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.

Notes

  • 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.

Scripting

Tips

  • Try to avoid complex computations in _process. _process runs on every frame the engine renders; if _process is 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 get_child("../C").
  • Try to avoid using get_node in _process and save a reference in a variable instead.

Signals

  • 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.

Groups

  • 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 get_tree().call_group("group_name", "method_name").

Projects settings

Display

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.

Scripting more

Notifications

  • 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
  • The _notification method receives all notifications sent to an object.
  • Most of notifications can be treated by overriding methods ( _ready,_proces,_enter_tree...)
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 get_tree().set_pause(true)).
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.

Singletons

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

C++: Input::get_singleton()->is_action_pressed("ui_accept"))

GDScript:Input.is_action_pressed("ui_accept"))

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

AutoLoad

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 /root/GlobalGameState.

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.

Editor Tools

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 get_editor_interface method

To run an editor script inside the editor, open it in ScriptEditor, then click “run” in the “file” menu (or Ctrl + Shift + X).

Input Basics

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.

  • event is 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.
  • set_process_input(enable): Set enable to false to 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

  • set_process_unhandled_input(enable): Set enable to false stops 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

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 Input.parse_input_event(action_move_up)

Article précédent Article suivant