エフアンダーバー

個人開発の記録

続・RPGツクールでローグライクな雰囲気を醸してみた

なんやかんやでまた書き始めたRPGツクールMVのローグライクプラグイン。

www.f-sp.com

JavaScriptでの整理が難しくなったのでTypeScriptに切り替えたり、 循環参照を保つためにシリアライザを置き換えたりしていたのですが、 それでもなお拡張に限界を感じたため、 とりあえずここまでの成果を曝して、また無期限延期とすることにしました。

ああ、やっぱり今回も駄目だったよ。

進捗

基本的に内部をいじっていたので、見てわかる変化は階段と敵が増えたくらいです。 機能としては階層管理機能とターン制の導入になります。

f:id:fspace:20161201153300g:plain
階層移動

f:id:fspace:20161201153301g:plain
ターン制

仕様

一応プラグインとして作る以上、エディタから設定しやすいものにしたいな、と思いいろいろと考えていました。

階層管理

階層管理(どの階層にどういったフロアを割り当てるか)は専用のタグ<blueprint>を設定したマップを作成することでできるようにしています。

二次元のマップの左上から順に一次元のインデックスを割り当て、階段などで特定階層へと移動する際には、 移動先階層と一致するインデックスの位置に設定されたイベントのコマンドを実行するという仕様になっています。 ここに特定マップへと移動するコマンドを書き込んでおけば、階層とフロア設定が関連付けられるという仕組みになっています。 また、イベントコマンドならなんでも書き込めるので、体力回復やダンジョンでない通常のマップへの移動などもできます。

インデックスの0番(一番左上)は特殊な番号として扱っていて、 現在は階層管理マップに直接移動したときのダンジョン初期化用として使っています。 現状未実装ですが、ひとつのイベントには複数のイベントページを作成できるので、 階層管理マップ範囲外のインデックスにアクセスした際のデフォルトコマンドの設定等への活用も考えていました。 これを実装すると、ダンジョン最後の階層の階段を上った際に実行するコマンドの設定ができるようになります。

f:id:fspace:20161201153258p:plain
全8階層の階層管理マップ

フロア管理

フロア管理(フロアのデザインや敵の設定等)もまた専用のタグ<dungeon>を設定したマップを作成することでできるようにしています。

マップ上の好きな場所に対応する設定を施した上で、専用のタグを設定したイベントを配置することで設定が読み込まれます。 例えば、フロアの壁に使用するタイルを設定したい場合には、好きな場所に壁用のタイルを設定し、その場所に空のイベントを配置、 イベントのメモ欄に<wall>タグを設定することで、そのタイルがダンジョン生成時に壁となった場所に配置されます。 敵や階段の設定も同様で、好きな場所に配置したイベントに<enemy>タグや<stairs>タグを設定し、適当な画像を設定しておくと、 そのイベントが自動的に複製されて、ダンジョン内に配置されます。

また、生成されるダンジョンの大きさはフロア管理マップの大きさと同じになります。 ダンジョン生成に使われるアルゴリズムもフロア管理マップにタグをつけることで切り替えられるような仕組みになっています (現状テスト用のシンプルなアルゴリズムひとつしかありませんが)。

f:id:fspace:20161201153259p:plain
森っぽいフロア管理マップ

拡張の限界

言い訳という名の愚痴。

階層やフロアの管理などをつくっている段階まではまだよかったのですが、 敵を表示するためにイベントを動的に生成し始めたあたりから管理に限界を感じ始めたため、実装を中止することにしました。

ツクールをローグライク化するためには、なかなかに大規模な変更を加える必要があるため、 直接コアエンジンのクラスを拡張していくと他のプラグインとの競合が発生しやすくなってしまいます。 そこで、今回はローグライク関連のモデルをツクールとは独立で作成し、 そのモデルに合わせてツクール側の要素を調整することでローグライク化を実現しようとしていました。 が、結局このツクール側の要素を調整するという部分が非常に面倒だったのです。

基本的にツクールはツクール自体の仕様を実現するためだけにできており、拡張性はほとんど考慮されていません。 具体的な例を挙げると、イベントの動的生成ができません。 マップにイベントを追加する機能がないのはもちろん、 そもそもイベントの内容はすべてグローバル変数として読み込まれているデータを直接参照していて、新たな挙動のイベントインスタンスが作れません。 グローバル変数のイベントデータはシリアライズされないので、ここにイベントデータを追加してもセーブ&ロードで消えてしまいます。 また、クラスの分割単位が非常にでかいので、同じインターフェースのクラスをつくって誤魔化すことも現実的ではありません。 さらには、これらの問題を解決してイベントインスタンスを生成したとしても、 マップの初期化がすでに終わっているので、プライベート変数を繰り、スプライトの追加等々の調整をする必要があります。

・・・とまあ、何かしようとするたびにやたらとコストがかかるのです。 そして変更に弱いというリスクも抱えます。

もともと想定されていない機能を盛り込むわけなので、もちろんある程度のコストは仕方のないことなのですが、 もう少しオブジェクト指向っぽい設計になっていればなぁ、と思うことがたびたび。 さすがにコスパが悪いのでここらで切り上げることにしました。

ソースコード

前回と同じとこに置いてあります。

github.com

ライセンスはMITです。

おわりに

今回、とりあえず一旦休止しますが、もしもいい設計案とか思いついたらまた始めるかもしれません。 前回も、もうやめるとか言っておきながらやってますので・・・。

次回の記事は、冒頭で述べたTypeScriptやらシリアライザやらの話になる予定です。



執筆時のRPGツクールMVのバージョン:1.3.4