見出し画像

RPGツクールプラグイン制作過程紹介 第12回

前回からだいぶ間が空いてしまいましたが、再開していきたいと思います。
前回はマップ画面にスキル選択ウィンドウを表示するところまで作りましたが、今回はその表示内容を作っていきます。

スキル選択ウィンドウ

現在の画面を再度確認してみましょう。

スクリーンショット 2021-09-26 12.10.48
空のウィンドウが表示されています

ご覧のようにウィンドウは表示されていますが、その内容は何も描画されていません。前回、このウィンドウの作成関数に指定したウィンドウクラスはWindow_SkillListでした。それならスキル一覧が表示されていても良さそうなものですが…なぜ何も表示されないのでしょうか?

このような場合、コアスクリプトでもともとWindow_SkillListが使用されている部分を解読することで原因を調査することができます。また、関連コードが流用できれば一気に解決することもできるでしょう。
そこで、まずはWindow_SkillListをVisual Studio Code(以下VSC)で検索してみましょう。

スクリーンショット 2021-09-26 12.24.15
Window_SkillListの検索結果

以前にもご紹介した通りこの検索結果でまず注目すべきはこのクラスの定義箇所である、コメントから始まる「// Window_SkillList」です。そちらを開いてみましょう。

Window_SkillListの定義箇所

結論から言ってしまうと、ここで重要なのはinitializesetActor関数です。特に、this._actorというプロパティに代入している箇所が重要です。詳しく見てみましょう。

Window_SkillList.prototype.initialize = function(rect) {
    Window_Selectable.prototype.initialize.call(this, rect);
    this._actor = null;
    this._stypeId = 0;
    this._data = [];
};

まずはinitializeです。この関数は以前にもご紹介した他クラスの同名関数と同じく、このクラスのインスタンスが作成されるときに自動的に呼び出される初期化関数コンストラクターです。
ここではthis._actorプロパティにnullが代入されています。これ自体には特に意味はなく、この後の処理のための下準備となります。それではその処理を見てみましょう。

Window_SkillList.prototype.setActor = function(actor) {
    if (this._actor !== actor) {
        this._actor = actor;  //①
        this.refresh();       //②
        this.scrollTo(0, 0);  //③
    }
};

このsetActorという関数は、actorという引数を取ります。
最初の条件式では、このインスタンスが持つthis._actorプロパティと引数actorを比較し、!==等しくないかどうかを判定しています。その結果が等しくないの場合ブロック内の処理を実行し、等しいの場合は何もしない、ということをやっているのです。
真の場合に実行する処理とは
this._actorプロパティに引数actorを代入する
refresh関数を呼び出す
scrollTo関数を呼び出す
の3つです。
②と③は今は無視して構いませんので、①にのみ注目しましょう。

①がやっていることというのは、現在のthis._actorプロパティの値を新しいactor情報で上書きする、というものです。this._actorプロパティはこのウィンドウに描画されるべきスキルの所持者を表します。このプロパティに有効なアクターを代入することでこのウィンドウにスキル一覧が描画される、という仕組みになっています。
ではなぜ最初にthis._actorプロパティの値と引数actorを比較したのかといえば、パフォーマンスのためです。
②のrefreshという関数はコアスクリプトで多用されている非常に重要な関数なのですが、その内容は「ウィンドウ内の内容を全て消去し、現在の情報で再描画する」というものなのです。この処理はやや重いのであまり何度も呼び出すと負荷がかかってしまいます。そのためむやみにrefresh関数を呼び出すべきではないのですが、かと言って本当に必要な時に呼び出さないのも本末転倒です。ではどうすればいいのかというと、今の状態が「再描画に値する」かどうかを判定し、値するならrefreshを呼び出す、という方法が考えられます。
例えば今描画対象になっているアクターとは別のアクターが描画対象になったとしたら、当然スキル一覧が変わるはずです。これは十分に「再描画に値する」と言えるでしょう。反対に、もし新しいアクターが今の描画対象アクターと等しい場合、スキル一覧が変わることはありません。これは、再描画に値しません。
このような条件を判定することこそが、最初の条件式の意図というわけです。

ケイシーのスキル一覧。赤枠がWindow_SkillList
エリオットに切り替えた状態。Window_SkillListの内容が変化している

関数の改造

さて、本題に戻ります。現在の課題は、Window_SkillListが表示されてはいるが内容が描画されていない、というものでした。そこで再度このクラスのインスタンスが作成されている箇所を見てみましょう。

Scene_Mapに定義したウィンドウ作成関数

createItemWindow関数によってWindow_SkillListのインスタンスを作成することはやっていますが、setActor関数は今のところ全く呼び出していません。つまり、このウィンドウ君には「誰の」スキルを表示すべきかが分からない、ということなのです。それでは表示のしようがありませんね。これが「ウィンドウに何も表示されていない」現象の原因です。

というわけで試しにsetActorを呼び出してみましょう。createItemWindow関数に以下のように追記してみます(コメントアウト部分は省略)。

Scene_Map.prototype.createItemWindow = function() {
    const rect = this.itemWindowRect();
    this._itemWindow = new Window_SkillList(rect);
    this.addWindow(this._itemWindow);
    this._itemWindow.setActor($gameActors.actor(6)); // 追記分
};

追記分ではthis._itemWindowWindow_SkillListのインスタンス)に対してsetActorを呼び出させるようにしています。その引数は$gameActors.actor(6)となっていますが、これはなんなのでしょうか。このコードは、いわばツクールにおけるイディオム決まり文句です。

$gameActors.actor(アクター番号)

上記のアクター番号を任意のアクター番号に置き換えることで、その番号のアクターが得られます。これはとても便利なので覚えてしまいましょう。
アクター番号6は「ケイシー」です。つまりこのウィンドウのスキルの持ち主をケイシーに設定する、という処理です。リード君でも良かったのですが、本プラグインでよく使うスキルを多数習得している彼女の方が適任ということでここではケイシーにしました。
それでは早速試してみましょう。

特に変化なし!

おや……? まだ何も表示されないようですね。何がおかしいのでしょうか?
もう一度Window_SkillListを見てみましょう。

initializesetStypeId

Window_SkillListinitialize関数には、this._actorプロパティへの代入の次にthis._stypeId = 0という処理もありますね。また、先程のsetActorのすぐ下にsetStypeIdというとてもよく似た内容の関数が定義されています。
stypeIdとはなんなのかと言うと、スキルタイプの番号を表します。スキルには、デフォルトでは「必殺技」や「魔法」といった区分がありますよね。あれがスキルタイプです。データベースの「タイプ」で名前を設定でき、またそのタイプを個々のスキルに対して設定できるというのは、みなさんよくご存知のことと思います。

データベース「タイプ」
スキルへのスキルタイプの設定

スキルの使用画面では、以下のように使われています。

赤枠のウィンドウ内でスキルタイプを選択

右上のウィンドウ内でスキルタイプを選択すると、下のウィンドウにそのスキルタイプに対応したスキル一覧が表示される、という仕組みになっていますよね。というわけで、これもWindow_SkillListに必要不可欠な情報なのです。このウインドウは「どのアクターのスキルを表示するか」という情報を必要とする、と上記しましたが、同様に「どのスキルタイプのスキルを表示するのか」という情報も不可欠なのです。つまり先ほどのWindow_SkillList君は「ケイシーを表示すればいいのは分かったけど、ケイシーの必殺技と魔法のどっちを表示すればいいのか分かんないよ〜!」という状態になったせいで何も表示できずにいた、ということなのです。
そういうことであれば、createItemWindow関数にさらに追記してみましょう。

Scene_Map.prototype.createItemWindow = function() {
    const rect = this.itemWindowRect();
    this._itemWindow = new Window_SkillList(rect);
    this.addWindow(this._itemWindow);
    this._itemWindow.setActor($gameActors.actor(6));
    this._itemWindow.setStypeId(1); // 追記分
};

先ほど見たWindow_SkillListsetStypeId関数を1という引数で呼び出しています。1は「魔法」のスキルタイプ番号です。それでは試してみましょう!

ちゃんとケイシーの魔法一覧が表示されるようになりましたね!
ですがもちろんこのままではケイシーの、しかも魔法しか表示できないウィンドウになってしまいますので、さらなる改良が必要です。とはいえテスト目的であればこの程度でも十分である、ということがお分かりいただけたかと思います!

まとめ

というわけで今回はスキルリストウィンドウにスキル一覧を表示させるようにしてみました。お疲れ様でした。

ツクールのウィンドウクラスには非常に多くの関数が定義されており、それらの意味をコードだけで理解しようとするとなかなか大変です。そこで実際にそれが使われている場面をゲーム上で確認することにより、理解を早めることができます。このようなテクニックは今後もよく使いますので、慣れていくと良いでしょう。

次回は今回の内容を進めて、スキルリストウィンドウのアクターやスキルタイプを切り替えられるようにするにはどうすればいいのか、というのを見ていこうと思います。

それではまた次回お会いしましょう!

今回までの最終コード

大変申し訳ありませんが、今回から最終コードは記事上には記載しませんのでGithub上でご確認ください。
ご理解の程、何卒よろしくお願い申し上げます。

この記事が気に入ったらサポートをしてみませんか?