RPGツクールMV用にプラグインを実装していました。
プラグインの内容としてはアドベンチャーゲーム等によくある「回想モード」です。 ゲーム内で一度でも見たCGやゲームシーンを、後から再生する際に利用する機能です。
画面の構成から考えて、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すれば画面にすぐに表示できたのに・・・。
ということで、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"); }; })();
無事に表示できました。
はまった理由
- Spriteと同じような書き方で対応できると思ってました
- 他のScene関数でcreateWindowLayerの記載があったにも関わらず、必要ないと判断してしまいました
プラグインについて
今日(12/22)、もしくは明日中には完成させる予定です。