Use JavaScript in extensions
Embed JavaScript libraries in extensions
After creating a new extension, you need to define an action with a JS event to declare the library code.
In order to get the library code, you can copy the content of a bundled library for instance a UMD one. You can usually find bundled libraries in the node_modules folder of a JS project after the installation of the library with a packet manager.
Bundled libraries have some extra code at the beginning and the end of the file to bundle the library. This code is not needed. Instead, the classes are added to the gdjs
namespace like in the following code:
// Avoid to declare the library several times.
if (gdjs._myNewExtension) {
return;
}
// My library function and classes
const myPrivateFunction = () => {
// Some code here.
}
const myPublicFunction = () => {
// Some code here.
}
class MyPrivateClass {
// Some code here.
}
class MyPublicClass {
// Some code here.
}
// Add all public function and classes to `gdjs` namespace.
gdjs._myNewExtension = {
myPublicFunction,
MyPublicClass,
};
Warning
Make sure never to use the runtimeScene
given by the JS event when declaring a library because it is the scene at the declaration which is unlikely to be the same one when the code is called. Instead, the caller should pass runtimeScene
as parameter.
This action must be called before the first scene is loaded in the onFirstSceneLoaded events function. When a behavior uses the library, it must also be called at the object creation in onCreated because instances in the scene editor are created before onFirstSceneLoaded is called.
Instantiate a state
Instantiate a state on a scene
When a new scene is loaded, you can initialize the attributes you need in the onSceneLoaded event function.
runtimeScene._myNewExtension = runtimeScene._myNewExtension || {
myAttribute: new gdjs._myNewExtension.MyPublicClass(),
};
These 2 extensions instantiate a state on scenes:
- The Noise generator instantiates a manager that gives generators from their names.
- The Curved movement also instantiates a manager for curves.
Instantiate a state on an object
When a new object instance is created, you can initialize the attributes you need in the onCreated event function.
behavior._myNewExtension = behavior._myNewExtension || {
myAttribute: new gdjs._myNewExtension.MyPublicClass(),
};
These 2 extensions instantiate a state on behaviors:
- The Boids movement uses a state to keep track of Boids speed.
- The Object stack uses a state to keep track of the object in the stack.
Wrap JavaScript libraries in events functions
Get parameter values in JavaScript
Number, string and boolean parameters can be accessed with getArgument
. Parameter names are case sensitive.
const angle = eventsFunctionContext.getArgument("Angle");
For object parameters, getObjects
must be used. It gives an Array
of RuntimeObject
.
const players = eventsFunctionContext.getObjects("Player");
for (const player of players) {
}
Call a library from an event-function
After getting the events function parameter values, you can pass them to a JavaScript function.
Call a "static" function of the library
gdjs._myNewExtension.doSomething(myParameter);
Call a function on an instance from a scene state
runtimeScene._myNewExtension.myAttribute.doSomething(myParameter);
These 2 extensions call functions on a state they created on scenes:
- The Noise generator
- The Curved movement
Call a function on an instance from an object state
behavior._myNewExtension.myAttribute.doSomething(myParameter);
These 2 extensions call functions on a state they created on behaviors:
- The Boids movement
- The Object stack
Return an expression value in JavaScript
For expressions, you need to return a number or a string by setting returnValue
.
eventsFunctionContext.returnValue = gdjs._myNewExtension.getSomeValue();
Return a condition value in JavaScript
For condition, you need to return a boolean by setting returnValue
.
eventsFunctionContext.returnValue = gdjs._myNewExtension.isSomethingRight();
Wrap JavaScript libraries in events-based behaviors
In case you are writing your first custom behavior, please refer to the custom behavior page to learn more about them.
Get an object behavior in Javascript
Behaviors parameter values are actually just a string of the behavior name. Each object instance has their own behavior instance so it avoids to pass an array for behaviors when they can be mapped from objects with object.getBehavior(behaviorName)
.
For actions and conditions of behaviors, the object parameter Object only contains one instance because GDevelop does the iteration on object instances. For other object parameters you still need to iterate on all instances.
const object = objects[0];
const behaviorName = eventsFunctionContext.getBehaviorName("Behavior");
const behavior = object.getBehavior(behaviorName);
Get behavior property values in Javascript
Behavior properties can be accessed from getters. The property name defined in the property editor is prefixed with _get
. Property names are case sensitive.
const myPropertyValue = behavior._getMyProperty();
Setters also exist, but you should not need them. Behaviors may have events functions to change its property values but it's easier to implement them with events. If you need to change property values from your JavaScript code, you probably should use JavaScript attributes instead and define expressions to let events access their values.
Use the power of both events and JavaScript
Although GDevelop engine features can be used in JavaScript (learn more about it in the JavaScript events page). It's easier to use events for this.
Both JavasScript and events can be used in the same extension:
- Events allow to easily use GDevelop engine features
- JavaScript should be only used for code independent from GDevelop
JavaScript and events should only communicate through actions, conditions and expressions. JavaScript code should avoid at all cost to use event variables directly because it will likely result to spaghetti code. Variables can still be passed as events function parameters in case the extension needs to exchange a structure or an array with the events.
These 2 extensions use a JavaScript library but also use some of GDevelop engine features with events:
- The 3D object shake extension uses a noise library and implements with events a behavior that makes 3D objects shake.
- The Curved movement extension evaluates Bézier curves using JavaScript and handles movement logics with events.
Learn by reading code from the community
Extensions can be implemented with events and JavaScript or a mix of both. Looking at existing extensions can help to understand the API and extension system.
This is a few instances of extensions that use JavaScript:
- The Noise generator extension uses a noise library and exposes its features through expressions, action and conditions.
- The 3D object shake extension uses the same noise library from the above extension but exposes a behavior that makes 3D objects shake.
- The Curved movement extension evaluates Bézier curves using JavaScript and handles movement logics with events.
- The Boids movement extension exposes a behavior to users and uses a R-Tree internally to quickly check neighbors.
- The Object stack extension exposes conditions that pick object instances according to their position in a stack.
- The Clipboard extension uses an asynchronous web API and implements fallbacks to Electron API or Cordova plugins.