プラグイン作成で気をつけたいところや自作プラグインの解説
閉じる
閉じる

新しい記事を投稿しました。シェアして読者に伝えましょう

×

プラグイン作成で気をつけたいところや自作プラグインの解説

2017-12-06 00:04


    こんにちは、まっつUPです。
    初めましての方も多分いると思いますが
    ぼくはRPGツクールMVでゲームを作成するついでにプラグインを作っています。

    プロフィールのところにゲームの公開先リンクがあります→
    ふりーむのコンテストにも参加していますので是非プレイを→

    今回は、今ここを閲覧している皆さんがもっとプラグインに
    触れやすくなるように解説をしていくつもりです。
    もう止まるんじゃねえぞ・・・と祈るだけのプラグイン導入生活に終止符をうちましょう。

    まだブログに慣れていないので拙い部分が多いと思いますが
    温かい目で見ていただければ幸いです。
    なお、このページで得た内容で何か不利益があっても
    まっつUPは責任を取ることはできないのでご了承ください。

    しかし、解説者が信用できないのに話は聞けないという方がいると思います。
    そこで、ツイッターでぼくが信用できるか聞いてみました。
    エロゲヒロインの話は102票もらえたのに(半ギレ)
    このように他の選択肢と拮抗していることが分かりますが、結果は明らかです。
    つまりまっつUPはストーンエッジと同じくらい信用できるということです!
    さて、ぼくを信じてもらえたところで記事の内容に入っていきたいと思います。

    RPGツクールMVのコアスクリプトは軒並み優秀なので
    RPGに必要なプラグインは既存処理の拡張が主になります。
    まだプラグインを作ったことない方は
    既存のプラグインの構成を参考にするとよいと思います。

    例えば、ぼくが作っているプラグインは
    開発者YojiOjimaさんの公式プラグインや
    キノコ王国の古文書を参考にして、構成しています。
    トリアコンタンさんありがとう!

    まずこちらのツクマテのプラグインを落としてください。(行をクリックしてね!)

    BattlebustPict.jsは拙作のプラグインで、
    新規の関数も必要であったためいくらか定義しているものの
    コアスクリプトの機能や拡張を多めに使っているため
    保守性に優れます。これを解説に使おうと思います。
    (全てのコードを解説するわけではありません。)

    ちなみに、プラグインを組むのに使ったエディタはVSCです。

    最初にプラグインのユーザーが見る部分から解説します。
    皆さんが毎日のように動かしている
    ツクールMVのエディタを起ち上げておいた方がいいでしょう。



    見やすさを考慮してパラメータ等のコメントの一部を削除しました。

    最初のファイル名ですが単にコメント(コードとして実行しない)
    としているだけなので、何らかの形で表示していればいいと思います。
    なお、ファイル名は半角英数字で構成してください。

    /*:jaと*/で囲われた部分が日本語ヘルプの記入部分です。

    @plugindescの内容は
    エディタのプラグイン管理画面の「説明」で表示されます。

    @authorには
    作者名を記入してください。


    @param,@desc,@default
    はプラグインパラメータの内容です
    それぞれ「パラメータの一意の名称(半角英数字)」、「パラメータの説明」、
    「プラグイン導入時点での初期値」を記入してください。

    @type numberとありますが
    これはパラメータの入力方法を少し変更することができます。
    値に数値を取りたいパラメータの場合は@type numberがよいでしょう。
    値に真偽値を取りたいパラメータの場合は@type booleanがよいでしょう。

    パラメータのtypeの指定方法に関してはツクマテの記事が参考になります。

    (行をクリックしてね!)

    @help
    プラグインを選択した時に見ることのできる
    「ヘルプ」の内容を記入してください。
    ファイルの利用規約はここに記入することが多いです。

    なお、以上の内容はプラグイン管理画面で合っているか確認できます。

    実際のコード部分の説明に入ります。

    今回のプラグインではプラグインパラメータがあるので
    扱いやすいように変数に代入しておきます。
    varから始まっているのでローカル変数への代入だと分かりますね。
    これは拙作だけでなく、多くの方がコードの最初の方でやっています。

    var parameters = PluginManager.parameters('BattlebustPict');
    var BPstartId = Number(parameters['startId'] || 50);
    一行目は導入されているこのプラグインのパラメータを取得します。
    とりあえず入れておきましょう。引数に入れるファイル名を間違えないように。
    2行目以降には同じような表現が並んでいます。
    Numberとある通りパラメータを数値型で取得しています。
    この場合、パラメータの入力がない時には50を取得します。
    他にもStringなどがありますがNumberだけ覚えていれば困りません。

    さて、BattlebustPict.jsで行う大まかな処理は以下の2つです。

    ・バトル開始直後にパーティメンバーの立ち絵を更新する。
    (バトル開始時のフェードインまでに更新は終わります。)

    ・パーティメンバーのステータスに変化があった時に立ち絵を更新する。


    開始時



    ダメージを受ける



    この「立ち絵を更新する」の処理は全く同じ処理を使っています。



    Game_Party.prototype.TimingUpdateBPのことですね。
    このthisはGame_Partyを意味するので
    内容を見るとパーティメンバーに何らかの処理をしていることが分かります。
    forEach文は主体の配列の項目数だけ、内容を繰り返し処理するので
    パーティメンバー全員(一人ずつ)に同じ処理を行うことができます。
    (ここでのactorはパーティメンバーの一要素、
     すなわちアクターを示しています。
     Game_Actorから始まる関数を呼び出すことができます。)

    このように共通の処理を使えるようにスクリプトを組んでいきましょう。

    次にGame_Party.prototype.onBattleStartを見ましょう。
    先に説明したバトル開始直後にパーティメンバーの立ち絵を更新する。
    を実行している部分です。

    ここでは
    ・オーバーライド
    ・フック
    という
    ツクールのプラグインを組む上で
    避けては通れない二つの技術が使われています。


    オーバーライドというのは
    親クラスで定義されている関数と
    同名の関数を子クラスで定義することです。

    処理を上書きしたいなら単純に新しい関数作ればよくね?
    と言う方がいると思います。
    おっしゃる通りです。
    しかしながら、これはツクール用のプラグイン。
    後述のフックと合わせて考えた場合オーバーライドの方が優れていると思います。

    <なぜそう思うのか>
    Game_PartyとGame_Troopは親クラスにGame_Unitを持ちます。
    Game_Unit.prototype.onBattleStartという関数がGame_Unitで定義されています。

    プラグイン未導入の状態では
    Game_PartyとGame_Troopは両方ともonBattleStartとつく関数は定義されていません。

    この時、Game_Partyを主体とする場合にonBattleStartが正しく呼び出された時
    Game_Unit.prototype.onBattleStartが実行されます。
    Game_Troopを主体とする場合も同様です。

    それぞれの共通の処理としてGame_Unit.prototype.onBattleStartが
    定義されていると考えられます。

    しかし、別名の新規の関数を作った場合は
    呼び出し元の記述をonBattleStartから直接変えなければいけません。
    オーバーライドならば子クラスに関数がある時はそれを優先して実行するので
    変える必要がありません.
    これらのことを考えるとオーバーライドした方がよいと思います。


    次にフックについて説明します。

    var _Game_Unit_onBattleStart = Game_Unit.prototype.onBattleStart; と
    _Game_Unit_onBattleStart.call(this); でフックしています。

    こうするとGame_Unit.prototype.onBattleStartの内容を
    call関数により実行することができます。
    引数には内容を実行する主体を指定することができますが
    今回のフックの役割としてはthis(Game_Partyを意味する)が適切です。
    第二引数以降には実行する関数の引数を入れますが(this, a, bみたいな感じで)
    Game_Unit.prototype.onBattleStartは引数を指定する必要がないので入れていません。

    なお、applyという機能が似た関数がありますがタケノコ王国ではcallのみ使っています。
    applyを使いたい方は各自調べてください。

    これらから既存の関数の内容を実行できることが分かると思いますが
    画像のコードを見るとフック以外の処理の記述があります。
    そういうことです。
    このフックの目的は既存の処理を実行しながら、追加の処理も実行することです。
    フックなしとの違いはフックで実行する関数の内容がデフォルトと違う場合でも
    変更後のものを呼び出せるので競合の回避が期待できます。

    <何が言いたいのか>
    つまり、Game_Party.prototype.onBattleStartは
    Game_Unit.prototype.onBattleStartの処理を実行しながら
    Game_Partyが主体の時のみ実行される処理を追加した関数です。

    <プラグイン内でのノートタグの扱い>
    2つ解説します。



    まずreturn data.meta[text];
    引数のtextの値と同じ名前のノートタグの値を返します。
    同じく引数であるdataの値がthis.actor()
    textの値が'BPnormal'の場合は
    return this.actor().meta['BPnormal'];
    を実行しているのと実質同じになります。
    これは関数を実行している主体のアクターのメモのノートタグを参照します。

    次にif(this.actor().note.match(/<BPnoequip>/i)) return;
    条件式は関数を実行している主体のアクターのメモに
    <BPnoequip>と入っていればtrueを返します。
    1行ifなのでtrueのときのみreturn;を実行します。
    ノートタグが入っている時は同関数内のその後の処理を実行しないので
    呼び出す前の関数に戻って次の処理に移ります。

    <最後に>
    以上がプラグインをつくるときに使う技術の例です。
    やや冗長な説明でしたがオーバーライドなんかはコアスクリプトでも
    Window_なんちゃらで多用されているので、ぜひ利用していきたいですね。
    皆さんのオリジナルのプラグインで動くゲームが
    公開されるのを楽しみにしております。

    TimingUpdateBPで検索すればステータス変化時の更新箇所も見つかると思います。
     上述の通り共通の処理が実行されています。興味がある方はご覧ください。
    ※うまくいかなかった場合は記述にミスがある場合が多いです。
     落ち着いて手を付けた場所を見直してみてください。
    ※フックした関数が元々returnなど戻り値に使用することを期待している関数の場合
    return _Game_Unit_kinokocrash.call(this);
    みたいな感じで組むとうまくいくかもしれません。
    ※関数をフックせずに上書きすることで動作するのが正常なプラグインもあるので
    なんでもフックすればいいというわけではありません。

    広告
    コメントを書く
    コメントをするには、
    ログインして下さい。