Construct for JavaScript developers quick start guide

14

Stats

1,459 visits, 1,986 views

Translations

This tutorial hasn't been translated.

Tools

License

This tutorial is licensed under CC BY 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

This tutorial is recommended by the Construct team! This means it contains useful, high quality information that will help grow you as a game developer.

Construct supports writing JavaScript code in both script files and event sheets. If you are new to the JavaScript programming language, consider taking the Learn JavaScript in Construct tutorial course. However if you already have some knowledge of JavaScript coding, this guide will help you quickly get up to speed with JavaScript in Construct.

Modules

All JavaScript code in Construct runs in modules. This is based on the JavaScript language provided module system, also known as JavaScript Modules, ES Modules or ESM. Construct does not currently directly support other module patterns like CommonJS or AMD.

Modules allow for using the import and export syntax, which is supported in Construct.

The main script

In Construct the main script is automatically loaded. This file appears bold in the Project Bar and has its Purpose property set to Main script. However other scripts are not automatically loaded by default - instead they must be imported in order to load and execute them.

Top-level scope

If you've not worked with JavaScript Modules before, note that top-level scope works differently in modules. Each module (script file) has its own top-level scope. This means top-level declarations are not globally accessible. Using imports and exports are preferable to global variables, but if you have to, use globalThis to access the global namespace, as demonstrated below.

// In a module, this is scoped only to the same file.
let myGlobal = 0;

// In a module, this is now global.
globalThis.myGlobal = 0;

Strict mode

Modules also run code in strict mode. This eliminates common problems such as silent errors, typos accidentally creating variables, and fixes some aspects of the language considered mistakes. This can be used outside of modules with the "use strict" directive, which is a best practice to help catch mistakes. However remember this directive is not necessary in modules as it always uses strict mode automatically.

Importing third-party scripts

Third-party scripts written in the modern ES Modules style should work normally in Construct. If you can, use a script based on ES Modules, or ask the third-party developer to provide one.

If you import an older third-party script that does not use ES Modules, it may try to add something to the global namespace by using a top-level declaration. Since modules have their own scope, this means the script won't actually declare anything usable in other script files. These scripts have to be lightly modified to get them to work as modules. An example is shown below.

// A third party script may try to declare a global
// function like this, which won't work in a module.
var SomeGlobal = function () { ... };

// Add an extra line to add it to global scope like this
// to make sure it really is accessible globally.
globalThis.SomeGlobal = SomeGlobal;

Often this is the only change necessary to get the script working again.

Similarly older scripts may try to use a variety of ways to identify the global object, relying on a mix of window, self or global. The modern way to access the global object is with globalThis. You may need to update the way the global object is referenced as shown in the example below.

// A third party script may use the following pattern to
// try to identify the global object and pass it to an IIFE.
(function (global) {

	// ... code using 'global' ...
	global.SomeGlobal = function () { ... };

})(window || self || global);	// <-- this code tries
		// to identify the global object

// The complicated code trying to identify the global object
// can be replaced with a simple reference to globalThis.
(function (global) {

	// ... code using 'global' ...
	global.SomeGlobal = function () { ... };

})(globalThis);	// easy way to get global object

To load a third-party script that does not use modules, use the following style of import statement. This loads and executes the script without using any exports.

import "./myscript.js";

Scripts in event sheets

When adding JavaScript code in an event sheet, it actually runs inside an async function. This allows use of await in such code snippets. The event system can then wait for a previous block of JavaScript code to finish using the Wait for previous actions to complete system action.

Note that since these code snippets are inside functions, the use of import and export is not allowed, as the JavaScript language does not permit these inside functions. Further, any variable or function declarations will only be available in that snippet. Global variables can still be accessed using globalThis.

Referring to script files in event sheets

Scripts in event sheets are a concept unique to Construct. Therefore the way modules are accessed in scripts in event sheets is slightly different to the way script files work.

Scripts in event sheets are all combined in to a single script file. If a script in the project has the purpose Imports for events, its content is inserted to the top of that combined script file. This provides a way to use modules in scripts in event sheets.

For example suppose the Imports for events script uses the following import:

import * from "./mymodule.js" as MyModule;

This then means all scripts in event sheets in the entire project can now refer to MyModule.

In fact the Imports for events script can declare variables and functions that can then be used in scripts in event sheets. However usually it is preferable to import a script, as that can also be shared with other script files.

The Imports for events script can also import the main script. This provides a convenient way to call functions exported from the main script from event sheets.

import * from "./main.js" as Main;

Construct APIs

Construct provides a range of APIs to access Construct-specific features. These are typically accessed via runtime, which refers to the runtime script interface.

In scripts in event sheets, runtime is automatically defined and so can be used directly.

In script files, runtime is passed to a callback in the special Construct-provided runOnStartup global function. The default code snippet in a newly added script file demonstrates using that. From there on, it is up to your own code to pass runtime to code that needs to use it.

Construct objects are typically accessed via runtime.objects, e.g. runtime.objects.Sprite is an IObjectClass representing the Sprite object. Note this does not represent an instance, and so does not have properties specific to instances such as x or y representing a position. Instead you must retrieve an instance from the IObjectClass.

For example if there is only one instance of Sprite, then it can be retrieved using getFirstInstance() like so:

const inst = runtime.objects.Sprite.getFirstInstance();
// now can use inst.x, inst.y etc.

If there are multiple instances they can be iterated with methods such as instances() like so:

for (const inst of runtime.objects.Sprite.instances())
{
	// now can use inst.x, inst.y etc.
}

The specific APIs for instances depends on the plugin type. These interfaces are all documented in the scripting reference section of the manual, such as ISpriteInstance for Sprite instances, which provides APIs for things like animations. Note that these interfaces also inherit from IWorldInstance and IInstance (depending on the kind of plugin). For example common properties like x and y are part of IWorldInstance.

Integrating scripts and events

Strings and numbers can be exchanged between event sheets and JavaScript code using global and local variables in event sheets. Local variables are accessible via localVars inside scripts in event sheets, and global variables are accessible via runtime.globalVars. There is more information in the manual section on Scripts in event sheets.

Strings and numbers can also be exchanged via instance variables via the instVars property of IInstance.

See also the example project Integrating events with script for an example of some useful techniques.

Learn more

Here are some more resources to learn more about using JavaScript in Construct.

Examples

There are lots of example projects using JavaScript coding in Construct which you can find in the Scripting category in the Example Browser.

Debugging

You can still use the browser developer tools to debug JavaScript code that you write in Construct. For a quick-start guide on debugging, see the manual section on Debugging script.

Minifying

Minifying on export also applies to your JavaScript code written in Construct. Code minification is done with Google's Closure Compiler, an industry-standard tool. Simple minify mode should never affect how your code runs. However if you enable Advanced minify mode on export, you may need to adjust how you write your code. See the manual guide on Exporting with Advanced minification for more details.

Worker mode

Construct is capable of running its entire engine in a Web Worker, rendering via OffscreenCanvas. However by default projects using JavaScript code run in the main page ("DOM mode") to ensure compatibility with code that expects to be able to use DOM features like document. If your JavaScript code is compatible with running in a Web Worker, you can re-enable worker mode for improved performance by changing the project property Use worker to Yes (in the Advanced section). There is more information about this in the manual section JavaScript in Construct.

Reference

See the Scripting section of the manual for full documentation on using JavaScript in Construct.

  • 8 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • Nice, this helps alot!

  • Do you think it'll be possible to import "resemble.js"

  • does improved performance running Web Worker apply at all the NWjs?

      • [-] [+]
      • 1
      • Ashley's avatar
      • Ashley
      • Construct Team Founder
      • 1 points
      • (4 children)

      The performance benefits of worker mode are covered in this blog post. It applies to all platforms that support worker mode.

      • Hi, I've read that post before and I just reread it, just in case I missed something. But not once does it mention NWjs and I still don't understand if it applies to NWjs! NWjs as I understand it is its own browser with nothing else running but your game. If "under the hood" Windows sees NWjs as just another Chrome process and groups it with other Chrome processes running, then I could see it being a major benefit. But if NWjs is only "based on chrome" but not actually chrome how would worker help? Sorry if that blog post spells it out and I am just not getting it, but I honestly don't understand.

          • [-] [+]
          • 1
          • Ashley's avatar
          • Ashley
          • Construct Team Founder
          • 1 points
          • (2 children)

          NW.js is for all intents and purposes the same as Chrome. It is separate to the Chrome browser so there aren't other web pages that might jank the page. But there are other benefits that still apply to NW.js, such as allowing main thread work to happen in parallel.

          • I see, so some tasks that can only be done on the main thread can be done in parallel with worker. It's not a burning question but the only follow-up I would have are what exactly are those tasks and do they apply to me specifically? I don't do anything with SVGs, preview and debugger are N/A. The reason I am asking all this is I am looking into doing some scripting for Greenworks.js specifically (allowing player to use Steam Workshop) that I think will disqualify me from using Worker. So I want to know exactly what I am giving up. Maybe its a non-issue to not run Worker for a game in NWjs that doesn't use "specific" things that would benefit from running in parallel?