Heliodor 2020/11/21 19:45

袋小路から脱出したい

何度か小出しにしている動画やテスト版で皆さんお気づきかもしれませんが、あやかし紅白戦ではプレイヤーが操作するキャラクターの他にもう一人仲間がいます。


某時空戦闘機のオプションや、よくあるRPGの仲間キャラみたいにキッチリ後を着いて来る仲間なら簡単なのですが、本作の仲間は勝手に動き回りながらプレイヤーの後についてきて、時々戦ってくれたりするようになっています。

しかしそれが裏目に出て、袋小路の奥に敵がいるときプレイヤーそっちのけで袋小路に入り込んでいき、敵と戦っている間にプレイヤーを見失い、その後プレイヤーの場所に戻りたいのに地形にハマって出られなくなる……という悲しい事故が頻繁に発生しました。

理由は簡単で、仲間は単純にプレイヤーのいる方向へ移動するという実装になっていたからです。


壁の向こう側にプレイヤーがいるような状況になると、壁を迂回するという発想ができずに壁に向かって歩き続けてしまうんですね。

まあ、これはなにも仲間に限ったことではなく、プレイヤーを狙う敵でもそうなんですが……。

背の低い障害物ならばただジャンプするだけで乗り越えられるのですが、完全な壁だとそうもいかないですね。(ヴィータ大脱出の敵は、障害物を検出したらとりあえず前ジャンプしていた)





ところで、以前見下ろし型のマップを使ったゲームを実験で作ったことがあったのですが、それはプレイヤーや敵が自由に壁を破壊できるシステム(ボ○バーマンみたいに)だったので、時間経過に従ってどんどん地形が変化していました。
そのような状況で敵がプレイヤーまで到達するようにするってのが結構大変でした。プレイヤーに向かってまっすぐ進むだけではまず到達できないですからね。

その時は A*(A-star: エースター)という経路検索方法を使って、自動的にプレイヤーに到達する経路を見つけ出すということをやっていました。
https://ja.wikipedia.org/wiki/A*
(※すみません、URLのアスタリスクが勝手に消えてしまうので、最後の全角「*」を半角で入力し直して下さい)



以下ちょっと細かい話

まずマップを細かい正方形のセルに分割して(ボ○バーマンで言うところの1ブロック=1セル)、すべてのセルの中心にノード(点)を置きます。つぎに、各ノードとその上下左右のノードをつなぐエッジ(通路)を、作成しておきます。

こうして作ったデータには「点がどの場所にあるか」といった位置の情報は全く含まれておらず、「どの点とどの点が繋がっているか」という情報だけがあります。これを無向グラフと言います。「登れないけど飛び降りることはできる」みたいに一方通行なエッジが存在するものは有向グラフです。

後は、現在地ノードからどのエッジをたどって目的地ノードに行くか、という問題になります。

まず地形状態に応じて各エッジの通過コストを設定します。
安全なノード同士を結ぶエッジはコストを低く設定し、危険なノード、通行不可能ノードを結ぶエッジはコストを高くするわけです。
(ノードを「国」や「都市」、エッジを「路線」、コストを「リスク」に言い換えればわかりやすいかと思います。安全な都市同士を結ぶ路線はリスクが低いが、危険な都市とつながっている路線はリスクが高いってことです)

このコストは、キャラクターによって変えることが出来ます。
(逆に言うと、ここでキャラクターの個性を表現する事が出来ます)

「破壊不可能なブロックでも破壊できる」みたいな敵にとっては、破壊不可能ブロックの通過コストはそれほど高くありませんし、「アイテムを好んで取得する」キャラクターにとっては、アイテムが存在する通路よりも何もない通路のほうがコストが高くなります。
好戦的なキャラ、逃げ回るキャラなんかも作れますね。
「プレイヤーの近くにあるノードほど通過コストが高い」みたいにすれば、プレイヤーから遠い場所を好んで通過するような移動をさせることができます。
(地形は常に変動しているので、極端な場合はこれらのコストを毎フレーム再設定することになります)


このようにして作ったデータ(重み付き無向グラフ)を A* に処理させると、目的地までたどり着くために最もコストが少なくなるようなノード配列(つまり経路)を得ることができます。

……と、まあこれはボ○バーマンのように地形が正方形単位で構成されていれば簡単にできたことなんですが、あやかし紅白戦のように正方形などまるで関係のない地形を組んであると、ちょっとやりにくいんですよね。
それに地形がそこまで複雑でないので、マップを細かいセルに分割してどうのこうのって方法は役不足(本当の意味で)かなあと。


そういう時に割と単純かつ効果的なのは、マップ上にナビゲーション用のマーカーを設置しておく方法です。
マップエディタでも何でもよいので、マップ上にマーカーをばんばん置いていきます。
マーカーを置くときのルールは単純で

1.マップ上のどの位置(プレイヤーが侵入できる位置)からも、最低一つのマーカーが見える
2.マーカーからは、最低一つの別のマーカーが見える

です。このマーカーはゲーム中では一切表示されません。でもキャラクターたちはマップのどこにマーカーがあるかを知っています。
プレイヤーを見失ったキャラクターは、とりあえずマーカーをたどっていけば、壁にぶつかる事なくプレイヤーが見えるところまで移動することができるってことです。
(この経路検索においては、移動コスト=マーカー間の距離になります)




ちなみにこの経路検索、なにも移動のためだけではないんですよ。
「音」の経路を設定するって使い方もあります。
移動するための経路検索のときと同様に、マップ上にノードとエッジを配置して、ノード間の距離(エッジの長さ)と障害物(音に対する障害物)によるコストを設定します。
ただし、この時のコストはキャラクターの移動コストではなく、音がよく通るかといったコストです。
例えば何もない場所や金網など音が素通りの場所は低コスト、閉じている扉や窓は中コスト、壁は高コストみたいに。
で、マップのどこかで音が鳴った時に、その音がプレイヤーまでどのような経路でたどり着くかってのを調べるんですよ。

そうすると、例えばプレイヤーの目の前の壁の向こう側で敵が吠えたとして、その音は壁からではなく開いている扉から聞こえてくる ってことができるようになります。
(まあ、これはガチ3Dなゲームの話なので本作にはほとんど関係無いんですが)


障害物関係無く効果音が聞こえるととてもやかましけど、それがゲーム性になってるケースもある


いつも思うことですが、普段当たり前のようにゲームで体験していることでも、裏では結構大変な思いをしているんですよね。

おそらくゲーム製作者あるあるだと思うのですが、ゲーム楽しむ以前に「うわ、これ作るの大変そう」とか「どうやってるんだこれ」って考えてしまいます。

かつてはただ遊んでいるだけだった、大昔のゲームを最近改めて見たときも同じように思うことがあります。


単純な物量は分かりやすいんですけど、実際に自分で作ってみて初めて分かる謎技術の恐ろしさ。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

記事のタグから探す

月別アーカイブ

限定特典から探す

記事を検索