目次
概要
例えばホラーゲームには暗闇でライトを持って前方を照らす…みたいな挙動が良くあります。RPG Developer Bakinでどのように実装すればよいのか悩んでいましたが以下のDLCを購入して中身を見て楽しんでいたところその挙動が実装されていました。私自身の備忘録も兼ねてメモ書きで残しておきます。何かに残しておかないと絶対に忘れる…
※ この記事の動作は rev.1.5.0.7.r59282
で確認しています。Bakinはまだアーリーアクセスの段階なのでこの記事にある方法が使えなくなる可能性があります。
RPG Developer Bakinでゲームを作る参考としてこのDLCはかなり買いだと思います。ファンタジーではない現代を舞台にした作品を制作する際の素材としても良いものが入っているのですがそれ以上にサンプルの実装に参考になるものがたくさんありました。明かりで照らす挙動以外にも泳ぐ挙動の実装方法やレイアウトを使用しないメニューの実装が同梱されています。
光源となるパーティクルを用意する
光源になるパーティクル素材はDLCに付属しています。無料のDLCに似たようなパーティクルは同梱されていないか確認したのですが特に見当たりませんでした。
DLCに同梱されているので購入するのも手ですが光源1つであれば作成するのもあまり手間はかかりませんでした。この記事ではせっかくなので素材から作成する手順も残しておこうと思います。
光源の画像を作成する
まずは光源の画像を作成します。ここで言う光源とは例えば懐中電灯の明かりを壁や地面に当てるとその部分が円形に明るくなりますよね。その部分のことを指しています。
画像はAffinityDesignerと呼ばれる画像編集ソフトウェアの画面です。光源の画像を作成するツールは以下の事ができれば何でも良いです。
- 円を描画できる
- 円を中心から放射状にグラデーションで塗りつぶすことができる
- 色に透明度を設定できる
- 画像をPNG規格で出力することができる
画像では終端は透明度0%、始点の透明度40%、中間点の位置は80%、色は#FFDD9Eでグラデーションしています。かなり薄く見えますが作るゲームによってはもっと薄くても良いかもしれません。これだけ薄くてもBakinに取り込むとかなり濃く映ります。
Effekseerで光源のパーティクルを作成する
Effekseerはパーティクルを作成することができるオープンソースのソフトウェアです。BakinはEffekseerに対応しておりエフェクト作成ではお世話になるソフトウェアです。
ライトで光源を表現するのにパーティクルを利用します。といっても動きのあるパーティクルを作成する訳ではありません。光源の画像を作成するで作成した光源の画像を3次元空間に貼り付けた素材をパーティクルで表現するためです。
私もこの素材作成のために初めてEffekseerを触ったのでEffekseerの使い方や仕組みを理解している訳ではありません。使い方自体はヘルプを参照して頂ければと思います。
とりあえずダウンロードして開くと初期画面はこのようになっているかと思います。正確には白い四角い図形は画面下部の再生ボタンをクリックすると表示されるかと思います。
キャプチャの手順で光源の画像を作成するで作成した画像をパーティクルに設定してください。つまり地面に光源が当たっているかのように見えればよいのでX軸に対して平行かつ消えないパーティクルを1つ作り、そこに画像を当てはめています。
(壁にあたる光源を作るのであればX軸を回転させる必要はないです。)
光源が作成出来たら標準形式で出力します。
Bakin側でリソースとして追加
リソースとはゲーム内で使用する素材のことです。例えばアイコンの画像だったりキャラクターの立ち絵、3Dモデルやサウンド、パーティクル、とにかくゲームを制作する際に使用するあらゆるデータです。素材がパソコンのハードディスクに存在するだけではBakinでは使えません。
Bakinのプロジェクトにその素材がパソコン上のどこにあり何に使用する素材なのかを登録する必要があります。登録するとBakinのコマンドだったりイベントで参照(選択)できるようになります。
まずは作成したパーティクルをBakinで使用するパーティクルとして登録します。
右ペインの「パーティクル」を選択した状態で追加ボタンをクリックするとアセットピッカーが開きます。「ファイルから作る」のタブからはフォルダから素材を探せます。「すぐ使える」タブからはDLC素材を探せます。DLCは素材がすでに分類されており追加しようとしている個所の素材種別でフィルタリングしてくれるためとても便利です。
目的のファイルを選択して「追加して終了」をクリックすると登録されます。登録するリソースの名前やフォルダ構成は好みに合わせてください。
BakinにEffekseerで作成したパーティクルを登録するとプレビューと共に表示されます。左ペインの「パーティクルの設定」にてBakin側でパーティクルの設定をいじれます。が、今回は特に何も変更しません。
光源のEffekseerでの見た目とBakinでの見た目、特に色合いが異なります。私はここらへんは素人なので詳しくは分からないのですが実装するゲームに合わせて調整してください。画像編集とEffekseer側である程度修正を加える作業になるかと思います。
光源を持った2Dスタンプを作成
光源のリソースを作成できれば、続けてリソースを登録します。
登録するリソースは光源を持ったキャストの2Dスタンプです。スタンプとして登録することでプレイヤー(あるいはイベント)のグラフィックに適用することができます。
キャプチャを参考に光源を持った2Dスタンプを登録してください。ここまで読んでくださった方は気付いていると思いますが、ライトを持たないキャストと同じパターンアニメのライトを持ったキャスト(2Dスタンプ)を作成することでライトを持っている、持っていないを表現します。
(フラグか何かでキャストに設定されているスタンプを交互に切り替えればよい訳です。)
明かりがあった個所の反射処理自体はBakinがエンジンで行ってくれます。光源が当たった個所のパーティクルとローカルライトが合わさることであたかも明かりが当たったかのような表現が可能になります。
今回は特に表現されていませんが、キャストに懐中電灯や松明を持たせたらよりそれっぽくなるでしょう。
スタンプとキャストの違い
余談です。
以前の記事でイベント≒キャストと書きました。ではスタンプとキャストは何が違うのでしょうか?あくまで私の理解なので間違っているかもしれませんが私は以下のように理解しています。
スタンプとして登録したものはマップでは「物体」タブで選んで貼り付けることができます。キャストとして登録したものはマップでは「イベント」タブから選んで貼り付けることができます。
スタンプはそれ単独でマップに存在している場合はその物体(スタンプ)に実装されているイベントも単独で実行されます。つまり同じスタンプをもう1つ貼り付けたとしても実装されているイベントは貼り付けたスタンプごとに異なります。
例を挙げると、看板のスタンプがあるとしてマップに看板を複数貼り付けます。それぞれの看板で表示されるメッセージは異なるメッセージが表示したいと思います。その場合はキャストとして看板を登録するのではなく物体すなわちスタンプとしてマップに貼り付けてそれぞれでイベントを組むことになります。
一方でキャストとして貼り付けられた場合、そのキャストに実装されているイベントは貼り付けられたキャストすべてで共有されるのが特徴です。
例を挙げると、敵Aをキャストとして作成します。敵Aはその特徴として触れるとビックリマークを表示する性質を持たせたいと思います。仮に敵Aをスタンプとしてマップに貼り付けると貼り付けた敵の数だけイベントを組む必要があります。ですがキャストとして登録してマップに貼り付ければキャストに組まれているイベントは共有されるため貼り付けた敵の数だけイベントを組む必要はなく。データベースから敵Aのカスタムイベントを組むだけで済みます。
明かりが当たったかどうかの判定実装の箇所で少し関わるため解説させて頂きました。
切り替え処理の実装
この時点ではまだリソースとして登録されているだけです。通常の状態から何かしらの方法でライトを持った状態へと切り替えましょう。1例を紹介します。
まずは何でも良いので物体のスタンプを配置します。
配置したスタンプをクリックしてカスタムイベント画面を表示します。
プレイヤーと接触したタイミングでイベントを実行するシートでフラグをオンにするコマンドを実行します。
もう1つ並列に実行する1回だけ実行するシートを用意します。そのシートは実行条件としてフラグがオンになった時を実行条件とします。
そのシートでグラフィックをライトを持った2Dスタンプに切り替えると切り替え処理となります。
このような感じで切り替えられます。これはアイテム取得時にスタンプを切り替えていますが、ボタンで切り替えたいなら入力を変数に入れてその値でフラグを管理しスタンプの切り替え処理を行えばよいということですね。
明かりが当たったかどうかの当たり判定を実装する
せっかくなので明かりが当たったら出現する敵を実装してみようと思います。基本となる考え方は以前書いた以下の記事を参考にします。
とりあえずここでは以下の挙動の実装までを目標とします。
- 敵は初期状態では画面上では不可視である
- 照らされているライトの範囲内に敵がいたら敵を可視状態にする
- 敵がライトの範囲外に出たら再度不可視状態にする
今回の当たり判定にはレイキャストと呼ばれるコマンドを使用します。前回の記事ではイベントを動的に生成、射出して敵側(当たる側)でイベント同士の衝突を検知していました。
今回も同じ方法でできなくはないのですが…懐中電灯とかの明かりはつけたり消したりを繰り返す訳ではないですよね?
普通の概念で行けば暗いところにいれば明るくなるまでは明かりをつけ続けるはずです。そうなると明かりがついている間イベント同士の衝突で明かりの当たりを判定するには常に生成し続けるか、あるいは何かしらのタイミングまで射出したイベントの消失を留めておく必要があります。(加えて言えば消失を留める場合はプレイヤーの移動に合わせてイベントを明かりの部分へ追従させる必要がある。)
これはちょっと難しそう…と思ったところに見つけたコマンドがレイキャストでした。
レイキャストのコマンドはコマンドセレクタの「制御」のタブに存在するコマンドです。
プレイヤーあるいはイベントから伸びる白い箇所に物体や地形、イベントの接触を条件に処理を分岐させることができるコマンドです。このコマンドを使用するといかにも明かりが当たったっぽい処理を実装できます。(あくまでっぽいです。)
こちらのGIFを見てください。レイキャストコマンドは判定の領域を距離だけでなく角度も任意の角度に向けることができます。また変数の設定も可能なことが分かります。つまり…
とりあえず上下方向のX軸の角度は無視します。Y軸の角度へ入れる変数を用意して、その変数の値を一定範囲内で増減させれば図のような探査が行えるはずです。
特定の並列実行タイミングで探査したレイキャストの範囲にターゲットがいれば「はい」の処理へ分岐します。その際に明かりが当たったフラグを立てることでそれっぽい挙動が実装できるのではないかと考えました。
もちろん光源の位置とレイキャストの距離は合わせておく前提です。
プレイヤー側にレイキャストの当たり判定処理を入れる
ではこの考え方をベースに実装していきます。まず、レイキャストで探査範囲を定めるための変数の用意とその変数の値を増減させるコモンイベント処理を実装します。
キャプチャを参考にして頂きたいのですが解説をします。まず用意するフラグ(スイッチ)は以下の4つです。フラグ名や変数名は適宜決めてください。
- ライトが点灯しているかどうかを判別するフラグ
- ライトのオン、オフができているなら存在するはず
- Y軸の角度が増加中であることを示すフラグ
- Y軸の角度が減少中であることを示すフラグ
- ライトが対象に当たっていることを示すフラグ
変数では以下の物を用意します。
- 当たり判定を探査する距離を格納する変数
- Y軸の現在角度を格納する変数
- Y軸の角度の増減値を格納する変数
- Y軸の角度の最大値を格納する変数
- キャプチャでは用意されていないが必要に応じて(45の箇所)
- Y軸の角度の最小値を格納する変数
- キャプチャでは用意されていないが必要に応じて(ー45の箇所)
シートのイベント開始条件は両方とも「自動的に開始(並列して繰り返し実行)」で設定してください。
イベントに組む処理の流れは以下の通り。増加を例に説明します。
Y軸の現在角度が最大値(45)に到達していなければ、現在角度に対して増減値を加える ↓ 到達していればY軸の角度が増加中であることを示すフラグをオフにして、Y軸の角度が減少中であることを示すフラグをオンにする
減少ではこの流れが逆になります。
Y軸の現在角度が最小値(ー45)に到達していなければ、現在角度に対して減少値を加える ↓ 到達していればY軸の角度が減少中であることを示すフラグをオフにして、Y軸の角度が増加中であることを示すフラグをオンにする
イベントの流れは上記の通りでシートのイベントに起動条件を加えます。
増加する起動条件は以下の通り。
- ライトが点灯しているかどうかを判別するフラグはオン
- Y軸の角度が増加中であることを示すフラグはオン
- Y軸の角度が減少中であることを示すフラグはオフ
- ライトが対象に当たっていることを示すフラグはオフ
減少する起動条件は以下の通り。
- ライトが点灯しているかどうかを判別するフラグはオン
- Y軸の角度が増加中であることを示すフラグはオフ
- Y軸の角度が減少中であることを示すフラグはオン
- ライトが対象に当たっていることを示すフラグはオフ
これらが組めると、ライトが点灯していて対象に当たっていない間は常に角度が増減します。
キャプチャを参考にコモンイベントを組みます。レイキャストコマンドのチェック元は3つともすべて「プレイヤー」です。
ここまで実装出来たらテストプレイでレイキャストを表示してみてください。
想定通りならばレイキャストの探査棒が左右に振り子のように動いているはずです。細かいところは実装するゲームに合わせて調整すればよいと思います。
明かりが当たった側の処理を考える
これでプレイヤー側が明かりを放ち何かに当たったまでは判定できます。ですがここで悩みが出てきます。レイキャストコマンドは何に当たったかまでは判定できますが何にの「どれ」に当たったかを判定できません…
マップには物体やイベントが多数存在しているでしょう。その中で明かりに当たることで特定の挙動を行う必要があるものが1つしかないのであればその物体あるいはキャストに対して「ライトが対象に当たっていることを示すフラグ」を条件にしたイベントを組めば良いだけです。
しかし複数存在するのであればどれに当たったかを何かしらの方法で調べなくてはなりません。
Wiki等を読みつつ色々なコマンドを調べたのですが…現状のBakinだとそもそもにおいてマップに配置された物体(イベント)やキャストの個別の識別子を得る方法がない模様です。(もしも…あるよ!って知っている方がいたら教えて欲しいです!)
さてどうしたものかと悩み私なりの解決方法を実装しようと思います。あくまで1例であると思ってください。
まず一般論的な話をします。例えば暗闇で人にライトを当てたとします。当然、明かりが当たった人は背面でも向いていない限りは明かりが当たったという事実に気づけるはずです。言い換えれば明かりが当たっているタイミングで明かりを照射している何かが居る方向に向けば自身に明かりが当たっていることに気づくはずです。
この考え方を利用します。幸いにもBakinにはイベントの向きを変更するコマンドが用意されています。つまり明かりを当てたことはフラグによって判別できるのだから、そのフラグがオンになった時、当たる側のイベントすべてがプレイヤーの方向を向いてプレイヤー側のレイキャストと同じ距離だけ当たる側もレイキャストでプレイヤーの位置を探るのです。
レイキャストがプレイヤーと接触した場合、つまり以下2つ条件を満たしたイベントこそがプレイヤーの明かりの照射が当たったイベントと判断できるのではないでしょうか?
ということでこの考え方をベースにイベントを組みます。
1はすでに組んでいるため2を組みます。
まずはデータベースでキャストを追加します。グラフィックも設定しますが何でも良いです。
追加したキャストのカスタムイベントを組みます。まずは明かりが当たっていない時のシートを作りイベントを組みます。
キャプチャを参考してください。ポイントは明かりが当たっていない時はグラフィックが設定されていないことです。こうすることで不可視の状態を作ります。またここで起動条件となる明かりの判定フラグはローカルに新規に作成してください。
自身が明かりに当たっているかどうかを判別するためのイベントを組みます。並列に実行するシートを追加してください。
キャプチャを参考にしてください。ポイントというか注意点は明かりが当たっているかどうかを判定するフラグは2つあります。1つはプレイヤー側のレイキャストによるフラグ、もう1つはこのキャストが参照するローカルなフラグです。
グラフィックの切り替え自体はローカルのフラグを使用して行います。キャプチャだとイケてないのですが分かりやすい変数名をつけることをお勧めします。
対象のレイキャストでは自分自身がプレイヤーの方向を向いてプレイヤー側のレイキャストと同じ距離だけ衝突を測れば良いです。角度を移動させる必要はないです。
自身に明かりが当たっていない時に常にローカルのフラグをオフにするイベントも組みます。並列に実行するシートを追加してキャプチャを参考にしてください。
最後にローカルのフラグがオンの時のイベントを組めば目標完了です!
テストプレイ
どうでしょうか?明かりに当たると人魂が表示されるっぽくなりました。今回は不可視、可視の切り替えですが明かりに当たった状態を判別できるので明かりに当たったら逃げる敵や攻撃してくる敵みたいな表現もできるかと思います。
レイキャストの状態を確認します。プレイヤー側のレイキャストと人魂のレイキャストが互いを見つけた時に明かりが当たったと判定していることが分かると思います。
複数体居たとしても明かりが当たった個体だけが可視状態になります。
まとめ
Bakinで明かりを持った挙動、正確にはあたかも明かりを当てているかのような挙動とレイキャストの使用例をこの記事では提示できたかと思います。あくまで1例でありもっと良い方法もあると思います。
実際問題この記事の当たり判定だとプレイヤー側の明かりが何かのキャストに当たると同じカスタムイベントを持つキャストすべてがプレイヤーの方向を向いてしまうという欠点があります…
不可視の状態から可視にするという仕様なので見た目には現れないですが、不可視の仕様がなければ微妙かもしれません。その場合、マップやカメラ構成を工夫するかあるいはこの方法とは違う当たり判定を考える必要があります。
GUIを使うローコードプログラミングは発想力がすべてです。この記事がBakinでのゲーム制作に少しでも役に立てばと思い残しておきます。