弾を避けて自動で移動する方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
M

弾を避けて自動で移動する方法

#1

投稿記事 by M » 16年前

環境は、Windows XP で縦型トップビューシューティングを作っている者ですが。
Borland BCC Developerで、DXライブラリを使っています。

今、敵キャラが弾から自動的に避けるコードを作ろうとしています。
ですが、最後には、四隅に寄って移動ができなくなります。

過去ログを探してみたのですが、探し方が下手だったのか見つけれませんでした。
(もし、過去ログに似た質問があれば教えてください。)

まだ試した方法は、ある一定距離以内の弾すべてとのXとYの変化量の和を使って、
どちらに移動したら良いのか判定する方法だけですが、
この方法では、最後には必ず四隅に居座ってしまいます。

東方の「花見塚」のように、計算によって移動の制御を行うには、どうしたらよいでしょうか?
やはり、ベクトルを用いるのでしょうか?
スカラーが壁からの距離に反比例していて中心に向かったベクトルと、弾を避けるベクトルの和みたいな方法も
できますでしょうか?

もっと良い方法とか、考え方だけでも教えてくれれば助かります。

(ソースコード付きだともっと助かります。)
よろしくお願いします<(_ _)>

Dixq (管理人)

Re:弾を避けて自動で移動する方法

#2

投稿記事 by Dixq (管理人) » 16年前

私もどうすればいいか結構迷い、未だにどうすれば最善の方法かよくわかりませんが、
端に追いやられるという場合は、場所に優先順位をつけてやればいいように思います。

例えば何も無い時は中央に寄るとか、
今、右か左に避けないといけないという状況の時、右の方が中央に近かったら右に行くとか、
反対方向に行くとリスクが増えたとしても、身動きがとれなさそうになるほど端っこにいってしまう状況ならリスクを負ってでも反対方向に逃げるなど。
ただ弾幕ゲーには切り返しだとかその弾幕特有の性質を個別に判断して独特の避け方をする必要があるものもあり、
なかなか難しいですねぇ;

M

Re:弾を避けて自動で移動する方法

#3

投稿記事 by M » 16年前

なるほど、、、とにかく試行錯誤ということなのですねww
回答を参考に、がんばってみます。
ありがとうございます<(_ _)>

Justy

Re:弾を避けて自動で移動する方法

#4

投稿記事 by Justy » 16年前


>計算によって移動の制御を行うには、どうしたらよいでしょうか?

 東方の花見塚とやらは全く知らないので、この機能を何に使うのか少しみえない
ところがありますが、イカサマ(全てを見通せる視点)なしで計算したいと
いうことでしょうか?

 イカサマすればいつの時点でどこに弾があるのか全て完全に把握できるので
確実に避けられるルートを算出することは不可能ではありませんが、
それを使わないとなると、万能な方法というのがなくなるので、なかなか難しいですね。


 よく聞く話では学習型のシステムを作って、避け方を覚えさせるというのがあります。
 ただ、難易度が結構高いので結構大変です。


 あまりこの手の分野は専門ではないのですが、2種類ほど考えてみました。
 これは、弾の速度、大きさ、弾同士の密度などによって
アルゴリズムは変わってきたり、全く通用しなかったりすることを
念頭に置いておいてください。


 一番手っ取り早そうなのが、レナードジョーンズの
ポテンシャル関数などを使ってプレイヤーを誘導することです。

 弾と壁際に斥力系のパラメータを仕込んでおいて、プレイヤー近隣の空きスペースに
向かって引力系のパラメータを設定しておきます。
 状況によっては、先読み(1フレーム先の弾の位置を推測して)し、
それを考慮に入れてパラメータを変動させる必要があるかもしれませんが、
調整次第では、まぁまぁきれいに避けてくれそうな気がします。
 特に当たり判定が小さければ小さいほどうまくいくかもしれません。


 その他、まじめに計算する方法もあります。
 まず、プレイヤーが確認できる弾全てにおいて、そのフレームにおける
位置、移動ベクトル、加速ベクトルを記録します。

 で、その情報を元に1フレーム後の全ての弾の位置を予測し、今の位置との
ラインを引きます。

 このラインにぶつかると弾に当たったことになります。
 1フレームで移動可能な場所への移動と移動しなかった場合を検討し、
安全な位置の候補をピックアップし、その位置に対して移動コストやスコアをつけます。

 移動はとりあえず最初は8方向くらいで考えればいいかと思いますが、
1フレームの移動距離が長すぎる場合は、その半分とかの長さで移動を行うことも
候補に加えた方がいいかもしれません。

 次に、更に次のフレーム(2フレーム後)での全ての弾の位置を求めて
先に求めた1フレーム後の予測位置とのラインを引きます。

 先にピックアップした「避けられる位置」から移動したと想定して、
同じように判定し位置をピックアップし、スコアを更新します。

 これを一定フレーム分(何フレーム~何十フレーム)分繰り返し、
もっともスコアが高かったルートを採用しプレイヤーを移動させます。
 推測に推測を重ねているので、先のフレームにいけばいくほど
情報は劣化していきますので、何秒も先まで求める必要はないかと思います。

 これでこのフレームは終了します。

 次のフレームでは、最新の情報を元に同様の処理をしますが、
先に求めたルートを優先的に一定フレーム分調べて、問題なければ
そのルートを採用し、問題があれば新たなルートを調べます。

 こんな感じで繰り返していけば、まぁそれなりに避けられるとは思いますが、
・ 移動先候補のスコアの付け方など、難しいところが多々ある
・ プレイヤーの1フレームにおける最大移動量が小さすぎたり、或いは大きすぎたり、
 弾の早さとかが極端だったりする場合は、上記の処理ではうまくいかない可能性がある
・ 自然な人間的な移動を目指したりする場合は調整が大変
・ この手法そのものが処理に若干時間がかかるので、やっぱり調整は大変

 というデメリットもあるので、形になるまでには時間がかかるかもしれません。

Dixq (管理人)

Re:弾を避けて自動で移動する方法

#5

投稿記事 by Dixq (管理人) » 16年前

>>東方の花見塚

というのは、対戦型シューティングです。
ネットワークを使って他の人とシューティングで競う(ぷよぷ●でいうおじゃまぷよみたいなものを相手に与えて邪魔することも可能)ゲームです。
もし人と対戦しない時は、コンピュータと対戦出来ます。

私は大真面目に計算する方法で実装した事があります。
しかし次のフレームまでしか考えないアルゴリズムだとすぐに限界が来るので、30フレーム先まで考え、30フレームとも当たり判定ではなかったフィールドに行くよう考えました。
そこが30フレーム先まで一度も危険地帯にはならなかったかどうかは、
シューティングのフィールドの大きさである「380x360」の大きさの配列を用意し、当たり判定範囲が通った場所にフラグを立てていきました。
30フレーム先まで当たり判定を計算していき、最後までフラグがオフだった配列要素の場所が安全地帯です。

しかし「切り替えし」による避け方をしないと避けられない弾幕(連続で自分の方向へ飛んでくる弾幕で、一度追われている方向に大げさによけて弾を弾き付けないと反対方向へ逃げれない弾幕)だと敵の周りをクルクルまわるようになってしまい、
画面上まで来ると、突然出てきた弾にやられてしまうということになりかねませんでした。
そして、自分の周りに似たような安全地帯が出来た時、どちらの方向に行けばいいか決めるのも結構難しかったように思います。
なかなか大変ですね。

Justyさんの斥力の案いいですね。
何も無い時常に中央にいると不自然すぎるので、この辺の斥力はその場に応じて変化させるといいかもしれませんね。


こういうことを考えれば考えるほど花見塚の動きが美しく見えますね^^;

Justy

Re:弾を避けて自動で移動する方法

#6

投稿記事 by Justy » 16年前


>というのは、対戦型シューティングです
>花見塚の動きが美しく見えますね

 なんとなくイメージがつかめました。

 だとすると常に一定のアルゴリズムで動かすのではなく、
そのシーン(弾幕)にあった避け方をさせているのではないでしょうか。

 いくつかの避け方の判断アルゴリズムとパターンを持たせて、
このときはAの情報を元に避け、次のシーンではBのパターンで、時には
AとBを合わせた情報で避ける、とか。

 これなら「切り替えし」をしないと避けられない弾でも、適切に設定すれば
避けられますし。

M

Re:弾を避けて自動で移動する方法

#7

投稿記事 by M » 16年前

いろいろな回答ありがとうございます。
まず最初のステップとしては、
自分の周り八ヶ所から、弾のベクトルと、自分の移動ベクトルとのあたり判定で数カ所を除外すること。
になるとおもうのですが、

その八ヶ所にすべての弾の判定をすると、そこそこ負担がかからないでしょうか?
8*弾の数 の判定をすることになるということになるとおもうのですが、
まだ実装していないので、どの程度負担があるかわかりませんが、この数を減らすことは不可能でしょうか?

ちなみに弾の保存方法は、今のところ標準ライブラリの deque を使用しています。
(dequeって、誰も使っていないから、重いのかちょっと不安なんですけれどもw)

Dixq (管理人)

Re:弾を避けて自動で移動する方法

#8

投稿記事 by Dixq (管理人) » 16年前

なるほど、なかなか難しそうですね^^;

確かに撃って来る弾の規則はその弾幕によって予めわかっているわけですから、
ある意味いかさまっぽく内部でそれにあったパターンで避けるようにすればなんとかなりそうですね。

こういうAI的なプログラムってきちんと動けば感動しますよね~w

M

Re:弾を避けて自動で移動する方法

#9

投稿記事 by M » 16年前

とりあえず、学んだことを生かして実際に試してみて、また困ったら
今度は、もっと具体的な質問を持ってきて訪問してみようと思います。
皆さん、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る