ctor() {
    // initialize properties that may be required in init

    // events
    this._eventBus = EventBus.create();
    this._waitingForStatus = {};

    // step/action queue
    this._actionInterfacesByIndex = {};
    this._stepInterfacesByIndex = {};
    this._stepQueue = [];
    this._skippableActionsByIndex = {};

    // nodes
    this._entityNodes = [];
    this._unitNodes = [];
    this._tileNodes = [];
    this._speechNodes = {};
    this._burnCardNode = CardNode.create();
    this._inspectCardNode = CardNode.create();
    this._referencedCardNode = CardNode.create(),
    this._playCardNode = CardNode.create();
    this._particleContainer = [];

    // ui
    this._lastMouseOverEntityNodesForAction = [];
    this._lastPlayedCardBoardPositions = [];
    this._customUIModules = [];
    this._notificationYourTurnSprite = new BaseSprite(RSX.notification_your_turn.img);
    this._notificationYourTurnSprite.setVisible(false);
    var label = new cc.LabelTTF(i18next.t('game_ui.label_your_turn'), RSX.font_bold.name, 66, cc.size(1280, 280), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
    label.enableStroke(cc.color(0, 0, 0, 0), 2);
    label.enableShadow(3, 0.5, 0.0);
    this._notificationYourTurnSprite.addChild(label, 1);
    label.setAnchorPoint(cc.p(0.0, -0.05));
    this._notificationEnemyTurnSprite = new BaseSprite(RSX.notification_enemy_turn.img);
    this._notificationEnemyTurnSprite.setVisible(false);
    var label = new cc.LabelTTF(i18next.t('game_ui.label_enemy_turn'), RSX.font_bold.name, 66, cc.size(1280, 280), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
    label.enableStroke(cc.color(0, 0, 0, 0), 2);
    label.enableShadow(3, 0.5, 0.0);
    this._notificationEnemyTurnSprite.addChild(label, 1);
    label.setAnchorPoint(cc.p(0.0, -0.05));
    this._notificationGoSprite = new BaseSprite(RSX.notification_go.img);
    this._notificationGoSprite.setVisible(false);
    var label = new cc.LabelTTF(i18next.t('game_ui.label_automatic_moves'), RSX.font_bold.name, 66, cc.size(1280, 280), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
    label.enableStroke(cc.color(0, 0, 0, 0), 2);
    label.enableShadow(3, 0.5, 0.0);
    this._notificationGoSprite.addChild(label, 1);
    label.setAnchorPoint(cc.p(0.0, -0.05));
    this._playerSelectionLockedRequests = [];

    // players
    this._player = Player.create();
    this._opponent = Player.create();
    this._altPlayer = Player.create();

    // layers
    this._battleLog = BattleLog.create();
    this._battleLog.setVisible(false);
    this._battleMap = BattleMap.create(this);
    this.backgroundLayer = BaseLayer.create();
    this.tileLayer = TileLayer.create();
    this.middlegroundLayer = ShadowCastingLayer.create();
    this.foregroundLayer = BaseLayer.create();
    this.bottomDeckLayer = BottomDeckLayer.create();
    this.player1Layer = Player1Layer.create(SDK.GameSession.getInstance().getPlayer1Id());
    this.player2Layer = Player2Layer.create(SDK.GameSession.getInstance().getPlayer2Id());
    this.uiLayer = BaseLayer.create();

    // add ui elements to ui layer
    this.uiLayer.addChild(this._battleLog, this._ui_z_order_battle_log);
    this.uiLayer.addChild(this._notificationYourTurnSprite, this._ui_z_order_notification_nodes);
    this.uiLayer.addChild(this._notificationEnemyTurnSprite, this._ui_z_order_notification_nodes);
    this.uiLayer.addChild(this._notificationGoSprite, this._ui_z_order_notification_nodes);
    this.uiLayer.addChild(this._referencedCardNode, this._ui_z_order_card_nodes);
    this.uiLayer.addChild(this._inspectCardNode, this._ui_z_order_card_nodes);
    this.uiLayer.addChild(this._playCardNode, this._ui_z_order_card_nodes);
    this.uiLayer.addChild(this._burnCardNode, this._ui_z_order_card_nodes);

    // bind initial players
    this.bindSdkPlayers();

    // do super ctor
    this._super();

    // add layers
    this.getFXLayer().addChild(this.backgroundLayer, 0);
    this.getFXLayer().addChild(this.tileLayer, 1);
    this.getFXLayer().addChild(this.middlegroundLayer, 2);
    this.getFXLayer().addChild(this.foregroundLayer, 3);
    this.getNoFXLayer().addChild(this.bottomDeckLayer, 0);
    this.getNoFXLayer().addChild(this.player1Layer, 0);
    this.getNoFXLayer().addChild(this.player2Layer, 0);
    this.getNoFXLayer().addChild(this.uiLayer, 1);
  }
GameLayer - controller for all visuals in a game.