神無月サスケの波瀾万丈な日常

神無月サスケのツイッター(@ktakaki00)を補完する長文を書きます。

多機能フックローププラグインの紹介とその哲学

多機能フックローププラグインとは?

2017年、僕は、RPGツクールMV用に、マップ上のアクション系プラグイン
「多機能フックローププラグイン」を公開しました。
https://forum.tkool.jp/index.php?threads/851/
簡単に言うと、フックロープなのですが、複数の機能を持ち、
汎用性が高く作られています。
百聞は一見にしかず。こちらに、このプラグインを使用した1分弱の動画がありますので、
まずはご覧になってください。
https://youtu.be/PBEbrzYt3xI

関連プラグイン:ツミオさんのアクションプラグイン

さて、このプラグインのみならず、巷には、
同様の、アクション系プラグインは、それなりに紹介します。
そこでまずはそれらのプラグインの中から、
有名なひとつをピックアップして紹介します。
それを紹介した後で、「それではなぜ、多機能フックロープなのか」という
話をしたいと思います。

ツミオさんのアクションプラグイン

プラグイン】特殊なアクションを実装
https://forum.tkool.jp/index.php?threads/669/
僕がこれを選んだのは、僕が知っている中で、
最も多機能なプラグインだからです。
ゼルダの伝説にあるアクションをそれこそすべて搭載する勢いで
数多くのアクションが設定可能です。
これらの挙動は動画でデモを観られます。
Youtubeの「ツミオチャンネル」
https://www.youtube.com/channel/UCTIxXkDwcTkAiku5WFt6oDQ
こちらでは、アクションプラグイン以外にも、
あなたの興味を惹く多くのプラグインのデモ動画もあるため、
単に「ゼルダの伝説のような、様々なアクションを導入したい」
という方は、ツミオさんのプラグインの方がいいかもしれませんね。
なお、彼はカンパ歓迎と話しているので、
気に入ったらカンパしてあげてほしいな、と思っています。

ツミオさんのプラグインと多機能フックロープ

さて、多機能フックローププラグインに話を戻します。
このプラグインは、フックロープのみであり、
ツミオさんのプラグインと比較して、
機能のバリエーションという意味では、明らかに見劣りします。
しかし、機能を絞りこむ代わりに、ある種の「哲学」を貫いているのです。
すなわち、僕の一貫するポリシー、哲学を理解してくれた人に
使ってもらいたいと思っているのです。

多機能フックロープに込めた「哲学」

ひとつのアイテムが複数の機能を持つのが望ましい

まず、僕がこのプラグインで目指したのは
「道具と言うのは、決まった一つの使い方のみならず、
いろんな使い方が出来るのが理想」というものです。
ゼルダの伝説シリーズを思い出してください。
複数の使い方があるアイテムや、
基本的な使い方は一つだが、特定の場所で思わぬ使い方が出来る……
そんな形で、多彩な使い方が出来るアイテムが多数あります。
僕がこのプラグインで目指したのは、まさにその方向性なのです。

直観的であること

前述の「基本的な使い方は一つだが、特定の場所で思わぬ使い方が出来る」というのは、
要するに、その道具の決められた機能にはなかったけれど、
現実世界の常識に照らし合わせて、「あ、あれでああできないかな」って考えて
試してみたら、それがビンゴだった、そういうことです。
すなわち「(現実世界に照らし合わせて)直観的である」ということです。
考えてみてください。最近の大規模なオープンワールドのゲーム(GTAシリーズを始めとする)は
全てこれに従っていますね。
そして、ゼルダの伝説も、この方向性が、シリーズを追うごとにどんどん進化しているのは、
僕より皆様の方が、詳しいと思います。
このようにゲーム内に説明はないけれど、直観的に試したら、うまくいった……
プレイヤーの期待に最大限応えてあげるのが、いいゲームデザインだといえます。
ただし、これを徹底するには、壮大な人海戦術が必要です。
個人制作では、到底追いつきません。
しかし、出来ることは出来る。多機能フックロープは、3つの機能を持たせました。

多機能フックロープの3つの機能

前述の動画を観ていただいて、もうご存知かもしれませんが、
改めて、このプラグインの3つの機能を紹介します。


1.フックロープの先に杭があった場合、プレイヤーが杭の手前まで移動
 基本。
2.フックロープが接触したイベントを起動
 川を挟んだ先にあるスイッチを操作するなど。
 - サンプルプロジェクトでは、普通に話しかけた場合と、フックロープをぶつけた場合でセリフが変わる人物を配置。
3.フックロープの先に接触したイベントを、目の前に持ってくる(フェッチ)。
 落とし穴を挟んだ先にある宝箱などのアイテムを取ってくる。
 - なお、目の前が通行不可の地形の場合、プレイヤーが一歩後退する仕様。
 - 目の前が通行不可でプレイヤーが後退不可の場合、取ってこられない。
気づかなかった人は、上記を意識して、もう一度動画をご覧ください。

このプラグインを使う際の設定について

では、このプラグインを実際に使ってみることを考えてみます。
実はこのプラグイン、多機能ゆえに、設定が少しだけ、手間がかかります。
詳しいことは、プラグインのヘルプに全て載せていますので、
ここでは、要点をピックアップしてみましょう。

何の設定に手間がかかるのか

なぜ設定に手間がかかるのか。それは「3つの動作が可能」であることの裏返しです。
どのイベント(またはタイル)に、フックロープは反応するのか。
それを設定しないといけませんが、それはすなわち、
「どのイベントがプレイヤーを移動させる杭で、
どのイベントが、イベント起動で、どのイベントが、持ってくることが出来るか」
を設定するということです。
これは主に、イベントのメモで設定しますが、
ひとつひとつ「これはこの動作」とメモに書いていたら、
作業量はとんでもないことになりますね。
そこで、プラグインのオプションで、
「ひとつのイベントに<picket>と書けば、その画像のイベントは全部杭になる」
「この条件を満たすイベントは、全部、デフォルトでフックロープが触れたら起動」
「この条件を満たすイベントは、全部、デフォルトでフックロープでフェッチ可能」
といったことが可能になっています。
具体的には、「なし」「!で始まるイベントのみ」「全て」が選べます。
なお、対象は「イベントに画像が設定されている」「プライオリティが通常キャラと同じ」を
満たすイベントだけです。
こうやってデフォルトを設定すれば、
「例外的にこの機能を持たせる(あるいは持たせない)イベント」にだけ
メモを書くことで済みます。

競合を解決するための優先順位の定義

さて、複数の機能を入れたことにより、一つ課題が出てきました。
それは「機能が競合してしまう」ことです。
ひとつのイベントに複数の機能が設定されても、その中のどれかひとつしか選べません。
また、フックロープを投げた先の範囲内に、複数のイベントがあった場合、
どれに反応すればいいのでしょう。

複数の動作が適用可能なイベントの優先順位

設定により、ひとつのイベントに、複数の機能が割り振られる設定になる状況が考えられます。
しかも、設定の方法をなるべく簡略化したため、
このプラグインでは、結構起こりやすい事象になります。
そんな時のために、複数が設定されていたら、以下の優先順位をとっています。
1(杭)>2(起動)>3(フェッチ)
こうした根拠は、より直感的なものを優先したからです。

「範囲内に複数の候補が存在した場合」

例えば、最大7延びるロープで、杭が4つ先と6つ先にあった場合、どちらに移動するか?
これは、大抵の人は、近い方、と答えるでしょう。
実際、一番近いイベントを重視しています。
しかし、開発の初期では、一番遠い方のイベントを優先していました。
その方が、なんとなく直観的に感じたからです。
ところが、テストプレイした方の全員が「不自然」と言ったため、一番近い方になりました。
いやはや、僕の「直観的」は、少しずれているのかもしれません。

サンプルプロジェクトの中身

なお、上記の動画ですが、サンプルプロジェクトをアップしています。
http://www.moonwhistle.org/tkoolMV/HookRopeTest.zip
RPGツクールMVをお持ちの方で、興味がおありのお方は、お試しください。
そして、プロジェクトをいじって、いろんなギミックを作ってみてください。
ギミックについては、僕の頭ではサンプルプロジェクトの範囲が限界でしたが、
公開することで、皆に面白い使い道を見つけてもらえそうなのでアップした、
ということです。
ぜひ、興味がおありの方は、ダウンロードして、いじって遊んでくだされば幸いです。

多機能フックローププラグインを支える技術

この記事は、ツクールMVの多機能フックローププラグインの記事です。
https://forum.tkool.jp/index.php?threads/851/
https://youtu.be/PBEbrzYt3xI

本日の先の記事と合わせてお読みください。

この記事は、このプラグインを作るにあたって直面した
技術的困難を中心に扱います。
専門的な内容なので、あまり興味がない人、プラグインが読めない人などは、
適当に読み流してください。

プラグインをダウンロードして、中を見てみましょう

さて、ここからはプラグインを実際にお見せしながら
説明していきたいと思います。
プラグイン単体(動作に必要な画像素材付き)は、以下のアドレスから入手可能です。
http://www.moonwhistle.org/tkoolMV/SuperiorHookRope.zip
こちらのプラグインは、前述のサンプルプロジェクトに入っているものより、
若干バージョンアップしています。

ロープが可変長ゆえの、アニメーションの動的生成の必要性

まず最初にこのプラグインを作るにあたって一番重要だったのは、
アニメーションを、データベースに登録するのではなく、
プラグイン内で動的に生成している、ということです。
これは、プラグイン利用者にデータベースでアニメーションを作ってもらうのが
煩わしいから、という理由だけではありません。
このプラグインは、ロープの長さが可変長に延びますが、
フックロープの動作は、アニメーションによって実現しています。
もし、データベースでアニメーションを登録するとすれば、
異なる長さごとに上下左右のアニメーションを作る必要があります。
例えば長さ最大7なら、0〜7まで8通り×上下左右4種類で、
32個のアニメーションが必要になります。
この手間は、ただごとではありません。
当然、現実的ではありませんね。
このため、プラグイン内で、プログラムで直接生成する必要が
出てくるというわけです。

アニメーションの動的生成のために:データ構造の解析方法

アニメーションを動的生成するために必要なのは、
データ構造を解析することです。
アニメーションのデータはJSON形式で、テキストファイルで見ることが可能です。
しかし、データの細かい意味が、それだけでは分かりません。
ツクールMVのヘルプにもJSリファレンスがありますが、そこには簡単な説明しかなく、
データの細かい説明はほとんどないため、解析が非常に困難と言えます。
そこで僕は、奥の手を使いました。
それはRPGツクールVX Aceのヘルプを参考にすることです。
両方のツクールをお持ちの方ならお気づきでしょうが、
RPGツクールMVのデータベースのデータ構造は、RPGツクールVX AceのRGSS3の
データ構造をベースにしています。
特に、アニメーションのように、追加機能が少ないものに関しては、
ほぼ1対1対応がある、と言っても過言ではありませんでした。
この事実は、データ構造を理解する上で非常に助かりました。
実際に、ご覧ください。

ご覧のように、日本語で、なおかつデータの詳細について説明してくれており、
情報量が全く異なり豊富なのが分かるでしょう。
こうしてめでたく構造を理解できた僕は、
アニメーションの動的生成を組むことに成功しました。
よくOSやツールなどの解析で言われることですが、
「データ構造が解析できれば、半分は解析できたも同然」
ということなのです。

タッチパネル対応。移動中いつフックロープを使うか

さて。次は、RPGツクールMV特有の課題です。
ツクールMVで作る以上、マルチプラットフォームを意識する必要があるため、
タッチパネル(、マウス操作)にも対応しなければなりません。
PCの場合、マウス操作以外でも操作は出来ますが、
スマートフォン移植前提の作品で使ってもらうなら、タッチパネル対応は必須でしょう。
そこで、タッチパネル移動時は、杭やフェッチ可能なイベントをクリックすると、
「フックロープが使えるところまで歩き、使えるようになった場所で使う」という
動作が必要になってくる、と考えました。
これは、それほど難しくなく、実装出来ました。
具体的には、プラグインの一番最後、Game_Character.prototype.findDirectionTo を
再定義している部分で処理している。興味のおありの方はお確かめいただきたい。
簡単に説明すると、
「フックロープ使用可能状態で、
なおかつ目的地がフックロープ関係のイベントの場合、
目的地への移動中、
プレイヤーが目的地へフックロープ到達可能の位置にいたら、
目的地の方を向いてフックロープ使用、プレイヤー移動はキャンセル」
ということです。

フックロープが壁を通過できなくする処理

フックロープは、壁を通過できないので、その前で止める必要があります。
これは、その座標に壁があるかどうかが判別できれば簡単です。
それでは、具体的にどうやるのでしょう。
実を言うと、このプラグインでは、A3タイル(壁の上部)とA4タイル(壁)の判定のみを
行っており、タイルA5やB〜Eで準備されたカスタムの壁は、通過します。
(ここのところは、今後のバージョンアップで設定可能にするなど、
対策が必要かもしれませんね)
A3タイルやA4タイルは、4層あるツクールMVのタイルの、最下層に位置します。
(「ちょっと待った、4層ではなく3層では?」という方がいらっしゃるかも知れませんが、
2つの上層と1つの下層の間に、タイルA2の一部を置く中層というものがあるんです)
そこで、最下層(レイヤー1)のタイルIDを確認します。
タイルIDはイベントコマンド「指定位置の情報取得」でも取得が可能な値です。
ただ、タイルIDで、それがタイルA3やA4なのかどうやって判定するのでしょう。
それは、タイルID仕様を知る必要があります。
これについては、「ツクールMV タイルID仕様」で検索すると、
調べてくれている人がいます。
https://www.f-sp.com/entry/2016/09/25/131242
この数値は一部RPGツクールVX Aceとも共通です。
これが分かれば、「目の前に壁(A3、A4タイル)があるか」はすぐできます。
自分で調べると結構骨が折れるので、
調べてくれている人に感謝、ですね。

力業で乗り切った点も

プレイヤーの移動とフックロープのタイミング合わせ、実は場当たり的

重要な点として、ツクールMVでは、プレイヤーの移動と、
アニメーションの表示は独立しています。
そして、フックロープは、アニメーションで実装されています。
フックロープを使う際、イベントをフェッチしたり、プレイヤーが一歩下がったり、
という場合、その動作にアニメーションをシンクロさせなければならないのですが、
これは、かなり場当たり的にやっています。
具体的には、フックロープの伸び方に応じて、最大の長さに達した時のウェイト数を変えたり、
逆にフェッチされるイベントの移動速度を、フックロープのアニメーションに
合わせたりしています。
本当に力業のため、フックロープの長さによっては、
若干タイミングがずれることもあるのですが、
ここはイベント移動とアニメーションのシンクロという点で、仕方ないことです。
なお、プレイヤーの移動ルートも、フェッチされるイベントの移動ルートも、
JavaScriptのオブジェクト記述形式、すなわちJSON形式で、直接リテラルで記述しています。
アニメーションのデータもそうですが、
ツクールMVはデータ構造がJSONというテキストで記述しやすい形式だからこそ、
実現できた部分が、このプラグインには多いのかもしれません。

アニメーションの関係から、一般的な(48x48サイズの)キャラにしか使えない

これもアニメーションの見た目を自然にするために、力業でのりきった点です。
フックロープを、プレイヤースプライトのどの座標から出すか……
下手をすると、上を向いているとき、頭や背中からフックロープが生えてくるように見えます。
そういったことをなくすため、プレイヤーが上下左右の向きで、
それぞれ座標を補正しています。
……ただ、これが原因で、ツクールMVの標準素材やジェネレーターで作成したような規格以外の、
特徴的なキャラクターが使うと、不自然な見え方になってしまいますが、
これはもう、現時点での仕様の限界、ということになります。

まとめ

いかがでしたでしょうか。これ以外にも、プラグインの中身を見ていただければ、
いろいろと分かりにくい部分で工夫しているのを理解してくれる人も
いらっしゃると思います。
今回、「多機能フックローププラグイン」として、ゼルダの伝説のギミックのように
「複数の機能を持たせる」「直観的にする」というものを作ったわけですが、
仕様的にも、技術的にも、いろいろ悩んだりしましたが、本当に考えていて、
苦になることはありませんでしたね。
むしろ、ゼルダの伝説がいかに偉大かが、よくわかりました。
何事も経験、ですよね。自分でやってみることで、改めて、凄さを知る。
僕にとって、このプラグイン制作の経験は、自らの身体の一部になっています。
この記事が、皆さまの何かのご参考になれば、幸いです。