独自ウィンドウを作成するためのプラグインを作る方法を紹介する。シーンクラスの知識を持っていることが前提なので、まだシーンクラスが知識が無い場合は以下を一読してほしい。
シーン(Scene)の構造と使い方 【RPGツクールMZプラグイン開発】
RPGツクールMV / MZのウィンドウは主に3種類のウィンドウがある。1つは単純に表示するだけのウィンドウ、1つはコマンドを列挙するウィンドウ、1つは好きなレイアウト、及びデザインでコマンドを列挙するウィンドウだ。この3種それぞれのテンプレートを紹介、解説していく。
単一の独自ウィンドウ
まずは一番基本的なウィンドウだ。ステータス画面、ゴールド表示ウィンドウなどが該当する。Window_Base、及びWindow_Selectableを継承してウィンドウを作る。ウィンドウを消すなどユーザーがこのウィンドウを操作する場合はWindow_Selectable、他のウィンドウからこのウィンドウを表示させたり削除するなど、ユーザーがこのウィンドウを操作しない場合はWindow_Baseを継承する。以下よりウィンドウを作りHello Worldと表示する簡単なテンプレートを作る。
/*:
* @plugindesc サンプルPlugin
* @target MZ
* @help
* 独自ウィンドウを表示するサンプル
*
* @command openScene
* @text シーン開始
* @desc サンプルシーンの開始。
*
*/
(() => {
const pluginName = document.currentScript.src.match(/^.*\/(.*).js$/)[1];
// Plugin Command
PluginManager.registerCommand(pluginName, "openScene", () => {
SceneManager.push(Scene_SampleMenu);
});
//サンプルウィンドウを管理するシーン
class Scene_SampleMenu extends Scene_MenuBase {
create() {
super.create();
//ウィンドウレイヤーを作成
this.createWindowLayer();
//サイズの決定。x座業,y座標,幅,高さ、
const rect = new Rectangle(200, 100, 400, 200);
//ウィンドゥの作成
this._sampleWindow = new Window_Sample(rect);
//このウィンドウにフォーカスを当てる。
this._sampleWindow.activate();
//決定・キャンセルでウィンドウを閉じる。
this._sampleWindow.setHandler("ok", this.popScene.bind(this));
this._sampleWindow.setHandler("cancel", this.popScene.bind(this));
//上記設定でウィンドウを作成
this.addWindow(this._sampleWindow);
}
}
//サンプルウィンドウクラス
class Window_Sample extends Window_Selectable {
initialize(rect) {
super.initialize(rect);
this.refresh('Hello', ' World')
}
refresh(string1, string2) {
//前の文字をクリア
this.contents.clear();
//文字出力
this.drawText(string1, 10, 50 + this.lineHeight() * 0, 200);
this.drawText(string2, 10, 50 + this.lineHeight() * 1, 200);
}
}
})();
まず、Windowを作るクラスWindow_Sample、シーンクラスScene_SampleMenuの順に見る。
継承元:Windw_Selectable
今回のサンプルの継承元はWindw_Selectable。簡単な表示のみのウィンドウの場合、継承元はWindw_Selectable以降かWindow_Base以降のどちらかとなる。違いはユーザーが操作するかどうか。本当に閲覧のみでユーザーが操作するのが他のウィンドウのみの場合はWindow_Baseからの継承でよい。今回はユーザーが決定やキャンセルで画面を消すという処理が入るためWindw_Selectableを継承元とした。
initialize
継承元にRectangleクラスを引き渡すとウィンドウの位置・幅・高さを設定してくれる。この段階で出力したい文字や画像、図形などを記述する。今回、refreshメソッドを用意した理由は、最初にHello Worldと表示しつつ、何かのタイミングでrefreshメソッドを呼ぶと新たな文字が上書きされる仕様を考えたからだ。
drawText(文字列、x座標位置、y座標位置、幅)
ウィンドウ内に文字を出力するメソッド。
lineHeight()
ツクールデフォルトフォントに合わせた行間を取得できる。このメソッドを利用するとツクールの各種UI画面と同程度の間隔で行移動ができる。デフォルトは36px。独自のフォントやフォントサイズの場合は適宜修正するとよい。
継承元:Scene_MenuBase
独自ウィンドウを作る場合はScene_Menubase以降が継承元となる。
createWindowLayer()
ウィンドウを作るための部品作成メソッド。おまじないみたいなメソッドなのでウィンドウを作る場合ははじめに宣言するメソッドと覚えておけばよい。
const rect = new Rectangle(x座標, y座標, 幅, 高さ)
pixiの四角形を定義するクラス。画面の左上を原点としてウィンドウの左上の位置をx,y座標で入力、及びウィンドウのx幅、y高さを入力。
this._sampleWindow = new Window_Sample(rect)
先ほどの四角形定義を代入しつつ、独自ウィンドウのクラスをインスタンス化。
activate() deactivate()
ウィンドウのアクティブ・非アクティブを切り替えるメソッド。アクティブとはユーザーが操作できるかどうかを指す。複数ウィンドウが立ち上がっている時、基本的には1つのみアクティブ化し、残りは全て非アクティブにする必要がある。そうしなければ、ユーザーの操作で複数のウィンドウが反応して予期せぬ動作挙動を示す。今回はこのウィンドウのみなのでアクティブ化した。
setHandler
特定挙動の処理を定義するハンドラー。ok、cancelはそれぞれ決定ボタンを押した時、キャンセルボタンを押した時の挙動。Windw_Selectableでこのok,cancelのハンドラーが定義されているため、今回のサンプルはWindw_Selectableを継承元としている。
addWindow
今まで_sampleWindowで設定した内容を実際に反映する。
独自コマンドウィンドウ
次は独自のコマンドを表示するウィンドウだ。タイトル画面、オプション画面、メニュー画面のスキル、アイテムなどを選択するウィンドウ、装備画面の装備、最強装備、全て外すコマンドウィンドウなどが該当する。縦のコマンド一覧はWindow_Commandを継承し、横のコマンド一覧はWindow_HorzCommandを利用する。以下は縦のコマンドウィンドウを表示するサンプルだ。
/*:
* @plugindesc サンプルPlugin
* @target MZ
* @help
* 独自コマンドウィンドウを表示するサンプル
*
* @command openScene
* @text シーン開始
* @desc サンプルシーンの開始。
*
*/
(() => {
const pluginName = document.currentScript.src.match(/^.*\/(.*).js$/)[1];
// Plugin Command
PluginManager.registerCommand(pluginName, "openScene", () => {
SceneManager.push(Scene_SampleMenu);
});
//サンプルウィンドウを管理するシーン
class Scene_SampleMenu extends Scene_MenuBase {
create() {
super.create();
//ウィンドウレイヤーを作成
this.createWindowLayer();
//サイズの決定。x座業,y座標,幅,高さ、
const rect = new Rectangle(200, 100, 400, 200);
//ウィンドゥの作成
this._sampleWindow = new Window_CommandSample(rect);
//このウィンドウにフォーカスを当てる。
this._sampleWindow.activate();
//決定・キャンセルでウィンドウを閉じる。
this._sampleWindow.setHandler("ok", this.popScene.bind(this));
this._sampleWindow.setHandler("cancel", this.popScene.bind(this));
this._sampleWindow.setHandler("displayString", this.DisplayString.bind(this));
this._sampleWindow.setHandler("back", this.popScene.bind(this));
//上記設定でウィンドウを作成
this.addWindow(this._sampleWindow);
}
DisplayString() {
//「サンプル」と書かれた文字を表示
this._text = new Sprite(new Bitmap(Graphics.width, Graphics.height));
this._text.bitmap.drawText("Sample", 0, 0, Graphics.width, Graphics.height, "center");
this._text.x = (Graphics.width - this._text.bitmap.width) / 2;
this._text.y = (Graphics.height - this._text.bitmap.height) / 2;
this.addChild(this._text);
//非アクティブになるので再度アクティブ化
this._sampleWindow.activate();
}
}
//サンプルウィンドウ(コマンド型)
class Window_CommandSample extends Window_Command {
makeCommandList(){
this.addCommand("文字表示", "displayString");
this.addCommand("戻る", "back");
}
}
})();
まず、Windowを作るクラスWindow_CommandSample 、シーンクラスScene_SampleMenuの順に見る。
継承元:Window_Command
Scene_Commandを継承するとコマンドを表示するウィンドウになる。
なお、継承元をWindow_HorzCommandに変更すると横型のコマンド画面になる。
makeCommandList
this.addCommand(表示したい文字列, ハンドラーの名称)
makeCommandListは追加したいコマンドを登録するメソッド。ここでaddCommandを登録することでコマンドを追加していく。
setHandler
通常のウィンドウ作成でも利用するハンドラーへの登録だが、同メソッドを利用してコマンド系を追加する。addCommandで登録した名称を第一引数にすると、そのコマンドを決定した時の処理を記述することができる。
明細デザインが自由なコマンドウィンドウ
次は同じく独自のコマンドを表示するサンプルだが、コマンドのレイアウトを自由に設定できる。各子アイテムの幅・高さ、描画内容も独自に設定ができる。メニュー画面のアクター一覧、アイテム画面のアイテム一覧などが該当する。単一のウィンドウを表示するクラスと同じだが、Window_Selectableを継承する。本来はこちらの機能を実現するためのクラスである。以下は、配列順にコマンドを表示するサンプルだ。
/*:
* @plugindesc サンプルPlugin
* @target MZ
* @help
* 列挙型の独自ウィンドウを表示するサンプル
*
* @command openScene
* @text シーン開始
* @desc サンプルシーンの開始。
*
*/
(() => {
const pluginName = document.currentScript.src.match(/^.*\/(.*).js$/)[1];
// Plugin Command
PluginManager.registerCommand(pluginName, "openScene", () => {
SceneManager.push(Scene_SampleMenu);
});
//サンプルウィンドウを管理するシーン
class Scene_SampleMenu extends Scene_MenuBase {
create() {
super.create();
//ウィンドウレイヤーを作成
this.createWindowLayer();
//サイズの決定。x座業,y座標,幅,高さ、
const rect = new Rectangle(200, 100, 400, 300);
//ウィンドゥの作成
this._sampleWindow = new Window_SelectSample(rect);
//このウィンドウにフォーカスを当てる。
this._sampleWindow.activate();
//一瞬動物名を表示させてからウィンドウを消す。
this._sampleWindow.setHandler("ok", this.DisplayString.bind(this));
//キャンセルでウィンドウを閉じる。
this._sampleWindow.setHandler("cancel", this.popScene.bind(this));
//上記設定でウィンドウを作成
this.addWindow(this._sampleWindow);
}
DisplayString() {
//動物名称を表示
this._text = new Sprite(new Bitmap(Graphics.width, Graphics.height));
this._text.bitmap.drawText(this._sampleWindow.currentAnimal, 0, 0, Graphics.width, Graphics.height, "center");
this._text.x = (Graphics.width - this._text.bitmap.width) / 2;
this._text.y = (Graphics.height - this._text.bitmap.height) / 2;
this.addChild(this._text);
this.popScene();
}
}
//サンプルウィンドウ(コマンド型)
class Window_SelectSample extends Window_Selectable {
//初期処理
initialize(rect) {
super.initialize(rect);
this._animal = ['あひる','ひよこ','犬','猫','ねずみ','牛','羊','豚','ライオン','いのしし'];
this.currentAnimal = '';
//リフレッシュを実行すると、drawItemがmaxItem回呼ばれる。
this.refresh();
}
//最大列数
maxCols() {
return 4;
}
//1行の高さ
itemHeight() {
return 80;
}
//列間
colSpacing() {
return 10;
}
//最大アイテム数
//今回は動物の配列数、つまり10個
maxItems() {
return this._animal.length;
}
//enable条件
isCurrentItemEnabled() {
if (this.index() % 2 == 0)
{
return true;
} else {
return false;
}
}
//アイテム内の描画
drawItem(index) {
const rect = this.itemLineRect(index);
const numberWidth = this.textWidth("0000");
this.drawText(index, rect.x, -15 + rect.y + this.lineHeight() * 0, numberWidth);
this.drawText(this._animal[index], rect.x, -15 + rect.y + this.lineHeight() * 1, numberWidth);
}
//ユーザーがアイテムを実行した時の処理
processOk() {
//動物を画面に表示
this.currentAnimal = this._animal[this.index()];
super.processOk();
}
}
})();
まず、Windowを作るクラスWindow_SelectSample 、シーンクラスScene_SampleMenuの順に見る。
継承元:Window_Selectable
単一画面と同様にWindow_Selectableが継承元になる。いくつかの設定をいじることで複数子アイテムの作成と選択型にすることが可能となる。
initialize
個別の場合は独自に処理を書いてもよかったが今回の場合、各子アイテムの描画はrefresh()を実行すると行われる。どこで実行しても良かったが、今回のテンプレートは初期化時に行った。
maxCols, maxRows
最大列数、最大行数。maxColsを定義することで、横4列に渡って子アイテムを配置した後に次の行で横に指定列、さらに次の行で……と子アイテムを配置するようになる。
itemHeight, itemWidth
子アイテムの高さ、幅。高さを指定することで、各子アイテムの高さが定義されると同時に2行目以降のアイテム位置が自動調整される。
colSpacing, RowSpacing
隣り合う横(縦)アイテムの間隔
maxItems
最大アイテム数。子アイテムはこの数まで自動的に作られる。
isCurrentItemEnabled
Enable可否。この条件でfalseになるとボタンを押しても反応しない。今回は1アイテム置きに選択できる・できないが変化するようにした。
drawItem
実際の描画部分。子アイテム分、indexを増加させながらこのメソッドをループする。const rect = this.itemLineRect(index)を使用することで、デフォルト(子アイテムの左上)となるrect.x, rect.yを取得することができる。
processOk
ユーザーがボタンを押下した時の処理。
DisplayString
processOkでそのボタンの動物名を変数に保持しており、描画の際にこの変数から文字を取得するようにしている。
関連リンク
当サイトのRPGツクールMZプラグイン開発のトップページ。他の記事へのリンクをまとめている。