【プラグイン講座】ウィンドウを表示させる

本日はシーンにウィンドウを表示させてみましょう。
前回分がまだの方は前回分も参照してください。
ウィンドウとは、タイトル画面を表示させたときに出る「コンティニュー」とかが書いてあるボックスや、会話をさせるときに表示されるメッセージボックスとかのことですね。

ウィンドウを作る機能がツクールには備わっている

ウィンドウを作るのは非常に簡単です。
というのも、ツクールにはもともとウィンドウを表示させるクラスが備わっているからです。
これを流用すれば簡単にウィンドウが作れるのですね。
しかもありがたいことに、選択肢用のウィンドウまで用意されています。
一から作る必要ナッシングです。
今回は選択肢用のウィンドウではなく、ふつーのウィンドウを表示させてみます。

ウィンドウの機能を担っているクラス

では具体的な話に入っていきましょう。
ツクールのウィンドウは全てWindow_Baseクラスに属しています(実はこのWindow_BaseクラスはさらにWindowクラスに属しているのですが、よほど凝ったプラグインを作らない限り、そこまで意識する必要はないと思います)。
Window_Baseのような大本の機能を担うクラスをスーパークラスと呼びます(実はScene_Baseもスーパークラスです)。

このWindow_Baseがどこに書かれているかと言えば、rpg_windows.jsファイルの中ですね。
最初の方のコメントに
The superclass of all windows within the game.
と書かれていますね(日本のソフトやのになんで英語やねんと思いますが)。

スーパークラスを直接いじることはしない

ここで少し話はそれるのですが、ツクールには他にも様々なスーパークラスがあります。
コメントで「これはスーパークラスですよ~」と書かれてあるので、コードを読んでいけばわかると思います。
で、このスーパークラスを直接いじってしまうと、ゲーム全体に影響が及んでしまいます
なので原則としてスーパークラスは変更せず、prototypeで継承したしたものをいじるのがよいですね。

注*ゲーム全体に影響を与えたいならスーパークラスをいじってください。

と言うか、スーパークラスでなくとも、コアスクリプトに書かれているクラスは基本的にいじらないほうがいいです(特にコアスクリプトを直接編集するのはご法度です)。
https://forum.tkool.jp/index.php?threads/%E3%82%B3%E3%82%A2%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E8%A7%A3%E8%AA%AD%E3%81%A7%E5%88%86%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E9%83%A8%E5%88%86%E3%82%92%E8%A9%B1%E3%81%97%E5%90%88%E3%81%84%E3%81%BE%E3%81%97%E3%82%87%E3%81%86.91/
コアスクリプトとはなんぞというのはこのスレッドを読むのがよいですね。
プラグイン制作に慣れてきて、コアスクリプトの内容を改変したい(こういったことは実はしばしばあります)場合、コアスクリプトを直接編集するのではなく、自作したプラグインの中でコアスクリプトの内容を変更しましょう(プラグインをON/OFFするだけでコアスクリプトへの影響がなくなるため)。

新しいウィンドウを実際に作ってみる

前置きが長くなりましたが、ここから実際にウィンドウを作っていきます。
まずはWindow_Baseを継承したWindow_Sampleクラスを作ります。

//—————————————————————————–
// Window_Sampleクラスの定義
//—————————————————————————–
function Window_Sample() {
this.initialize.apply(this, arguments);
}

Window_Sample.prototype = Object.create(Window_Base.prototype);
Window_Sample.prototype.constructor = Window_Sample;

はいこれだけです。
Scene_Sampleクラスを作った時とほぼ同じなので簡単ですね。

着目すべきは
Window_Base.prototype
のところで、この部分をいじれば選択肢用のWindowを作ったりもできます。

例のごとく、これだけでは画面にWindowは表示されません。
シーンにaddChildする必要があります。

Scene_SampleクラスのdrawTriangleメソッドの下に以下のコードを追加してください。

Scene_Sample.prototype.createSampleWindow = function() {
this.sampleWindow = new Window_Sample(0,300,Graphics.width,200);
this.addWindow(this.sampleWindow);
};

まず一行目の
this.sampleWindow = new Window_Sample(0,300,Graphics.width,200);
を見てください。
sampleWindowという名前の入れ物に、先ほど作ったWindow_Sampleクラスを代入しています。
引数の意味は(x座標,y座標,幅,高さ)です。
この座標・幅・高さは作成したあとでも変更できます。
ヘルプのWindow Classを見てください(Window_Baseのスーパークラスです)。
が、とりあえずはサイズなどはこのまま行きましょう。

次の
this.addWindow(this.sampleWindow);
を見てください。

addChildではなくaddWindowですが、意味合い的には似たようなものです。
一応中身も見ておきましょう。
addWindowはScene_Baseクラスに属するメソッドで、こんな感じのコードが記されています。

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

はい、つまり今までのaddChildがシーンに対して直接addChildしていたのに対して、addWindowは_windowLayerに対してaddChildしているのですね。
「小難しいことはどうでもいいんじゃ! シーンにウィンドウが表示できればいいんじゃ!」ということでしたら、「ウィンドウをシーンに貼り付けるときはaddWindow」と覚えておけばよいと思います。

さて準備が整いました。
あとはScene_Sample.prototype.createメソッドの中身をこんな風に変えます。

Scene_Sample.prototype.create = function() {
Scene_Base.prototype.create.call(this);
//createSprite実行
this.createSprite();
//createFigureSprite実行
this.createFigureSprite();

//Window用のレイヤーを作成
//this.createWindowLayer();
//実際のウィンドウを貼り付け
this.createSampleWindow();
};

ゲームを実行して、シーンを表示させてみてください。
見事エラー(TypeError: Cannot read property ‘addChild’ of undefined)が出ましたね。

それもそのはずで、実はScene_Base.prototypeにはWindowを表示するための機能(メソッド)はあっても、Scene_Baseのcreateメソッドが呼び出される段階ではそのメソッドは実行されません
つまり、実際にウィンドウを表示するにはその機能(メソッド)をこちらで実行しておかなければならないのです。

それが上記のコードの
//this.createWindowLayer();
の部分です。
この「//」を削除してください(これをコメントアウトと言います。逆に「//」をつけるのをコメントインと呼びます)。
this.createWindowLayer();
をあらかじめ実行しておくことによって、addWindowが正常に機能してくれるのですね。

注*正確な内容が知りたい方は、rpg_scene.jsのcreateWindowLayerメソッドを見てください。ここでWindowLayerクラスのインスタンスthis._windowLayerを作成しています。

改めてゲームを実行してみてください。
ウィンドウが表示されましたか?

上図のように表示されたら成功です。

ウィンドウに文字を表示してみる

空のウィンドウを表示するだけではなんですので、文字を表示してみましょう。
Windows_Sampleクラスにある
Window_Sample.prototype.constructor = Window_Sample;
というコードの下に以下のメソッドを追加してください。

Window_Sample.prototype.drawJobHuntingMessage = function(text) {
this.drawTextEx(‘お仕事ください!\n’ + text + ‘\nお仕事ください!’,10,10);
}
;

drawJobHuntingMessageメソッドの中にあるdrawTextExメソッドは、Window_Baseクラスにもともと付属しているものです。
要はウィンドウに文字を描くメソッドですね。
制御文字も使用できます。
もう少し凝った囲み文字などを表示したい場合(僕のステータス画面拡張プラグインで表示しているような文字のこと)、drawTextExメソッドを改造したり、オリジナルのテキスト描写用のメソッドを作成する必要があります。
が、ここではそこまで深くは触れません。

drawJobHuntingMessageの追加できたら、今度はScene_SampleクラスのcreateSampleWindowに以下のコードを追加しましょう。

//中身を描く
this.sampleWindow.drawJobHuntingMessage(‘僕はニートです。’);

先ほど作ったdrawJobHuntingMessageを実行しているのですね。
ゲームを起動して、Scene_Sampleシーンに飛んでみてください。

どうでしょうか?
ウィンドウの中に文字が表示されましたか?
表示されていたら完成です。
お疲れ様でした。

参考情報

「俺様は顔グラを表示させたいんじゃい!」という方もいるかと思います。
ですがツクールMVのグラフィック描写に関する仕様は僕もいまいち理解していないので、ここでは解説を省略しました。
その不明な部分を僕なりに言語化してみます。

まず、グラフィックをWindowに貼り付けるには、「そのシーンが始まるよりも前に」ロードされている画像でないと表示されないらしいのです。
試しにdrawJobHuntingMessageの中にthis.drawFace(‘Actor1’, 0, 0, 0, 100, 100);などと書いて顔グラを表示させようとしてみてください。
顔グラを一度もロードしていない状態だと、この顔グラは表示されません(つまりメニュー画面などを開いたあとにScene_Sampleにアクセスすると表示されるが、そうでない場合は表示されない)。
今のところ僕は、このよくわからない現象を解決するのに

1.シーンの中で無理やり何回も画像をロードさせ、画面も複数回書き換えて画像を表示させる
2.Scene_Bootの時点で画像を読み込ませる

の二つの方法を併用しています。

ただしスプライトで直接画像を表示させる場合、別にロード等はさせなくてもいいようです。
Windowに画像を表示させたい場合だけ、この問題が起こるのですね(理由は知りません)。
詳しくはプロツクラーの方々の情報を待たれよ!

フォローする