イベント命令のマクロ化プラグイン
イベント命令をマクロとして定義して、いつでも呼び出せるようにするプラグインを作りました。
ざっくり一言にするなら、既存の命令を組み合わせて、自分で新しいイベント命令を作れるようにするプラグインです。ここでいう新しいイベント命令のことを、マクロと呼んでいます。マクロは各々がメモリをもつので、コモンイベントの呼び出しよりも自由度が高いです。
試しに、現在地から対象物までの距離を教えてくれる命令を作ります*1。本プラグインを使うと、このイベント命令は次のように書けます:
あらかじめ定義しておいた「目標までの距離」マクロに、対象物の座標を入力して呼び出して、距離を求めてもらい、その結果を変数に代入して表示するのです。対象物が3個あると、求める距離も3通りありますが、距離を求める手続きはどれも同じなので、それを一つのマクロとして定義しておいて、それを呼び出すだけで実装できるという仕組みです。
マクロの定義から呼び出しまでの流れ
マクロの定義は、コモンイベントやマップイベントであらかじめ作成しておきます:
このイベント命令は、目標物の座標(x, y)を入力すると、プレイヤーからの距離を求めて返却するものです。目標物の座標(x, y)は(変数41番, 変数42番)として与えて、計算用に変数45番を使い、計算結果(距離)を、(変数43番, 変数44番)に格納します。
このとき、入力として与える(変数41番, 変数42番)のことを引数、計算結果の(変数43番, 変数44番)のことを戻り値、変数45番のように計算用に使う、内部の一時的な変数のことをローカル変数とそれぞれ呼びます。
呼び出し側でこのイベント命令をマクロとして定義するときに、「(変数41番, 変数42番)が引数、(変数43番, 変数44番)が戻り値、変数45番がローカル変数」ということを教えてあげるのです。マクロの定義は、以下の赤枠部分に相当します。
このように記述しておけば、あらかじめコモンイベントで作成しておいた「目標までの距離を返す命令」がマクロとして定義され、以降、「マクロ呼び出し」命令でいつでも呼び出すことができます。マクロ定義はゲームのオープニングなどでまとめてやってしまっても良いかもしれませんね。
「マクロ呼び出し」命令は以下の赤枠部分です。引数と、戻り値の変数を変えて、3回呼び出しています。
引数には、対象物の座標を入れています。それぞれの対象物までの距離をマクロで求めて、その計算結果を、薪は(変数1番, 変数2番), 岩は(変数3番, 変数4番), さぼてんは(変数5番, 変数6番) にそれぞれ格納します。
コモンイベントの「目標までの距離」命令では、引数や戻り値を変数41番などの別の変数で定義していましたが、「マクロ定義」命令によってそれらは引数や戻り値として扱う、と紐づけられたことにより、マクロのイベント命令内に記述されている変数41番や42番には値の読み書きが一切されなくなり、代わりにそれぞれのマクロ自身がもっている内部的なメモリに読み書きされるようになります。変数41番や42番は、イベント命令を作成するために記述する仮の姿で、実際にマクロとして呼び出されるときには、すべて画面上に見えない内部メモリが使用されるのです。ちょっとややこしいですね。
そのため、引数(14, 3)、戻り値(変数1番, 変数2番)としてマクロを呼び出すと、値(14, 3)は変数41番, 42番には格納されずに、マクロの内部メモリに書き込まれます。変数43, 44, 45番にも値の書き込みは行われず、計算結果だけが(変数1番, 変数2番)に書き込まれます。
このように、マクロ自身がそれぞれ区別されたメモリをもっていて、メモリを介して入出力や計算を行うのが、単純にコモンイベントの呼び出しを行うことと異なる点です。コモンイベントの呼び出しで代替していたときには、どの変数を使用しないといけないか、などを都度考えなければなりませんでしたが、マクロ定義に使用する変数はすべて仮の姿ですので、自分さえわかれば、同じ番号の変数を流用して、変数の被りなどを一切考えず、安心して便利機能を作成することが可能になるのです。
また、マクロは別のマクロを呼び出すことができるので、この仕組みを利用すれば、例えばマクロが自分と同じマクロを呼び出す、再帰マクロを作ることもできます。マクロの記述は同じでも、マクロそれぞれのメモリは区別されているので、同じ変数に値が書き込まれないのです。使いどころが難しいですが、きっと何かの役に立つはずです。
再帰マクロの例(階乗):
スクリプト的な補足
変数の操作で、実際にはその変数ではなくマクロの内部メモリを読み書きするという仕組みは、スクリプト的には以下の関数をオーバーライドして実装しています:
・$gameVariables.value(変数の値の読み取り)
・$gameVariables.setValue(変数の値の書き込み)
そのため、スクリプト上でも単純に$gameVariables.value, $gameVariables.setValueをそのまま記述すれば、マクロ内の場合は勝手にマクロの内部メモリへの参照に切り替えるので、マクロ内かどうかを気にする必要はありません。
*1:南に-2歩とか、わけわかんないこと言ってるのは気にしないでね^^;