読者です 読者をやめる 読者になる 読者になる

気ままなタンス*プログラミングなどのノートブック

プログラミングやRPGツクール、DTM、VOCALOIDについてのんびり書きます。

【ツクールMV】Scene_Baseをプロトタイプ継承したオブジェクトのエラーで悩んだ話

JavaScript ツクールMV

ツクールMV用にプラグインを実装していました。

プラグインの内容としてはアドベンチャーゲーム等によくある「回想モード」です。 ゲーム内で一度でも見たCGやゲームシーンを、後から再生する際に利用するアレです。

f:id:rinne_grid2_1:20151222072303p:plain

画面の構成から考えて、Scene_Baseをプロトタイプとするオブジェクトを 作成するのが望ましいと考え、Scene_Recollectionというものを作成しました。

Scene_Baseをプロトタイプ継承したScene_Recollection(動かない)

(function() {
    //=========================================================================
    // ■ Scene_Recollection
    //=========================================================================
    // 回想用のシーン関数です
    //=========================================================================
    function Scene_Recollection() {
        this.initialize.apply(this, arguments);
    };

    Scene_Recollection.prototype = Object.create(Scene_Base.prototype);
    Scene_Recollection.prototype.constructor = Scene_Recollection;
  
    Scene_Recollection.prototype.initialize = function() {
        Scene_Base.prototype.initialize.call(this);
    };

    Scene_Recollection.prototype.create = function() {
        Scene_Base.prototype.create.call(this);
        this.createCommandWindow();
      
    };

    Scene_Recollection.prototype.createCommandWindow = function() {
        this._rec_window = new Window_RecollectionCommand(0, 0);
        this._rec_window.setHandler('select_recollection', this.commandShowRecollection.bind(this));
        // select_cg, select_back_titleと関数のbindは省略
        this.addChild(this._rec_window);
    };

    Scene_Recollection.prototype.commandShowRecollection = function() {
        alert("回想モードを選びました");
    };



    //=========================================================================
    // ■ Window_RecollectionCommand
    //=========================================================================
    // 回想モードかCGモードを選択するウィンドウです
    //=========================================================================
    function Window_RecollectionCommand() {
        this.initialize.apply(this, arguments);
    }

    Window_RecollectionCommand.prototype = Object.create(Window_Command.prototype);
    Window_RecollectionCommand.prototype.constructor = Window_RecollectionCommand;

    Window_RecollectionCommand.prototype.initialize = function() {
        Window_Command.prototype.initialize.call(this, 0, 0);
    };

    Window_RecollectionCommand.prototype.makeCommandList = function() {
        Window_Command.prototype.makeCommandList.call(this);
        this.addCommand(settings.str_select_recollection, "select_recollection");
        this.addCommand(settings.str_select_cg, "select_cg");
        this.addCommand(settings.str_select_back_title, "select_back_title");
    };


})();

Cannot read property addChild of undefinedで落ちる

「addChildが定義されてなくてプロパティ読めないよ」ってエラーで落ちました。

なぜだろう?

Spriteの時は、Spriteオブジェクトを作成して、addChildすれば画面にすぐに表示できたのに・・・。

ということで、30分~1時間くらいモヤモヤしながら、対象のソースを熟読した後、 rpg_scene.jsの中身を読んでいたらようやく原因が判明しました。

WindowLayerが生成されていないから

  • rgs_scene.js:57行目付近
Scene_Base.prototype.createWindowLayer = function() {
    var width = Graphics.boxWidth;
    var height = Graphics.boxHeight;
    var x = (Graphics.width - width) / 2;
    var y = (Graphics.height - height) / 2;
    this._windowLayer = new WindowLayer();
    this._windowLayer.move(x, y, width, height);
    this.addChild(this._windowLayer);
};

Scene_Base.prototype.addWindow = function(window) {
    this._windowLayer.addChild(window);
};

addWindow関数はwindowLayerオブジェクトに対して、addChildしており、 windowLayerオブジェクトは、createWindowLayer関数内で生成されています。

つまり、Scene_Recollection.prototype.createの中で、createWindowLayerを呼ぶ必要がありました。

Scene_Baseをプロトタイプ継承したScene_Recollection

(function() {
    //=========================================================================
    // ■ Scene_Recollection
    //=========================================================================
    // 回想用のシーン関数です
    //=========================================================================
    function Scene_Recollection() {
        this.initialize.apply(this, arguments);
    };

    Scene_Recollection.prototype = Object.create(Scene_Base.prototype);
    Scene_Recollection.prototype.constructor = Scene_Recollection;
  
    Scene_Recollection.prototype.initialize = function() {
        Scene_Base.prototype.initialize.call(this);
    };

    Scene_Recollection.prototype.create = function() {
        Scene_Base.prototype.create.call(this);
        // 【!】これが必要
        this.createWindowLayer();
        this.createCommandWindow();
      
    };

    Scene_Recollection.prototype.createCommandWindow = function() {
        this._rec_window = new Window_RecollectionCommand(0, 0);
        this._rec_window.setHandler('select_recollection', this.commandShowRecollection.bind(this));
        // select_cg, select_back_titleと関数のbindは省略
        this.addChild(this._rec_window);
    };

    Scene_Recollection.prototype.commandShowRecollection = function() {
        alert("回想モードを選びました");
    };



    //=========================================================================
    // ■ Window_RecollectionCommand
    //=========================================================================
    // 回想モードかCGモードを選択するウィンドウです
    //=========================================================================
    function Window_RecollectionCommand() {
        this.initialize.apply(this, arguments);
    }

    Window_RecollectionCommand.prototype = Object.create(Window_Command.prototype);
    Window_RecollectionCommand.prototype.constructor = Window_RecollectionCommand;

    Window_RecollectionCommand.prototype.initialize = function() {
        Window_Command.prototype.initialize.call(this, 0, 0);
    };

    Window_RecollectionCommand.prototype.makeCommandList = function() {
        Window_Command.prototype.makeCommandList.call(this);
        this.addCommand(settings.str_select_recollection, "select_recollection");
        this.addCommand(settings.str_select_cg, "select_cg");
        this.addCommand(settings.str_select_back_title, "select_back_title");
    };


})();

無事に表示できました。

f:id:rinne_grid2_1:20151222073507p:plain

はまった理由

  • Spriteと同じような書き方で対応できると思ってました
    • 他のScene関数でcreateWindowLayerの記載があったにも関わらず、必要ないと判断してしまった

プラグインについて

今日(12/22)、もしくは明日中には完成させる予定です。