Advanced Scripting

By starting this Advanced Scripting section it is assumed one is already familiar with the scripting system, including decorators and so on. Otherwise, please refer to the following documents to get up to speed first:

Instantiation

Define a Foo class and a Bar class through a script. The Foo class needs to use the properties defined by the Bar class, to allow directly issuing new the Bar class to an object in the Foo class:

  1. class Foo {
  2. public bar: Bar = null;;
  3. constructor() {
  4. this.bar = new Bar();
  5. }
  6. }
  7. let bar = new Foo();

Instance Methods

Instance methods should be declared in the prototype object:

  1. class Foo {
  2. public text!: string;
  3. constructor() {
  4. this.text = "this is sprite"
  5. }
  6. // Declare an instance method named "print"
  7. print() {
  8. console.log(this.text);
  9. }
  10. }
  11. let obj = new Foo();
  12. // Call the instance method
  13. obj.print();

Type Determination

When making a type determination, use TypeScript’s native instanceof.

  1. class Sub extends Base {
  2. }
  3. let sub = new Sub();
  4. console.log(sub instanceof Sub); //true
  5. console.log(sub instanceof Base); //true
  6. let base = new Base();
  7. console.log(base instanceof Sub); // false

Static Variables and Static Methods

Static variables or static methods can be declared with static:

  1. class Foo {
  2. static count = 0;
  3. static getBounds() {
  4. }
  5. }

Static members are inherited by subclasses, and Creator gives a shallow copy of the parent’s static variables to the subclass when inherited, so that:

  1. class Object {
  2. static count = 11;
  3. static range: { w: 100, h: 100 }
  4. }
  5. class Foo extends Object {
  6. }
  7. console.log(Foo.count); // The result is 11, because `count` inherits from the `Object` class
  8. Foo.range.w = 200;
  9. console.log(Object.range.w); // The result is 200 because 'Foo.range' and 'Object.range' refer to the same object

Private static members can also be defined directly outside of the class if inheritance is not a concern:

  1. // Local methods
  2. doLoad(sprite) {
  3. // ...
  4. };
  5. // Local variables
  6. let url = "foo.png";
  7. class Sprite {
  8. public url = '';
  9. load() {
  10. this.url = url;
  11. doLoad(this);
  12. };
  13. };

Inheritance

Parent constructor

Note: the constructor of the parent class is automatically called before the subclass is instantiated, regardless of whether the subclass has a defined constructor or not.

  1. class Node {
  2. name: string;
  3. constructor() {
  4. this.name = "node";
  5. }
  6. }
  7. class Sprite extends Node {
  8. constructor() {
  9. super();
  10. // The parent constructor has already been called before the child constructor is called, so `this.name` has already been initialized
  11. console.log(this.name); // "node"
  12. // Reset `this.name`
  13. this.name = "sprite";
  14. }
  15. }
  16. let obj = new Sprite();
  17. console.log(obj.name); // "sprite"

Rewrite

All member methods are dummy methods, and subclass methods can override parent methods directly:

  1. class Shape {
  2. getName() {
  3. return "shape";
  4. }
  5. };
  6. class Rect extends Shape {
  7. getName () {
  8. return "rect";
  9. }
  10. };
  11. let obj = new Rect();
  12. console.log(obj.getName()); // "rect"

get/set Methods

If get/set is defined in a property, then the predefined get/set methods can be triggered when the property is accessed.

get

Define the get method in the property:

  1. @property
  2. get num() {
  3. return this._num;
  4. }
  5. @property
  6. private _num = 0;

The get method can return a value of any type.
Properties that have a get method defined can be displayed in the Inspector panel and can be accessed directly in the code.

  1. class Sprite {
  2. @property
  3. get width() {
  4. return this._width;
  5. }
  6. @property
  7. private _width = 0;
  8. print(){
  9. console.log(this.width);
  10. }
  11. };

Notes:

  • Properties cannot be serialized after the get method is defined, i.e. the serializable parameter is not available.

    For example, the width property will neither be displayed in the editor nor serialized as shown below:

    1. get width() {
    2. return this._width;
    3. }
    4. @property({ type: CCInteger, tooltip: "The width of sprite" })
    5. private _width = 0;
  • Properties that have a get method defined need to have property defined if they need to be displayed by the editor, otherwise they won’t be rendered.

    For example, the width property will not be rendered on the editor if the @property is removed, and the _width property will be serialized:

    1. @property
    2. get width() {
    3. return this._width;
    4. }
    5. @property({ type: CCInteger, tooltip: "The width of sprite" })
    6. private _width = 0;
  • The property itself that defines the get method is read-only, but the returned object is not read-only. The developer can still modify the properties inside the object through code, for example:

    1. get num() {
    2. return this._num;
    3. }
    4. @property
    5. private _num = 0;
    6. start() {
    7. console.log(this.num);
    8. }

set

Define the set method in the property:

  1. set width(value) {
  2. this._width = value
  3. }
  4. private _width = 0;
  5. start() {
  6. this.width = 20;
  7. console.log(this.width);
  8. }

The set method takes an incoming parameter, which can be of any type. The set method is generally used in conjunction with the get method:

  1. @property
  2. get width() {
  3. return this._width;
  4. }
  5. set width(value) {
  6. this._width = value;
  7. }
  8. @property
  9. private _width = 0;

Note: the set method does not define properties.