開発日誌

すべての記事

[ テクニック ] [ プラグイン/スクリプト ] サブフォルダ付きプラグインの仕様変更

2021-07-05 23:17:06

RPGツクールMZのバージョン1.3.2がリリースされました。

先々週公開のバージョン1.3.0で仕様追加されたサブフォルダ関連の改善がなされましたが、サブフォルダ内にjsファイルが格納されても正しくプラグインが動作するような修正対応「サブフォルダ内のプラグイン名取得」が、これによって逆に動作しなくなってしまいました。なんちゅうことしてくれた……。

当サイトのプラグインも再修正しました

というわけで、拙作プラグインも先日修正したものを再び修正しました。河原で積んだ石を鬼(公式)に壊された気分w

サブフォルダを使っていなければ特に影響はありませんが、6月23日以降にダウンロードされた方は、お手数ですが修正版を再度ダウンロードお願いします。

プラグイン名の自動取得

ただ元に戻すのは癪だったので、この機会にプラグイン名を自動的に取得できるようにしてみました。

具体的には、

const pluginName = decodeURIComponent(document.currentScript.src).match(/([^\/]+)\.js$/)[1];

として、自分のファイルパスからファイル名を取得しています。

従来はプラグインのファイル名を変更すると動作しなくなっていたのですが、これによりファイル名を変更しても動作するようになります。

ただ、プラグインファイル名については、ユーザーで勝手に変更することを想定していないケースが多く、特にMZ以降、@base@orderAfterなどのプラグインの依存関係を定義するアノテーションも登場したため、ある程度の知識がないとファイル名の変更は推奨されません。

1.3.2修正の要点

結局のところプラグインのサブフォルダ問題は、

  • プラグインパラメータやプラグインコマンドはサブフォルダ名を含まない、プラグインファイル名のみをキーにして取得
  • 同名のプラグインが別フォルダに存在する場合は重複している旨の警告が出る

という形で対応がなされたようです。

つまり、プラグイン名は別フォルダであっても同名のファイルを避けるようにするべきで、サブフォルダは純粋に、ユーザーが多数のプラグインファイルを分類して整理できるようにした便利機能と位置づけられた模様です。

既に1.3.0の時点で対応修正した分が無駄にならないように、とか、プラグインIDとファイルパスを別々に指定できるように、とかの提案もあったようですが、結局1.3.0対応の修正は思いっきり無視されて、最小限の修正で済むような対応となった模様です。

まあ、一時のマズい仕様に対応するために余計なコードを増やしてもしょうがないので、これはこれで仕方ないかと。明らかに影響範囲の広すぎる仕様変更だったので、性急に個人で対応せず、公式の発表を待てばよかったかもしれませんね。我々が騒いだから、公式も影響の大きさに気付いた、という面もありそうですが……。

お陰でコアスクリプトの理解も進んだし、.match( )に入れた部分を簡単に取得する方法も今回の修正を通じて知れたので、収穫もあった……とポジティブ思考。

[ テクニック ] 何度か使うと壊れるアイテムの実装

2021-06-25 00:37:34

戦闘中に複数回使用でき、何回か使うと壊れてしまうアイテムを、プラグインなしで実装する方法の解説です。

いわゆるドラクエの「祈りの指輪」のようなアイテムですね。

ただ、祈りの指輪は移動中でも使えますが、RPGツクールの標準仕様だと、メニュー画面(移動中)で使用した場合に、壊れた時のメッセージをどう表示するかという問題があるので、今回は戦闘中にのみ使用できるアイテムに限定しています。

こういうのはプラグインでないとできないと思っていましたが、コモンイベントだけで比較的簡単に実装できました。

壊れる確率をどう設定するかというのがゲームバランスに直結します。自分専用に作るならともかく、プラグインとして広く公開するとなると、この確率計算の指定方法をどうするのかが悩ましくなりますが、コモンイベントであれば確率計算はユーザーが自由に作れます。

ここでは例として、「安息のハープ」という、戦闘中にのみ何度か使えて味方全員のHPを50回復するアイテムを作ってみます。

壊れる確率ですが、3回までは確実に使えて、3回目の使用後に25%の確率で壊れ、4回目に50%、5回目に75%、6回目は100%の確率で壊れる、という風にしました。1回目でいきなり壊れてしまうと残念なので、必要な時には躊躇せず使えるようなバランスを目指しました。

まずはコモンイベントを作成します。

このコモンイベントで、使用回数のカウントと壊れる確率の計算、そして壊れた場合の処理を行います。

壊れるアイテムが複数ある場合は、よっぽど数が多くない限りは、アイテムごとにコモンイベントを用意した方がいいかもしれません。壊れる確率の計算やメッセージの表示部分が、アイテムごとに異なると思うので。

変数を2つ使用します。1つはこのアイテムの使用回数をカウントする専用の変数。もう1つは計算過程で使うだけなので汎用の変数で構いません。

まず最初に、使用回数のカウントと壊れる確率の計算です。

◆変数の操作:使用回数 += 1
◆条件分岐:使用回数 >= 3
 ◆変数の操作:汎用変数 = 6
 ◆変数の操作:汎用変数 -= 使用回数
 ◆変数の操作:汎用変数 -= 乱数 0..3

使用回数を+1し、2回目までは壊れないので、条件分岐で3回目以降の場合のみ、壊れる確率の計算に入ります。

確率計算部分が少しややこしいですが、まず「6 - 使用回数」を算出しています。3回目の時は3で、4回目の時は2、6回目の時は0となります。

そしてその値から、0~3の乱数を引き算します。そうすると結果の値は、3回目の時は3~0、4回目の時は2~-1、6回目の時は0~-3となります。

結果の値が0以下の時に壊れる、とすることで、最初に設定した3回目に25%、4回目に50%、6回目に100%という確率が実現できます。

この辺の確率計算は、ゲーム全体のバランスを考えて、他にも自由に設定可能です。

 ◆条件分岐:汎用変数 <= 0
  ◆SEの演奏:壊れた際のSE
  ◆スクリプト:BattleManager._logWindow.push('addText', '壊れたメッセージ');
        :BattleManager._logWindow.push('wait');
        :BattleManager._logWindow.push('clear');
  ◆アイテムの増減:安息のハープ - 1
  ◆変数の操作:使用回数 = 0

前述の通り、条件分岐で汎用変数が0以下の時に、壊れた場合の処理を行います。

まずは壊れた際に分かりやすくSEを鳴らしました。この辺の演出はお好みでどうぞ。

次に壊れたメッセージを表示しますが、戦闘ログに表示させるため、ここはスクリプトを用いています。壊れたメッセージは任意のテキストが使用できます。

イベントコマンドの「文章の表示」だと、戦闘ログではなく通常のメッセージウィンドウで表示されてしまうため、ややテンポに劣ります。ここはどうしてもスクリプト頼りになるため、プラグインなしで実装と言うとちょっと語弊があるかもしれませんが。

そして当該アイテムを1つ減らして、最後に使用回数を0にリセットします。

以上で作成したコモンイベントを、当該アイテムの「使用効果」のコモンイベントに指定します。

こうすることでアイテム使用時にコモンイベントが呼ばれ、壊れる判定と壊れた時の処理が行われます。

RPGツクールMVの頃は、1つのアイテムにつき1つのコモンイベントしか呼べなかったのですが、RPGツクールMZになって複数のコモンイベントを順に呼べるようになり(今回の例では複数呼べる必要はないですが)、特殊アイテムの実現もやりやすくなりました。

なお、アイテムの消耗は「なし」(消耗するかどうかはコモンイベントで行うので)、使用可能時を「バトル画面」に設定するのを忘れないようにしてください。

今回は戦闘中にのみ使用可能なアイテムということにしていましたが、移動中(メニュー画面)でも使用可能にした場合、変更する必要があるのは壊れたメッセージの表示部分だけです。

イベントコマンドの「条件分岐」で、スクリプトに$gameParty.inBattle()と記入すれば、戦闘中か否かを判別できるので、戦闘中なら上記と同じように戦闘ログに表示、そうでなければ「文章の表示」でメッセージを表示するようにすればOKかと思います。

[ テクニック ] [ プラグイン/スクリプト ] サブフォルダ内のプラグイン名取得

2021-06-22 23:14:17

※追記:
バージョン1.3.2の修正で、本対応は不要となりました。逆に動作しない原因となるため、お手数ですが各プラグインの再ダウンロードをお願いします。
サブフォルダ付きプラグインの仕様変更」記事参照。

RPGツクールMZのバージョン1.3.0(1.3.1)がリリースされ、プラグインフォルダにサブフォルダを作れるようになりました。

多くのプラグインは、プラグインパラメータやプラグインコマンドの取得のため、自分のプラグイン名を指定する必要がありますが、jsファイルをサブフォルダ内に入れることは基本的に想定されていないため、このままだと動作しなくなってしまいます。

ここではプラグイン作者向けに、サブフォルダ内に格納された場合でも、自分のプラグイン名を正しく取得するスクリプトを紹介します。

サブフォルダでプラグイン整理

RPGツクールでプラグインとして提供されるjsファイルは、プロジェクトフォルダの中にある js/pluins フォルダの中に格納する決まりになっています。

しかし、プラグインは何十個と導入するケースも珍しくなく、pluginsフォルダの中に大量のファイルが存在することになってしまいます。

このことから、RPGツクールMZバージョン1.3.0では、pluginsフォルダの中にサブフォルダを作ることができるようになりました。これによって、プラグイン作者別に整理したり、戦闘系・マップ系・メニュー系・立ち絵系……などとジャンル別に整理したり、といったことが可能になりました。

非常に便利ですね!

▲フォルダ内に雑然とあったファイルが…

▲この通りフォルダ分けされてスッキリ!

プラグイン作者泣かせの変更

しかし、この変更はプラグイン作者にとってはかなり厄介です。

プラグインパラメータやプラグインコマンドの実装の際、自分のプラグイン名を指定する必要があります。サブフォルダ内に格納されたプラグインの場合は、このプラグイン名が「サブフォルダ名/プラグイン名」となります。

もともとサブフォルダ内に格納できる仕様ではなかったため、多くのプラグインでは冒頭で、

const pluginName = 'プラグイン名';

のように自プラグイン名を直接指定しており、「プラグインのファイル名は変えないでください」で通していました。しかし、サブフォルダ名はユーザーの任意で付けられるので、プラグイン作者の方で事前に指定することができません。

document.currentScript.scrで自ファイル名を自動的に取得する方法もありますが、現在普及している書き方はやはり、サブフォルダ内に格納されることを想定していないため、正常に動作しません。

また、サブフォルダの中にさらにサブフォルダを作ることも可能となっており、全てのパターンに対応しようとすると、けっこう一筋縄ではいきません。

自分のプラグイン名を取得する

というわけで、自分のプラグイン名を取得するのにどう書けばいいのかということですが、トリアコンタンさんが真っ先に取得方法を上げてくださっていました。ありがとうございます。

https://gist.github.com/triacontane/71064daf535160d4d355aeb9bc3c49f9

以下は、それを参考に少しアレンジしたコードです。ご自由にお使いください。

const pluginName = decodeURIComponent(document.currentScript.src).replace(/^.*?\/plugins\/(.*).js$/, "$1");

※追記:
さらに、うなぎおおとろさんが改良版を上げていらっしゃったので、それを採用しました。ありがとうございます。

https://github.com/unagiootoro/RPGMZ

const pluginName = decodeURIComponent(document.currentScript.src).match(/^.*\/js\/plugins\/(.+)\.js$/)[1];

少し詳しく解説すると、decodeURIComponentは、フォルダ名やファイル名が日本語(非ASCII文字)の場合に、正しく日本語に変換(デコード処理)するための関数です。

document.currentScript.srcで自分のjsファイル名を取得できますが、これで取得できるのはフルURIのため、ここからプラグイン名のみを抽出する必要があります。

抽出は正規表現を使って、/js/plugins/から末尾の.jsまでの間の文字をプラグイン名として取得しています。

※さらに追記:
当初、正規表現の冒頭を^.*?として最短マッチを使うことで、サブフォルダ名に「plugins」が使われても正しくマッチさせるようにしていましたが、逆に配信サイトのURLに万一「plugins」が入っていた場合に動かなくなるとの指摘をいただいたため、修正しました。そんなことする人もいないと思いますが、サブフォルダをjs/pluginsにはしないようにしてください。

他に、もっとスマートな書き方とか、この書き方だと正常に動作しないケースとかがあれば、教えてください。

当サイトのプラグインも修正しました

というわけで、プラグインパラメータもプラグインコマンドも使っていないプラグイン以外は、現在出回っているほとんどのプラグインに影響が出ると思います。厄介なことしてくれちゃって……。

まあ、フォルダ分けしなければ影響は出ないので、使えなくなるというわけでもありませんし、修正はごくわずかです。ユーザーの方でも難しい修正では全然ありません。

拙作プラグインもほとんど影響が出るので、全て修正しました。めんどくさかった……。

[ テクニック ] [ 素材 ] [ プラグイン/スクリプト ] イベントキャラ移動の改善プラグイン

2021-06-17 23:08:30

イベントキャラクターのランダム移動やプレイヤーに近づく移動を改善するプラグインを作りました。RPGツクールMVとRPGツクールMZの両方に対応しています。

イベントキャラクターの移動に関して以下の3点を改善します。

1点目は「移動ルートの設定」における「ランダムに移動」。

RPGツクールの標準のランダム移動は、まず上下左右4方向からランダムに移動方向を決定し、その方向に移動ができたら移動する、という仕組みになっています。ランダムに決定された方向に障害物があって動けない時は、移動が発生しません。

したがって、3方向を囲まれた袋小路のような場所にキャラクターがいる場合、1/4の確率でしか動かないことになります。

このプラグインはそれを改善します。先に上下左右4方向で移動可能な方向をリストアップし、その移動可能な方向の中からランダムに移動方向を決定します。したがって、袋小路のような場所でも必ず動ける方向に動きます。

2点目は「自律移動」の「ランダム」。

RPGツクールにおける自律移動タイプの「ランダム」は、実は完全にランダムに移動するわけではなく、1/2の確率で今向いている方向にそのまま前進、1/6の確率でその場に停止、1/3の確率でランダムな方向に移動する仕組みになっています。

完全にランダムだと周りをウロウロするだけの怪しい動きになってしまうので、これ自体は動きを自然に見せるための仕組みだと評価できます。ただ、それぞれの確率を調整したい場合もあるでしょう。

このプラグインは、プラグインパラメータで前進と停止の確率を調整できます。デフォルトは前進が50%(1/2)、停止が17%(1/6)となっており、この値を変更すれば、ランダム移動の確率を高くしたりすることができます。

また、1点目のランダム移動の改善も適用されるため、キャラクターがランダム移動で狭い場所に入り込んでしまった時の動きが、劇的に改善されると思います。

そして3点目は「自律移動」の「近づく」。

RPGツクールにおける自律移動タイプの「近づく」は、ランダムと同様、常にプレイヤーに近づいてくるわけではなく、少し遊びのある動きをします。具体的には、プレイヤーに近づいてくる移動は2/3の確率であり、1/6の確率でランダムに移動、1/6の確率で今向いている方向にそのまま前進します。

敵が追いかけてくるような動きの場合は、この確率だと少々無駄な動きが多く、かといってカスタム移動の「プレイヤーに近づく」だと100%近づいてきてしまうため、それはそれで逃げ場がありません。

ランダム移動と同様、プラグインパラメータでランダム移動と前進の確率を調整できます。デフォルトはどちらも17%(1/6)で、この値を小さくすれば、より積極的に近づいてくる動きになります。

実際の動きはこんな感じ。狭い場所に入った時のランダムな動きや、プレイヤーへの接近具合が改善されているのが分かります。

質問やアドバイスなどはコメント欄まで、お気軽にお願いします。素材利用条件などについては、このサイトについての「提供素材について」の項目などをご覧ください。

[ テクニック ] 地形タグで滑る床を実現

2021-06-10 21:01:46

床に矢印が描かれていて、上に乗ると矢印の方向に強制移動させられる――いわゆる「滑る床」と呼ばれるお馴染みのダンジョンギミックの作成方法です。

RPGツクールでこの「滑る床」を実装する方法は、イベントを敷き詰める方法、始点にのみイベントを置く方法、プラグインを使う方法、リージョンIDと並列処理を使う方法、と様々ありますが、おそらくプラグインなしで一番簡単に実装できる方法として、地形タグと並列処理を使った方法を解説します。

地形タグとは?

まず「地形タグ」って何やねん、という話ですが……。

「地形タグ」とは、RPGツクールVX Aceから登場した機能で、データベースの「タイルセット」で1つ1つのマップチップに、0~7の8種類(デフォルトは0)の番号を割り振ることができます。

おそらく戦闘背景の制御などを意図して用意されたものと思われますが、特に正式な用途は定められておらず、ツクールにしては珍しく汎用的な項目となっています。

同時期に登場した「リージョンID」が、ランダムエンカウントの制御という本来の目的以外に、立体交差の実現など様々な用途で利用されているのに比べると、この「地形タグ」はマイナーな存在で、初めて知ったという方も多いのではないでしょうか。

今回は、そんな「地形タグ」をフル活用した「滑る床」の実装方法です。

滑る床に地形タグを振る

最初に注意点として、この方法は地形タグを4つ使用します。地形タグは8種類(デフォルトの0も含む)しか設定できないので、既に別の用途で地形タグを4つ以上消費している場合は、この方法は使えません。

まず、データベースの「タイルセット」で、矢印の滑る床のマップチップに「地形タグ」を設定します。

矢印の床はダンジョンのタイルセットにあります。

地形タグの振り方が分からないかもしれませんが、「地形タグ」を選んだ状態で、対象のマップチップを左クリックすると数字が1ずつ増えていき、右クリックすると数字が1ずつ減っていきます。

地形タグの番号は何でもいいのですが、↓に4、←に5、→に6、↑に7と振っておくと、向きの番号(↓が2、←が4、→が6、↑が8)と順番が揃うので分かりやすいかと思います。

マップに配置する

地形タグを振り終わったら、実際に矢印の滑る床をマップ上に配置していきましょう。

すぐ正面は外れルートに、正解ルートはどう配置しようか、意外なところに宝箱へのルートを作ったり、簡単すぎず難しすぎずのバランスを考えるのが楽しいのではないでしょうか。

イベントやリージョンIDを使った方法だと、床を配置したら、それに合わせてイベントやリージョンIDも設置しないといけません。床の配置を変更したら、イベントやリージョンIDも変更しなければならず、間違えるとギミックが破綻します。その点、地形タグであれば直接マップチップに紐付いているため、二重に設定する手間が省けるのが大きなメリットです。

並列処理イベントを作成する

さて、いよいよ根幹部分です。

マップの端あたりにイベントを設置し、トリガーを「並列処理」にします。

それと、地形タグを受け取る変数を1つと、滑り中か否かを判別するスイッチと、滑り処理中か否かを判別するスイッチの2つを用意します。

以降、ちょっと長いですがイベントの実行内容を順に解説します。

◆指定位置の情報取得:変数1, 地形タグ, プレイヤー

イベントコマンドの「指定位置の情報取得」を使います。

地形タグを受け取る変数を指定し、情報タイプには「地形タグ」を指定します。

そして場所は、RPGツクールMZで新たに設定項目として加わった「キャラクターで指定」で「プレイヤー」を指定します。

RPGツクールMV以前ではキャラクターでの場所指定ができないので、先にプレイヤーのX座標とY座標を変数に取得し、その変数で場所を指定する必要があります。ちょっと手間ですね。ショボい機能追加しかないと酷評されがちなMZですが、地味ながらもこうして新機能の恩恵を感じられると嬉しいです!

◆条件分岐:「地形タグ変数」 >= 4
 ◆条件分岐:スイッチ「滑り中」がOFF
  ◆スイッチの操作:「滑り中」 = ON
  ◆メニュー禁止の変更:禁止
  ◆移動ルートの設定:プレイヤー(ウェイト)
  :        :◇歩行アニメOFF
  :        :◇向き固定ON
  :        :◇移動速度:6
 :分岐終了

まずは現在位置の地形タグで分岐します。

地形タグが4以上であれば滑る床に乗っているので、滑る床の処理をします。

この時、スイッチの「滑り中」がOFFであれば、普通の床から滑る床に入った瞬間を意味するので、その処理をします。

すなわち、まずは「滑り中」のスイッチをONにします。次に滑っている最中にメニュー画面を開けないよう、メニューの禁止をします。そしてプレイヤーの移動ルートで、歩行アニメはOFF、向き固定はON、移動速度は最高の6にします。これで、プレイヤーキャラクターが滑っている最中のモーションらしくなります。

 ◆条件分岐:スイッチ「滑り処理中」がOFF
  ◆SEの演奏:Miss (90, 150, 0)
  ◆スイッチの操作:「滑り処理中」 = ON
 :分岐終了

次に、スイッチの「滑り処理中」がOFFであれば、滑るSEを鳴らして、「滑り処理中」のスイッチをONにします。

「滑り中」と「滑り処理中」の2つがあって紛らわしいですが、「滑り中」は現在滑る床に乗っているかの判定、「滑り処理中」は滑る床の効果でプレイヤーが1マス強制移動させられている最中かの判定に使っています。

1マス移動している最中にも並列処理は呼ばれ続けるので、移動中か否かを判別してやらないと、滑るSEが鳴りすぎて壊れた感じになってしまいます。

滑るSEは、標準素材だと「Miss」のピッチを150にしたのが、それっぽいと思って愛用しています。

 ◆条件分岐:「地形タグ変数」 = 4
  ◆移動ルートの設定:プレイヤー(飛ばす)
  :        :◇下に移動
  ◆ウェイト:3フレーム
 :分岐終了

いよいよ地形タグ(矢印の向き)に応じて強制移動させる部分です。

地形タグが4、すなわち↓の床の場合は、「移動ルートの設定」でプレイヤーを下に移動させます。この時、「移動できない場合は飛ばす」のチェックは入れ、「完了までウェイト」のチェックは外します。

そしてウェイトがないとやや速すぎるので、適度なウェイトを入れます。

 ◆条件分岐:「地形タグ変数」 = 5
  ◆移動ルートの設定:プレイヤー(飛ばす)
  :        :◇左に移動
  ◆ウェイト:3フレーム
 :分岐終了
 ◆条件分岐:「地形タグ変数」 = 6
  ◆移動ルートの設定:プレイヤー(飛ばす)
  :        :◇右に移動
  ◆ウェイト:3フレーム
 :分岐終了
 ◆条件分岐:「地形タグ変数」 = 7
  ◆移動ルートの設定:プレイヤー(飛ばす)
  :        :◇上に移動
  ◆ウェイト:3フレーム
 :分岐終了

同様に、地形タグが5(←)、6(→)、7(↑)の場合の強制移動も設定します。

地形タグの変数が同時に4~7の複数の条件を満たすことはないため、条件分岐の「それ以外のとき」で入れ子にする必要はありません。

:それ以外のとき
 ◆条件分岐:スイッチ「滑り中」がON
  ◆移動ルートの設定:プレイヤー(ウェイト)
  :        :◇歩行アニメON
  :        :◇向き固定OFF
  :        :◇移動速度:4
  ◆メニュー禁止の変更:許可
  ◆スイッチの操作:「滑り中」 = OFF
 :分岐終了
:分岐終了

それから、最初の現在位置の地形タグでの条件分岐において、4以上でない、すなわち現在地が滑る床ではない場合の処理に移ります。

この時、スイッチの「滑り中」がONであれば、滑る床から普通の床に着地した瞬間を意味するので、滑っている最中のモーションを元に戻し、メニューを許可し、スイッチの「滑り中」をOFFにします。

「滑り中」がOFFであれば、もともと普通の床を歩いている状態なので、特に何もしません。

◆スイッチの操作:「滑り処理中」 = OFF

最後にスイッチの「滑り処理中」をOFFにして、並列処理は終了です。

並列処理は重いから使いたくないという方もいると思いますが、他にも並列処理を山ほど実行しているならともかく、このくらいの並列処理で重くなることはありません。

特に「滑り処理中」のあたり、もう少しスマートな処理の仕方はありそうですが、一応これで思った通りの動作になっています。こうした方がいいのでは?とかあれば、教えてください。