Modularize Script
Cocos Creator allows you to split the code into multiple script files and they can be called by each other. To implement this, you need to know how to define and use the module in Cocos Creator. This step is called modularize for short.
If you are not sure what modularization can do, you can consider it as:
import
in Java and Pythonusing
in C#include
in C/C++<link>
in HTML
Modularization enables you to reference other script files in Cocos Creator:
- Access parameters exported from other files
- Call method other files that have been exported
- Use type other files that have been exported
- Use or inherit other Components
JavaScript in Cocos Creator uses the same Common JS standard as Node.js to implement modularization, in short:
- Each individual script file forms a module
- Each module is an individual action scope
- Reference other modules in the synchronized
require
method - Set
module.exports
as an exported variable
If you still don't quite understand, don't worry, we will explain it in here.
In this article, the two terms "module" and "script" are equivalent. All the "comment" parts belong to advanced contents that don't need to be understood at the very start. No matter how we define the module, all user designation codes will eventually be compiled into native JavaScript by Creator and can be run directly in the browser.
Reference module
require
Other than the interface provided by Creator, all the user-defined modules will need to call require
to be accessed. For instance, we have a component defined at Rotate.js
:
// Rotate.js
cc.Class({
extends: cc.Component,
// ...
});
Now if you want to access it in another script, you can:
var Rotate = require("Rotate");
What require
returned is the object exported by the module. Normally, we would save the result to a variable (var Rotate
) immediately. The incoming require
character string is the module's file name, the name contains neither path nor suffix and it is case sensitive.
require complete example
Next, we can use Rotate to derive a subclass and create a new script SinRotate.js
:
// SinRotate.js
var Rotate = require("Rotate");
var SinRotate = cc.Class({
extends: Rotate,
update: function (dt) {
this.rotation += this.speed * Math.sin(dt);
}
});
Here, we define a new component named SinRotate, which is inherited from Rotate, and rewrite the update
method.
This component can also be accessed by other scripts as long as you use
require("SinRotate")
.
Comments:
require
could be called at any place in the script at any time.- All of the script will be automatically required when the game is started. At this time, the defined code in each module will be executed once, no matter how many times it is required, the same instance will be returned.
- When debugging, any module in the project can be required in the Console of Developer Tools.
Define module
Define component
Each individual script file is a module, such as the new script Rotate.js
mentioned above:
// Rotate.js
var Rotate = cc.Class({
extends: cc.Component,
properties: {
speed: 1
},
update: function () {
this.transform.rotation += this.speed;
}
});
When you declare a component in the script, Creator will acquiesce to export it so other scripts can use it by requiring this module.
Define regular JavaScript module
You can not only define a component in the module, but you can also export any JavaScript object. Let's imagine that there is a script config.js
// config.js
var cfg = {
moveSpeed: 10,
version: "0.15",
showTutorial: true,
load: function () {
// ...
}
};
cfg.load();
Now, if we want to access the cfg
object in another script:
// player.js
var config = require("config");
cc.log("speed is", config.moveSpeed);
The result will report an error: "TypeError: Cannot read property 'moveSpeed' of null", this is because cfg
has not been set as the export object. We also need to set module.exports
as config
at the end of config.js
:
// config.js - v2
var cfg = {
moveSpeed: 10,
version: "0.15",
showTutorial: true,
load: function () {
// ...
}
};
cfg.load();
module.exports = cfg;
The reason for doing this is because as long as there is another script that requires it, what they actually get will be the module.exports
object in here.
In this way, it can output correctly: "speed is 10".
The default value of
module.exports
: If a script does not declaremodule.exports
, Creator will setexports
as the Component declared in script automatically. And if a script does not declare any Component but declares other types of CCClass, it will setexports
as declared CCClass automatically.
Comments: The other variables added to module
can not be exported, that is to say exports
can not be replaced with other variable names, the system will only read the exports
variable.
More examples
Export variable
module.exports
is a empty object ({}
) and can be added in a new field directly.// foobar.js: module.exports.foo = function () { cc.log("foo"); }; module.exports.bar = function () { cc.log("bar"); };
// test.js: var foobar = require("foobar"); foobar.foo(); // "foo" foobar.bar(); // "bar"
module.exports
value can be any JavaScript type.// foobar.js: module.exports = { FOO: function () { this.type = "foo"; }, bar: "bar" };
// test.js: var foobar = require("foobar"); var foo = new foobar.FOO(); cc.log(foo.type); // "foo" cc.log(foobar.bar); // "bar"
Packaging a private variable
Each script is a single scope where the local variable defined using var
in the script cannot be accessed by external modules. We can package the private variable in the module easily:
// foobar.js:
var dirty = false;
module.exports = {
setDirty: function () {
dirty = true;
},
isDirty: function () {
return dirty;
},
};
// test1.js:
var foo = require("foobar");
cc.log(typeof foo.dirty); // "undefined"
foo.setDirty();
// test2.js:
var foo = require("foobar");
cc.log(foo.isDirty()); // true
Circular reference
Please refer to Property delay definition