ドリフトっぽい動きをするミサイル

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

ドリフトっぽい動きをするミサイル

#1

投稿記事 by 珈琲 » 10年前

シューティングゲームでミサイルを作ったのですが、いまいち動きに納得できません。
敵に向かって飛んでいき、しっかり命中したのでミサイルとしては機能しているのですが、単純すぎて面白く無いので、慣性っぽい動きを載せた挙動にしようと思っているのですが
どう計算すればいいのかというのと、どのような考え方をすればいいのか、言ってしまえば全部わかりません。

今までに作ったミサイルは、
「敵に方向を常に向きながら、ミサイルの向いてる方向に前進していればいつか敵に当たる」 ※対象物よりミサイルの速度が1倍~2倍範囲内の場合
という方法です。
敵への方向ベクトルとミサイルの向いてる方向の外積を軸にして、毎フレーム一定角度づつ向きを合わせればいつかあたります。

今回質問したいのは、
「現在の移動ベクトルにミサイルの向いてる方向に発生する推力ベクトルを合成して、なおかつ敵に当たる」
という方法です。

車でいうなら、
車から見て目の前を通り過ぎるように移動する対象物に、加速しつつドリフトしながら対象物に車の横腹をぶつけるイメージです。

空気抵抗や摩擦は考えませんが、移動ベクトルの大きさに上限は設けます。
また、発射直後のミサイルの移動ベクトルは、ミサイルを発射した親の移動ベクトルを引き継ぎます。



自分の予想では、
 まず対象物が突然その座標に停止し、ミサイルは既に対象物の方向へ向いてると仮定して、
  対象物とミサイルの距離、ミサイルの加速度から衝突する時間を計算します。
 次にその衝突時間分、対象物の移動速度と方向ベクトルを見て現在の座標から先読みします。
 衝突予測時間の対象物の座標がわかったので、進行方向ベクトルがそこへ向くよう、
  ミサイルの向きを操作して、推力方向を操作し、間接的に進行方向ベクトルを操作する。

という手順を毎フレーム行えば、正確ではないにしろ実現できるかと思うのですが、
問題なのは
「進行方向ベクトルがそこへ向くよう、ミサイルの向きを操作して、推力方向を操作し」
の部分です。
推力ベクトルによって変化し続ける進行方向ベクトルから、推力ベクトルを回転させる最適な方向をどのように計算したらいいでしょうか?


自分にしかわからないような質問・説明になってるかもしれません

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#2

投稿記事 by usao » 10年前

何をしたいのかがいまいちわかりません.簡潔に言うと

 今まで作ったミサイル → フレームごとに向いている方向へ一定距離だけ進む
 これから作りたいもの → フレームごとに向いている方向へ一定量だけ加速する

ということですか?

・とりあえず加速度の概念を単純に導入(向きの操作はそのままに)したらどうなるのですか? 何が不十分なのですか?
・「最適な方向」とは何ですか?
 (相手が等速直線運動している仮定の元で,ということであれば
  実際の相手は仮定を覆すだろうから,仮定の上での何らかの厳密さを追い求めても無駄な気もしますが)
・その他,そのフレームは加速しないという選択肢を取れるのか? とか,旋回できる角度に制限があるのか? とかいう条件にもよりそう

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#3

投稿記事 by usao » 10年前

ミサイルの向いている方向に進む/加速する のではなくて

運動は単純化:
各フレームで任意の方向に加速できる点とみなして 計算する,
例えば,
・ミサイル現在位置→ターゲット現在位置 方向
とか
・ミサイル現在位置→ターゲットの数フレーム後予測位置 方向
に毎フレーム加速度を加える
 ↓
表示的なミサイルの向きは常に
・ミサイルから見たターゲットの方向
とか
・(ミサイル現在速度方向+ミサイルから見たターゲットの方向)/2
とかにしてしまえばドリフトっぽく見えないことも無いと思いますがそれだとダメでしょうか.

コード:

        ・・*Tgt
      ・
    ・
  ・
 ・
 ・
・
・ミサイルの運動軌道
・
・
・
▲自機

 ↓表示↓

        --*Tgt
      -
    /
  /
 /
 / ←横滑りしているように見える
/
/ミサイルの描画向き
 /
 /
 /
▲自機
#加速度はうまくやらないとターゲットの衛星軌道にのっちゃったりしますが,それはそれとして.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#4

投稿記事 by softya(ソフト屋) » 10年前

やりたいのは、こういうことでしょうか?
「Missile」
http://homepage1.nifty.com/kaneko/missile.htm
※ 亡くなられた 「金子 勇」氏 のサイトです。ご冥福をお祈りいたします。

「比例航法のまとめ」
http://raptorial.jp/stg/doc.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#5

投稿記事 by 珈琲 » 10年前

usao さんが書きました:何をしたいのかがいまいちわかりません.簡潔に言うと

 今まで作ったミサイル → フレームごとに向いている方向へ一定距離だけ進む
 これから作りたいもの → フレームごとに向いている方向へ一定量だけ加速する

ということですか?
はい、そうです。
usao さんが書きました: ・とりあえず加速度の概念を単純に導入(向きの操作はそのままに)したらどうなるのですか? 何が不十分なのですか?
命中率が著しく落ちます。
そのために、soft屋さんも提示してくれた比例航法を使おうと思います。(No1の対象物との距離と自分の速度から到達時間云々の行)
usao さんが書きました: ・「最適な方向」とは何ですか?
 (相手が等速直線運動している仮定の元で,ということであれば
  実際の相手は仮定を覆すだろうから,仮定の上での何らかの厳密さを追い求めても無駄な気もしますが)
usao さんが書きました: ・その他,そのフレームは加速しないという選択肢を取れるのか? とか,旋回できる角度に制限があるのか? とかいう条件にもよりそう
移動ベクトルの大きさには制限があります。加速度と移動ベクトルの和を計算した後、最高速度にに大きさを縮めたいと思っています。
また、旋回角度の制限は考えていません。ただ、他の部分が完成して、実際に試してみて面白い動きをするのならば、それで行こうと思います。
基本的には制限しない方向で行きたいと思います。

珈琲

Re: ドリフトっぽい動きをするミサイル

#6

投稿記事 by 珈琲 » 10年前

usao さんが書きました:ミサイルの向いている方向に進む/加速する のではなくて

運動は単純化:
各フレームで任意の方向に加速できる点とみなして 計算する,
例えば,
・ミサイル現在位置→ターゲット現在位置 方向
とか
・ミサイル現在位置→ターゲットの数フレーム後予測位置 方向
に毎フレーム加速度を加える
 ↓
表示的なミサイルの向きは常に
・ミサイルから見たターゲットの方向
とか
・(ミサイル現在速度方向+ミサイルから見たターゲットの方向)/2
とかにしてしまえばドリフトっぽく見えないことも無いと思いますがそれだとダメでしょうか.
ミサイルが追いかける対象物は結構な速度で移動しています。
特に純粋追尾航法ですと、対象物がどんなに遅くてもミサイルは必ず対象物の後ろにつく(らしい)です。
画像
一定の速度で前進する純粋追尾航法ミサイルは実際に手元で再現できるのですが、やはり命中率は悪いです。
当たり判定でどうにかなる部分もあるのですが、今まで以上に高速で敵を負うミサイルを作りたいので、
後出しみたいで申し訳ありませんが、純粋追尾航法は避けたいです。

珈琲

Re: ドリフトっぽい動きをするミサイル

#7

投稿記事 by 珈琲 » 10年前

softya(ソフト屋) さんが書きました:やりたいのは、こういうことでしょうか?
「Missile」
http://homepage1.nifty.com/kaneko/missile.htm
※ 亡くなられた 「金子 勇」氏 のサイトです。ご冥福をお祈りいたします。

「比例航法のまとめ」
http://raptorial.jp/stg/doc.html
このサイト、Winnyの作者のサイトだったんですか、知りませんでした。。
やりたいのは、それです。
たしか実行中、Aキーでミサイル視点になれた気がします。
現在の進行方向を調整するために、ミサイルの方向(推力)を回転させる、という意味でそのまんまです。
知りたいのは、ミサイルをどの方向にどれぐらい回転させれば、進行方向を対象物の座標に向けられるか、の算出式です。

珈琲

Re: ドリフトっぽい動きをするミサイル

#8

投稿記事 by 珈琲 » 10年前

soft屋さんが提示してくれた比例航法と違うのは、
ミサイルが加速し続ける(上限あり)というのと、
進行方向とミサイルの向きが別にあるという所です。

もしかしてゲームループ内でやるような負荷の処理ではないのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#9

投稿記事 by softya(ソフト屋) » 10年前

珈琲 さんが書きました:soft屋さんが提示してくれた比例航法と違うのは、
ミサイルが加速し続ける(上限あり)というのと、
進行方向とミサイルの向きが別にあるという所です。

もしかしてゲームループ内でやるような負荷の処理ではないのでしょうか?
そのぐらいは例で紹介しているサイトに書かれていないだけで、ちゃんとやっていると思います。
と言うか3Dで空戦ものを扱うなら、加速度ベクトル(ミサイルの向き)、運動ベクトル(進行方向)などちゃんと計算しないとリアルっぽくならないですよって前に書いた気が。
【補足】
理解すべきは運動物理とベクトルの関係です。処理的には重い処理ではありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#10

投稿記事 by usao » 10年前

>知りたいのは、ミサイルをどの方向にどれぐらい回転させれば、進行方向を対象物の座標に向けられるか、の算出式です。
比例航法というやつは,「(未来に相手が要るだろう方向に)いくらか余計にミサイルの向きを回転させる」という話だと思いますけど(偏差射撃というか)
示されたリンク先に式まで書かれているのですが,それではダメなのでしょうか.
>どれぐらい
がちょうどいいのかは,裁量次第なのだと思いますが.とりあえず3次元だと
・前フレームでのミサイル位置 → 前フレームでのターゲット位置
・現フレームでのミサイル位置 → 現フレームでのターゲット位置
なる2つの方向ベクトルにより張られる面を考えて,その面上でのθを使えばいい…のかな.
(回転軸は面の法線)


>特に純粋追尾航法ですと、対象物がどんなに遅くてもミサイルは必ず対象物の後ろにつく(らしい)です。
最終的に対象物を後ろから追いかける形になるのは
私の経験上,ゲームでのミサイルとして自然な気がしますが,そうならないようにしたいということなのでしょうか.
#比例航法というやつでも後ろから追いかける形になりそうに想像しますが違うのだろうか?
 慣性がつくなら余計そうなりそうです.相手の将来の動作は未知なのだし.

珈琲

Re: ドリフトっぽい動きをするミサイル

#11

投稿記事 by 珈琲 » 10年前

usao さんが書きました:>知りたいのは、ミサイルをどの方向にどれぐらい回転させれば、進行方向を対象物の座標に向けられるか、の算出式です。
比例航法というやつは,「(未来に相手が要るだろう方向に)いくらか余計にミサイルの向きを回転させる」という話だと思いますけど(偏差射撃というか)
示されたリンク先に式まで書かれているのですが,それではダメなのでしょうか.
>どれぐらい
がちょうどいいのかは,裁量次第なのだと思いますが.とりあえず3次元だと
・前フレームでのミサイル位置 → 前フレームでのターゲット位置
・現フレームでのミサイル位置 → 現フレームでのターゲット位置
なる2つの方向ベクトルにより張られる面を考えて,その面上でのθを使えばいい…のかな.
(回転軸は面の法線)
そうですね、そこまでが比例航法でして、
それに慣性(運動ベクトル)を載せようとした時の回転値が知りたいです。
「(未来に相手が要るだろう方向に)いくらか余計にミサイルの向きを回転させる」
を言い換えるならば
「未来に相手が要るだろう方向に進行方向を合わせるためにミサイルの向きを回転させる」
という感じです。
usao さんが書きました: >特に純粋追尾航法ですと、対象物がどんなに遅くてもミサイルは必ず対象物の後ろにつく(らしい)です。
最終的に対象物を後ろから追いかける形になるのは
私の経験上,ゲームでのミサイルとして自然な気がしますが,そうならないようにしたいということなのでしょうか.
私はエースコンバットAHのミサイルと観察してみたのですが、前から来るミサイルは前にあたりますし、横からくるミサイルは横にあたります。
後ろから発射された、進行方向の軸が重なるミサイルが当たりやすいという印象はあります。
usao さんが書きました: #比例航法というやつでも後ろから追いかける形になりそうに想像しますが違うのだろうか?
 慣性がつくなら余計そうなりそうです.相手の将来の動作は未知なのだし.
比例航法は文字通り衝突時の敵機の座標を予測します。
さっきの画像元のサイトに画像がありました↓
画像

>慣性がつくなら余計そうなりそうです
慣性が乗せると確かに後手後手に回るため、後ろにつくようになると思います。
そうならないために、慣性をも含めた計算式で通常の比例航法の回転率計算とは違う方法が必要だと思いました。

[hr]
説明がヘタクソですいません。
自分なりに無駄な情報を省いてみると、
MPos //ミサイルの座標(x,y,z)
MIne //ミサイルの運動(ベクトル)
MDir //ミサイルの向き(単位ベクトル)
MAcc //ミサイルの加速度(スカラ)

EFPos //敵の未来座標(x,y,z)
の5つの情報が現在わかっていて

・毎フレームMIne分MPosに加算されるけば
//↓加速と慣性の表現で、比例航法とは別の計算なはず。 
・毎フレーム(MDir * MAcc)分MIneに加算される
という条件があった時に

MIneを単位化したベクトル == (EFPos - MPos)を単位化したベクトル
を満たすMDirの値が知りたい、

という感じです。
EFPosを算出して、MPosを引けば未来座標へのベクトルがわかるので、
それをMDirに代入するまでが比例航法だと思います。

この時のMDirを求める式がわからなくて・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#12

投稿記事 by softya(ソフト屋) » 10年前

とりあえず比例航法の計算方法で角度は計算して、その上に運動ベクトルの合成もしてみて、その実装状態の動きから考えてみてはどうでしょうか?
私もどうやれば、お望みの動きに成るか分かりません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#13

投稿記事 by usao » 10年前

>MIneを単位化したベクトル == (EFPos - MPos)を単位化したベクトル
>を満たすMDirの値が知りたい、

うーん,果たしてその説明どおりのものを求めたとして,自然に見えるのかどうか…

ちょっと図の貼り方がわからないので想像していただきたいのですが…
とりあえず想像しやすいように2次元だとして
(1)点MPosから,目的の方向(EFPos-MPos)を示す直線を引っ張る.
(2)点MPosから,前フレームでのミサイル速度ベクトルをあらわす矢印を引っ張る(向きが速度方向で長さが速度の大きさの線分)

やろうとしていることは,Mlneを
Mlne = Mlne_prev + MDir * MAcc
として更新したときに,Mlneが(1)で引いた直線上にぴったり重なるような MDir を求めることに相当すると思います.
更新の様子を図示すると,
(2)の矢印の先端を中心とした半径MAccの円を書いて,この円と(1)の直線との交点Pを求め,
MDir = UnitVectorOf( P - (2)の矢印の先端 )
とすることに相当すると思います.
当然,解がない場合もありますが,とりあえず円と直線が接する状態を考えてみれば,MDirは直線と垂直な方向となります.
仮に次フレームのEFPosに変化が無かったら,次のフレームではミサイルの向きMDirは直線に沿う方向にせねばなりません.
これをこのまま実装したら,
なんかミサイルが1フレーム間で90度回転したりすることになっちゃったりしそうですが,大丈夫なのでしょうか?(挙動として)

珈琲

Re: ドリフトっぽい動きをするミサイル

#14

投稿記事 by 珈琲 » 10年前

ありがとうございます。

疑問が少しあります。

>(2)の矢印の先端を中心とした半径MAccの円を書いて,この円と(1)の直線との交点Pを求め,
>MDir = UnitVectorOf( P - (2)の矢印の先端 )

矢印の先端を中心とした円と直線の交点とはどのような意味があるのでしょうか?


>なんかミサイルが1フレーム間で90度回転したりすることになっちゃったりしそうですが,大丈夫なのでしょうか?(挙動として)
うーん
やっぱり1フレームで回転する制限をかけたほうがよさそうですね

たいちう
記事: 418
登録日時: 13年前

Re: ドリフトっぽい動きをするミサイル

#15

投稿記事 by たいちう » 10年前

> 一定の速度で前進する純粋追尾航法ミサイルは実際に手元で再現できるのですが、やはり命中率は悪いです。
> 当たり判定でどうにかなる部分もあるのですが、今まで以上に高速で敵を負うミサイルを作りたいので、
> 後出しみたいで申し訳ありませんが、純粋追尾航法は避けたいです。

昼間ROMってて気になったこと。

「純粋追尾航法」だから命中率が悪いのではなく、
「純粋追尾航法」を実装できていないから命中率が悪いのでは?

命中率が悪いというプログラムをここに載せたらアドバイスがもらえそうではないですか?

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#16

投稿記事 by GRAM » 10年前

よくわからないですが、とりあえず適当に書いてみました。こんな感じはどうなんでしょうか。
クリックするとある程度ランダムな初速度でミサイル(緑)が
ターゲット(青)に向かって飛んでいきます。
(単純な計算の割には結構命中してるようにも見えます)

●●航法とかは全然詳しくないので、以下のように考えてプログラミングしました。
①ミサイルの最適な航行経路を求めるのは可能かもしれないが、ぱっと考えた感じ困難
(というのもミサイルは2次元あるいは3次元的に回転しかつ加速し、またターゲットは回避行動をとるのが普通と思われるため)
②ミサイルとターゲットとの衝突時刻をある程度予測することは可能
③衝突予測時刻から求めた予測衝突座標に向かって飛翔し、予測衝突座標を絶えず更新するのが妥当か
④予測衝突時刻はターゲットとの相対位置ベクトルと、ターゲットと自分の相対速度、自分の加速度から求める
具体的には高校1年生でならうと思われる等加速度運動の公式で近似します

|St-Sm| = |(Vm-Vt) |* t + (1/2)*|A|t2
S:位置ベクトル V:速度ベクトル A:ミサイルの加速度ベクトル

後は二次方程式をt>0の下で解いて目標座標へ適当に追尾するだけです
⑤角速度に制限を設けないとあまりにも凶悪なミサイルができてしまったので、最大10°/フレームの制限を設けました

添付ファイルでは予測される衝突座標は赤丸で示されます。
ミサイルは毎秒0.5ピクセル/フレーム^2 だけ加速されます。

自分の書きやすいようにして書いたため必要とあれば修正してコードを掲載します。
問題があればどこをどう変えたらいいか教えてください。

(追尾困難と思われる場合はあきらめますが仕様です。具体的にはミサイルの前方視野180°以内にターゲットがいないとあきらめます)
DxTest.rar
(542.28 KiB) ダウンロード数: 133 回

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#17

投稿記事 by usao » 10年前

疑問が少しあります。

>(2)の矢印の先端を中心とした半径MAccの円を書いて,この円と(1)の直線との交点Pを求め,
>MDir = UnitVectorOf( P - (2)の矢印の先端 )

矢印の先端を中心とした円と直線の交点とはどのような意味があるのでしょうか?
説明を読んだ限りだと,
「ターゲット予測位置方向に常にミサイルの速度ベクトル(Mlne)が向いている状況をキープする」
ことが,やりたいことなのだと思いました.

仮に現フレームでミサイルが「加速しない」とすれば,ミサイルの位置は前時刻の速度(Mlne_prev)分だけ進みますよね.
その位置が(2)の矢印の先端です.
その移動方向が(1)の直線に沿っていないから,どうにかして速度を変更して直線に沿うようにしたい
(Mlne_prev に加速度を加えて Mlne にする)
という話.

簡単に考えるために移動前のミサイル位置MPosを原点と見なしましょう.
そうすれば矢印の先端の座標はMlne_prevですよね.
加速後の現在フレームでの速度ベクトル Mlne をMlne_prevと同様にMPosから矢印で書いたら,その先端の座標がMlneです.
この座標Mlneが(1)の直線上に乗っていなければなりません. ...(A)
で,その座標Mlneとは,座標Mlne_prevからMAccだけいずれかの方向に離れた場所 です.
常にMAccだけ加速するので.
だから,座標Mlneが取り得る座標は,座標Mlne_prevを中心とした半径MAccの円周上ということになります. ...(B)
条件(A)と(B)を共に満たすMlneは,円と直線の交点です.

……だと思います.

珈琲

Re: ドリフトっぽい動きをするミサイル

#18

投稿記事 by 珈琲 » 10年前

たいちう さんが書きました:> 一定の速度で前進する純粋追尾航法ミサイルは実際に手元で再現できるのですが、やはり命中率は悪いです。
> 当たり判定でどうにかなる部分もあるのですが、今まで以上に高速で敵を負うミサイルを作りたいので、
> 後出しみたいで申し訳ありませんが、純粋追尾航法は避けたいです。

昼間ROMってて気になったこと。

「純粋追尾航法」だから命中率が悪いのではなく、
「純粋追尾航法」を実装できていないから命中率が悪いのでは?

命中率が悪いというプログラムをここに載せたらアドバイスがもらえそうではないですか?
失礼しました、現段階での純粋追尾航法のコードです
エフェクトなどのコードは省いてます。

コード:

if(Exist){
	//ミサイルの接触処理
	//ミサイルに触れたオブジェクトがミサイルの持ち主以外の場合、Hitとする。(発射直後の暴発を防ぐため)
	for(size_t i=0;i<PendingDamageList.size();i++){
		if(PendingDamageList[i]->Owner!=Owner){
			Hit=true;
		}
	}
	PendingDamageList.clear();//ダメージ処理終わったのでクリア


	if(LifeTime>300){//寿命
		Hit = true;
	}

	Damage.Direction = Direction;

	LifeTime++;

	if(!Hit){//ヒットしていない時

	//移動処理

		//敵へ直で向く直座標角度
		VECTOR EDirection = VNorm(VSub(TargetObject->GetPosition(),Position));

		//その軸
		VECTOR RotAxis = VNorm(VCross(EDirection,Direction));


		AxisZ = VNorm(ReactionQuaternion(RotAxis,Direction,DX_PI_F/90));//敵の方向に2度づつ回転し続ける

		Position = VAdd(Position,VScale(Direction,30.0f));	//実際に移動



		MATRIX PredeterminedAngle = MGetRotVec2(VGet(0,0,1.0f),Direction);

		//行列を作成し、角度→座標の順でモデルに適用する
		MATRIX PredeterminedMatrix = MGetIdent();

		PredeterminedMatrix = MMult( PredeterminedMatrix, PredeterminedAngle );

		PredeterminedMatrix = MMult( PredeterminedMatrix, MGetTranslate(Position) );

		Model->SetMatrix(PredeterminedMatrix);

	////
	}else{
		//爆発などのオブジェクトを作ります
		//存在フラグをfalseにし、削除されるのを待ちます。
		Exist=false;
	}
}

珈琲

Re: ドリフトっぽい動きをするミサイル

#19

投稿記事 by 珈琲 » 10年前

31行目
AxisZ = VNorm(ReactionQuaternion(RotAxis,Direction,DX_PI_F/90));//敵の方向に2度づつ回転し続ける

Direction = VNorm(ReactionQuaternion(RotAxis,Direction,DX_PI_F/90));//敵の方向に2度づつ回転し続ける
こうでした。

珈琲

Re: ドリフトっぽい動きをするミサイル

#20

投稿記事 by 珈琲 » 10年前

GRAM さんが書きました: ●●航法とかは全然詳しくないので、以下のように考えてプログラミングしました。
①ミサイルの最適な航行経路を求めるのは可能かもしれないが、ぱっと考えた感じ困難
(というのもミサイルは2次元あるいは3次元的に回転しかつ加速し、またターゲットは回避行動をとるのが普通と思われるため)
②ミサイルとターゲットとの衝突時刻をある程度予測することは可能
③衝突予測時刻から求めた予測衝突座標に向かって飛翔し、予測衝突座標を絶えず更新するのが妥当か
④予測衝突時刻はターゲットとの相対位置ベクトルと、ターゲットと自分の相対速度、自分の加速度から求める
具体的には高校1年生でならうと思われる等加速度運動の公式で近似します

|St-Sm| = |(Vm-Vt) |* t + (1/2)*|A|t2
S:位置ベクトル V:速度ベクトル A:ミサイルの加速度ベクトル

後は二次方程式をt>0の下で解いて目標座標へ適当に追尾するだけです
⑤角速度に制限を設けないとあまりにも凶悪なミサイルができてしまったので、最大10°/フレームの制限を設けました

添付ファイルでは予測される衝突座標は赤丸で示されます。
ミサイルは毎秒0.5ピクセル/フレーム^2 だけ加速されます。

自分の書きやすいようにして書いたため必要とあれば修正してコードを掲載します。
問題があればどこをどう変えたらいいか教えてください。

(追尾困難と思われる場合はあきらめますが仕様です。具体的にはミサイルの前方視野180°以内にターゲットがいないとあきらめます)
DxTest.rar
実際に自分の環境でやってみました、が、||の扱いが・・・

コード:

//			|St-Sm| = |(Vm-Vt) |* t + (1/2)*|A|t2

			VECTOR Vm =Inertia;
			VECTOR Vt =TargetObject->GetInertia();
			int t =LifeTime;
			VECTOR A =VScale(AxisZ,2);//AxisZ = ミサイルの向いてる方向

			VECTOR CollisionPredictionPosition = VAdd( VScale(VSub(Vm,Vt) , t) , VScale(VScale(A,(1/2)),t*t));

			DrawSphere3D(CollisionPredictionPosition,5,10,GetColor(255,0,0),5213,1);
GRAM さんが書きました: 自分の書きやすいようにして書いたため必要とあれば修正してコードを掲載します。
問題があればどこをどう変えたらいいか教えてください。
比例航法としてはこの実行ファイルであってると思います。
それに、usaoさんの
>「ターゲット予測位置方向に常にミサイルの速度ベクトル(Mlne)が向いている状況をキープする」
という状況を加えたいです。


でも比例航法も1人で再現できないようじゃ厳しいか(´・ω・`)・・・

珈琲

Re: ドリフトっぽい動きをするミサイル

#21

投稿記事 by 珈琲 » 10年前

比例航法ではなく純粋追尾航法で、
敵の現在位置に向かって進み続けるというコードです。
恐らく回答してくれた方々が予想していた慣性とはちょっとずれてると思います。。。

コード:


//敵へ直で向く直座標角度
VECTOR EDirection = VNorm(VSub(TargetObject->GetPosition(),Position));

//その軸
VECTOR RotAxis = VNorm(VCross(EDirection,AxisZ));

//AxisZ = VNorm(ReactionQuaternion(RotAxis,AxisZ,DX_PI_F/60));

AxisZ = EDirection;

VECTOR Thrust = VScale(AxisZ,1.3);//推力

Inertia = VAdd(Thrust,Inertia);//慣性っぽい何か

Position = VAdd(Position,Inertia);

”移動方向を敵の方向に向ける”ではなく”ミサイルの向きを敵の方向に向ける”という処理なので当然あたりません。。


”ミサイルの向きを敵の方向に向ける”
という処理を
”移動方向を敵の未来位置方向に向ける”
に変える

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#22

投稿記事 by softya(ソフト屋) » 10年前

敵というかターゲットの移動ベクトルが分かっているのなら未来位置は簡単に計算できますが、それではダメなのでしょうか?
あとミサイルが敵の方向を向けば後方から追いついてやがては必ず当たります。 
※ 当たらないとしたらミサイルが敵機より遅い場合です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#23

投稿記事 by usao » 10年前

それに、usaoさんの
>「ターゲット予測位置方向に常にミサイルの速度ベクトル(Mlne)が向いている状況をキープする」
という状況を加えたいです。
おっと,なんかこの文面だけを見ると まるで私がそういうことを提唱しているかのように見えちゃいそうなので
念のため書いておきますが,
私は単に「本当にそれがやりたいのならば」「その計算内容はNo13およびNo17のようなことになりそうですよ」
と言っているだけです.(内容が合ってるか間違っているかは別として)
#さらに,状況次第では不自然な動きになるのではないかと想像しています.なんとなくですが.

で,仮に計算方法の内容が合っていれば
3次元ならば円を球に置き換えるだけの話ですから,やりたければやってみればいいのでは?
交点が無い場合でも適当にやればいいでしょう.例えば球と直線の最近点を使うとか.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#24

投稿記事 by softya(ソフト屋) » 10年前

とりあえず適当航法のプログラム。
これをベースにホーミングを討論するのはどうでしょうか?
※ 出来れば、こういうのを先に作ると話が進みやすい&デバッグしやすいのでご自分でやるときでも作るべきものです。

【補足】バグっているみたいで。右回転しかしません(^_^;)。そこも含めて適当ということで。

コード:

#include "DxLib.h"
#include "math.h"

#define MARK_MAX (256)

//	共通描画
void Draw(VECTOR pos,VECTOR mark[MARK_MAX],int size,int r,int g,int b)
{
	//	マーク表示
	for( int i=0 ; i<MARK_MAX ; i++ ){
		if( mark[i].x != 0 && mark[i].y != 0 ) {
			float bright = (float)(MARK_MAX - i) / (float)MARK_MAX;
			DrawPixel( mark[i].x, mark[i].y, GetColor(r*bright,g*bright,b*bright) );
		}
	}
	
	//	表示
	DrawCircle( pos.x, pos.y, size, GetColor(r,g,b), TRUE );
}

//	共通マーク処理
void SetMark(VECTOR pos,VECTOR mark[MARK_MAX])
{
	//	マーク保存
	for( int i=MARK_MAX-1 ; i>=1 ; i-- ){
		mark[i] = mark[i-1];
	}
	mark[0] = pos;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

	//	初期値
	VECTOR targetPos = VGet(320,400,0);
	VECTOR targetVec = VGet(-2,0,0);
	VECTOR targetMark[MARK_MAX] = {{0}};
	MATRIX targetRotMatrix = MGetRotZ( 3.141592 / 180.0 * 1 ) ;
	int targetSize = 5;
	
//	VECTOR misslePos = VGet(0,480,0);
	VECTOR misslePos = VGet(160,360,0);
	VECTOR missleVec = VGet(0.1,0,0);
	VECTOR missleMark[MARK_MAX] = {{0}};
	int missleSize = 3;

	// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
	int hitCount = 0;
	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
		
		//	表示
		if( hitCount > 0 ) {
			hitCount--;
			Draw(targetPos,targetMark,targetSize,255,0,0);
		} else {
			Draw(targetPos,targetMark,targetSize,255,255,255);
		}
		Draw(misslePos,missleMark,missleSize,0,255,0);
		
		//	マーク処理
		SetMark(targetPos,targetMark);
		SetMark(misslePos,missleMark);
		
		//	 運動ベクトル計算
		{
			//	ターゲットへのベクトル
			VECTOR mis2tarVec = VSub( targetPos,misslePos );
			
			//	ターゲットへのベクトルと運動ベクトルの角度を求める。
			float dot = VDot( mis2tarVec, missleVec );
			float costheta = dot / ( VSize(mis2tarVec)*VSize(missleVec) );
			float theta = acos( costheta );
			
			//	変更角度の制限
			float max_theta = 3.141592 / 180.0 * 45;//角度限界。
			if( theta > max_theta ) {
				theta = max_theta;
			}
			if( theta < -max_theta ) {
				theta = -max_theta;
			}
			
			//	推進ベクトル確定
			VECTOR dirVec = VNorm(missleVec);	//今飛んでいる方向ベクトル
			VECTOR aVec = VScale(dirVec,0.20);	//推進力分だけ倍増
			MATRIX rotaMatrix = MGetRotZ( theta ) ;	//変更角度で回す。
			aVec = VTransform(aVec,rotaMatrix);
			
			//	運動ベクトルの合成
			missleVec = VAdd(missleVec,aVec);
			
			//	偽空気抵抗
			missleVec = VScale(missleVec,0.95);
		}
		
		//	命中判定
		float diffX = targetPos.x-misslePos.x;
		float diffY = targetPos.y-misslePos.y;
		float size = targetSize+missleSize;
		if( (diffX*diffX)+(diffY*diffY) < (size*size) ) {
			hitCount = 30;
		}
		
		
		//	ターゲットの周回
		targetVec = VTransform(targetVec,targetRotMatrix);
		
		//	移動
		targetPos = VAdd(targetPos,targetVec);
		misslePos = VAdd(misslePos,missleVec);
	}

	DxLib_End(); // DXライブラリ終了処理
	return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#25

投稿記事 by GRAM » 10年前

珈琲 さんが書きました: 比例航法としてはこの実行ファイルであってると思います。
それに、usaoさんの
>「ターゲット予測位置方向に常にミサイルの速度ベクトル(Mlne)が向いている状況をキープする」
という状況を加えたいです。
そういう条件を加えることは容易ですが、上にも述べたとおり「凶悪な」ミサイルになります。
その文章の意味するところは
①角速度に制限がないため予測衝突座標の方向へ一瞬で向く
②予測衝突座標は一意に決まる為回避不可能
(速度ベクトルが一瞬で予測座標を向くのならターゲットからみた相対座標系において静止している目標にまっすぐ飛んでいくことと同義)
という①はおかしな挙動に見え(横を向いて発射されたミサイルがいきなり上を向いたりできるということ)②はどうなの?という感じに思います。

最初の実装もこの実装もターゲットの進行方向に寄らず前からなら前から、横からなら横から命中しますし、
加速もしています。
今からバイトなのでコードは12時くらいに乗っけられると思います。
(左から出るミサイルが前の実装を速く収束するようちょっとだけ改良したもの。右から出るミサイルは今回の実装)
DxTest.rar
(542.7 KiB) ダウンロード数: 120 回

珈琲

Re: ドリフトっぽい動きをするミサイル

#26

投稿記事 by 珈琲 » 10年前

softya(ソフト屋) さんが書きました:敵というかターゲットの移動ベクトルが分かっているのなら未来位置は簡単に計算できますが、それではダメなのでしょうか?
あとミサイルが敵の方向を向けば後方から追いついてやがては必ず当たります。 
※ 当たらないとしたらミサイルが敵機より遅い場合です。
えーと、移動ベクトルがわかっていて、ミサイルの速度、からなる追いつく時間(おおよそ)がわかれば、その時間*移動ベクトル方向に伸ばせばいいということですよね
追いつく時間を知るためにはミサイルの移動ベクトルの大きさが必要で、このベクトルは別の推力ベクトルによって常に変化し、
ついでに移動ベクトルの向きによって到達時間は大きく変化する。

あれ、でもそうすると、ミサイルの移動ベクトルのターゲット方向ベクトルの内積が負の値の時「永遠にあたりません」という評価が出て到達時間が無限になるんですかね・・・?


クオリティダウンするのは悔しくて泣きそうになりますが、到達時間の算出もできないようじゃ自分には難しいかなぁ・・・
usao さんが書きました: おっと,なんかこの文面だけを見ると まるで私がそういうことを提唱しているかのように見えちゃいそうなので
失礼しました、悪気はありません。
usao さんが書きました: で,仮に計算方法の内容が合っていれば
3次元ならば円を球に置き換えるだけの話ですから,やりたければやってみればいいのでは?
交点が無い場合でも適当にやればいいでしょう.例えば球と直線の最近点を使うとか.
うーん、球の交点というのがいまいちピンときません。
それに、ミサイルの移動ベクトルとターゲットの方向から推力ベクトルの回転の算出もよくわからず・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#27

投稿記事 by softya(ソフト屋) » 10年前

エースコンバットでも正面からくる敵に発射したミサイルってまず命中しないと思いますが、命中しましたっけ?
ロックオン自体が困難ですけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#28

投稿記事 by 珈琲 » 10年前

とりあえずミサイルは既に目標へ向いていて直線で目標に向かって移動する、ついでに目標も等速直線運動で移動する、
という前提で算出した時間を近似値として求めたいと思います。毎フレーム計算するので多分大丈夫です。(ここからかよと思われるかもしれませんが
直線というのはミサイルからターゲットへの直線です

コード:

//ミサイルからターゲットの方角に対してターゲットの移動ベクトルはどれぐらいの速度を出しているか
float TargetSpeed = VScale(Target.Inertia , VDot(VNorm(VSub(Target.Position,Missile.Position)),VNorm(Target.Inertia)));
//↑とほぼ同じで、現在のミサイルの速度
float MissileSpeed = VScale(Missile.Inertia , VDot(VNorm(VSub(Target.Position,Missile.Position)),VNorm(Missile.Inertia)));
//ミサイルの加速度(スカラ)はミサイルの向きによって倍率が決まる。当然ミサイルが逆を向いていたら・・・
float MissileAcceleration = Missile.Thrust * VDot(VNorm(VSub(Target.Position,Missile.Position)),Missile.Direction);

//で、ミサイルがターゲットを追い越す時間を求める

int i=0;
while(true){
	if( TargetSpeed * TimeCount < (MissileSpeed + MissileAcceleration * TimeCount) * TimeCount ){
		//追い越したはず
	}
	TimeCount++;
}

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#29

投稿記事 by GRAM » 10年前

コードです。
長くなるのでスポイラーにします。
(ベクトル演算用のコードが長いだけなので160行あたりまで読み飛ばしてもいいです)
► スポイラーを表示
基本的には最初のコードそのままです。
正面からも側面からも後方からも狙え、およそ敵に命中し、かつ加速もしてますが、ドリフトしてるかはわかりません

珈琲

Re: ドリフトっぽい動きをするミサイル

#30

投稿記事 by 珈琲 » 10年前

softya(ソフト屋) さんが書きました:エースコンバットでも正面からくる敵に発射したミサイルってまず命中しないと思いますが、命中しましたっけ?
ロックオン自体が困難ですけどね。
わかりやすいのはエースコンバット0のラスボスと一騎打ちで、すれ違いざまにミサイルをぶつけあうというよくわからないカッチョイイ戦闘があります。

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#31

投稿記事 by usao » 10年前

>うーん、球の交点というのがいまいちピンときません。

そうですか…私にはこれ以上簡潔に説明できませんし
他の方もおっしゃられているように非常に不自然な結果になると思われ,そもそもそのまま実装することもないでしょうから
これ以上この計算内容について述べるのは無駄だろうなと思います.

>それに、ミサイルの移動ベクトルとターゲットの方向から推力ベクトルの回転の算出もよくわからず・・・

少なくとも私が書いた説明の計算内容は,現在のベクトルをいくらか回転させてどうの というような話ではありませんよ.
各時刻のミサイルの向きMDirを方程式の解として求める,というだけの話です.
言い換えれば 前時刻のミサイルの向きとは関係なく現在時刻でのミサイルの向きを決定するようなこと でしょうかね.
(あくまでも向きを回転させるという捉え方をするのであれば フレーム間での回転角度を無制限に選べる という状態ですね.
 だから1フレームで向きを90度変化させたりとかいうことも起こりえると思われる.)


>エースコンバットでも正面からくる敵に発射したミサイルってまず命中しないと思いますが、命中しましたっけ?
本当に真正面であれば 正面衝突な形で命中しますね.
ステージによっては開始時の配置がそんな感じなので1機確殺できます.
それ以降はまず狙えないと思いますけど.

#特殊な例としてはエースコンバットZEROの最終ステージとかもあります(敵が謎の装備で真正面からのミサイルしか受け付けない)
 …って投稿しようとしたら先をこされてしまった.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#32

投稿記事 by softya(ソフト屋) » 10年前

> わかりやすいのはエースコンバット0のラスボスと一騎打ちで、すれ違いざまにミサイルをぶつけあうというよくわからないカッチョイイ戦闘があります。

エースコンバット0は未経験ですが、そのボス・ステージ専用にミサイルの挙動が調整されているとかありませんか?
一般ステージだと外れると思いますが。

【追記】
動画で見てみましたが、ボスが正面から来る時と後ろから来る時の相対速度が余り変わらないように見えます。
つまり、正面から来る時は対地速度がすげー遅いんじゃないかと。
まぁ、ゲームですのでそこは面白くするためにはこう言う嘘も必要です。
[youtube][/youtube]
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#33

投稿記事 by 珈琲 » 10年前

GRAM さんが書きました:コードです。
長くなるのでスポイラーにします。
(ベクトル演算用のコードが長いだけなので160行あたりまで読み飛ばしてもいいです)


基本的には最初のコードそのままです。
正面からも側面からも後方からも狙え、およそ敵に命中し、かつ加速もしてますが、ドリフトしてるかはわかりません
ありがとうございます、恐縮です。

>double D = v*v + 4*a*s; //二次方程式 at^2 + vt - s = 0を解く(距離と速度と加速度の関係より)
>double t = ( -v + sqrt(D) ) / (2.0*a);
これで時間がわかるのですか、勉強になります

ドリフト自体はしていないと思われます。
>Vec S = target_->S() + target_->V()*t; //目標地点
に対して、ミサイルの移動方向(Missile::v_)が徐々に回転していますが、
理想的なのはミサイルの次のフレームのいる相対座標に、推力と称したベクトル足し続けている感じです。

↓こんなイメージ
珈琲 さんが書きました: Direction=向き(単位)
Position=座標
Inertia=移動ベクトル
Thrust=推力ベクトル

コード:

//敵へ直で向く直座標角度
VECTOR EDirection = VNorm(VSub(TargetObject->GetPosition(),Position));

//その軸
VECTOR RotAxis = VNorm(VCross(EDirection,AxisZ));

Direction = VNorm(ReactionQuaternion(RotAxis,Direction,DX_PI_F/180*40));//40度づつ曲がる

VECTOR Thrust = VScale(Direction,1.3);//推力

Inertia = VAdd(Thrust,Inertia);//慣性っぽい何か

Position = VAdd(Position,Inertia);


珈琲

Re: ドリフトっぽい動きをするミサイル

#34

投稿記事 by 珈琲 » 10年前

Soft屋さんが貼られた
http://homepage1.nifty.com/kaneko/missile.htm
このゲームが本当に理想に近いんですけど・・・
(まぁゲーム内のミサイルの命中率は微妙ですが)


比例航法だとどうなるかわかりませんが、純粋追尾航法で、慣性(もどき)をのせた、敵の方向にしか向かないミサイルの軌跡はそこまで不自然じゃないような・・・
ただ、敵機の真横をすれ違ったあとに戻ってきてまたアプローチするミサイルは現実的じゃないと言われればそうなんですが

画像画像

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#35

投稿記事 by GRAM » 10年前

横やりですが、まぁエースコンバットについて言うのならば、ヘッドオンでミサイルは普通にあてられます。
難易度に関わらず、です。
とはいえある程度引き付けて打たないと敵が回避しちゃうので逃げられますが…誘導の問題はたぶんないと思います。
むしろ0のラストは特殊な例ですね。あれは最後だけ敵がほぼ回避行動とらないので…

ところで自分も

コード:

a_ = v_.Normalize()*accel;                      //一定の加速度を加える
v_ += a_;
s_ += v_;
こういう処理を入れているのでミサイルは進行方向に加速していると思うのですがダメなのですかね?

追記:あぁなんとなくわかってきました。
ただ個人的な意見を言うのならば、速度ベクトルを回転さして何か悪いのか という感じですね
というのも加速度ベクトルを(V'-V)としてやれば、話は全く同じことになるわけですよね。
一応回転させるにも加速度を与えてやる必要があるので、加速度の上限が決まっているという条件のもとプログラムを組みなおしました。
速度ベクトルはもはや直接回転さしてはいません。ただし与えるスラスト力により間接的に回転することになるわけではありますが
► スポイラーを表示
ただそもそも論でやはりドリフトがよくわからないわけなのですが…ドリフトしてるかどうかって、シミュレーションしてるわけじゃないのなら
3次元の物体そのものの演出であって、別に点の軌跡からわかることではないですよね。(私のイメージはリアが滑っているような感じなのですが)

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#36

投稿記事 by usao » 10年前

>3次元の物体そのものの演出であって、別に点の軌跡からわかることではないですよね。(私のイメージはリアが滑っているような感じなのですが)

そういうこと(ドリフト感はミサイルの描画の問題,みたいな)
をNo3で既に述べたつもりなのですが,なんか違うみたいですよ(?)

というかNo3程度ので不十分なのかどうかが?
加速方向を
>ミサイル現在位置→ターゲットの数フレーム後予測位置 方向
に取れば比例なんちゃらいうのに原理的に近い形になると思うし,
>各フレームで任意の方向に加速できる
これがいやならそのフレームで加速できる方向に制限を設ければいいだろうし
命中率とか命中までの軌跡の長さに不満があるなら,
加速度を加算した後の速度ベクトルの長さを速度最大値に切り詰める前に
横滑り方向速度に減衰を設けてやる(ミサイルから見れば左右方向のみに空気抵抗が働く→膨らみが抑えられる)とか,
微調のやりようはいくらでもあると思うのですが,
やはりそういうことを中途半端にやると何か”不自然”に見えるのでしょうかね.
オフトピック
検討時は
これまで実装されたミサイルを同時にFIREされてみると運動を比較できて良いのではないですか?
オフトピック
ところで実際のミサイルってどうやって向き変えてるんだ? というのを少し検索してみたら
ノズルからガスを噴射する方向を変えてどうの みたいな話である模様(?).
であれば,ミサイルの向きと加速方向とは異なり得るわけで,ミサイルという物体がどっちを向いているかってのは制御の結果側ですね.
ここでやってる話は ミサイルの向きがINという形だけど,実物ではむしろOUT側 というか.
まぁ完全にどうでもいい話ですが.
最後に編集したユーザー usao on 2013年8月21日(水) 11:48 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#37

投稿記事 by softya(ソフト屋) » 10年前

何にしても演出前に、ちゃんと当てられるミサイルを作ってそこから調整でしょうね。
あと、見た目が気持ちよければどんな挙動をしても良いと思います。いきなり90度ターンしても構いません。
某マクロスミサイルのように横へのスライドをしても良いでしょう。
そこは、空間での動きを自在に操れるようになってくださいとしか言えません。

ただし、自分に来るミサイルと敵に当てるミサイルは挙動を変えないと避けれないミサイルになります。

【補足】
同じ金子さんのNekoFlight に関してはjava版のソースコードが公開されていますので、参考にして下さい。アルゴリズムは参考に出来るはずです。
「NekoFlight for Java」
http://homepage1.nifty.com/kaneko/jflight0.htm
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#38

投稿記事 by usao » 10年前

なんかもう 加速度がどうの とか忘れて,毎フレーム
適当なパラメトリック曲線に沿って一定距離だけ進ませればいいんじゃね?とかいう邪悪な(?)考えが…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#39

投稿記事 by softya(ソフト屋) » 10年前

usao さんが書きました:なんかもう 加速度がどうの とか忘れて,毎フレーム
適当なパラメトリック曲線に沿って一定距離だけ進ませればいいんじゃね?とかいう邪悪な(?)考えが…
珈琲さんはシミュレーション性には興味が無いようなので、それこそ気持ち良ければ、それでも良いと思いますよ。
気持ち良い動きって所が問題なんでしょうけど。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#40

投稿記事 by 珈琲 » 10年前

先読みはしてるのかわかりませんがまったく当たりませんね、軌跡は気持ちいいんですが・・・
画像
見せミサイルとしておくのがやっぱ無難ですか・・・

珈琲

Re: ドリフトっぽい動きをするミサイル

#41

投稿記事 by 珈琲 » 10年前

先読み(比例航法)で、ミサイルの回転の制限がないミサイルで、慣性をまったく含んでない場合
画像

相手の目の前を蝿みたいに・・・

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#42

投稿記事 by usao » 10年前

例えば,シンプルに毎フレーム
(1)ミサイル現在位置
(2)ターゲット現在位置
(3)ターゲットのいくらか未来の予測位置
の3制御点でBezier曲線を求めて,ミサイルはそのフレームでは現在位置から曲線にそって一定距離分すすむとか
(曲線上の距離がめんどくさい場合(1)の点での傾き方向に進む,とかで近似してもいいか)

なんとなく 常に「(2)と(3)の間の方向に向かって進む」ということになりそうだけど
(2)と(3)の間の重みがちゃんと毎フレーム変わることになるだろうか?(数学疎いのでよくわからない)
固定だったら曲線とか意味ない.
オフトピック
(2)や(3)の座標の更新方法を工夫すれば慣性っぽさが調整できたりしないかなぁ.
気になるからあとでやってみよう.
>相手の目の前を蝿みたいに・・・
絵の見方がよくわかりませんが,
常に相手の一歩先を目指せばまぁ相手の目の前に行くのは必然のような.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#43

投稿記事 by softya(ソフト屋) » 10年前

何度も書いてますが、当たるミサイルを作ってからですよ。
そこは出来ているんでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#44

投稿記事 by 珈琲 » 10年前

純粋追尾航法の慣性なしのミサイル→当たってます。期待値は当たります。
純粋追尾航法の慣性ありのミサイル→当たりません。期待値は当たりません。
比例航法の慣性なしのミサイル→当たりません。期待値は当たります。
比例航法の慣性ありのミサイル→当たりません。期待値は当たります。

比例航法を使う以上、ターゲットとミサイルの距離が近づけば近づくほど
実際のターゲットの位置と衝突する予測の未来のターゲットの位置が近づくはずなんですが、、

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#45

投稿記事 by softya(ソフト屋) » 10年前

肝心の起こっている問題への調査・分析が足りないと思います。
予想と食い違うのはなぜでしょうか?

>比例航法を使う以上、ターゲットとミサイルの距離が近づけば近づくほど
> 実際のターゲットの位置と衝突する予測の未来のターゲットの位置が近づくはずなんですが、、

あれ?どういう原理でそうなるんでしょうか。
そんなコードでは無かったような。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#46

投稿記事 by 珈琲 » 10年前

えっと、ターゲットとミサイルの現在の距離を測って、ミサイルがどれぐらいの時間で命中するかを計算し、
その時間を元にターゲットの未来座標を予測する、というものです

コード貼っつけ忘れてました
以下のコードは、比例航法・慣性無しのコードです。
機体の前に蝿が~のミサイルです。

コード:

	//直線でミサイルが進んでいったとして、衝突時間の近似値を求めます
			//敵へ直で向く直座標角度
			VECTOR EDirection = VNorm(VSub(TargetObject->GetPosition(),Position));
			//距離
			float EDistance = VSize(VSub(TargetObject->GetPosition(),Position));

			//ミサイルからターゲットの方角に対してターゲットの移動ベクトルはどれぐらいの速度を出しているか
			float TargetSpeed = VSize(VScale(TargetObject->GetInertia() , VDot(EDirection,VNorm(TargetObject->GetInertia()))));
			//↑とほぼ同じで、現在のミサイルの速度
			float MissileSpeed = VSize(VScale(Inertia , VDot(EDirection,VNorm(Inertia))));
			//ミサイルの加速度(スカラ)はミサイルの向きによって倍率が決まる。当然ミサイルが逆を向いていたら・・・
			float MissileAcceleration = 1.3 * VDot(EDirection,AxisZ);

			float s = TargetSpeed - MissileSpeed;//現在の相対速度
			float D = EDistance*EDistance + 4*MissileAcceleration*s; //二次方程式 at^2 + vt - s = 0を解く(距離と速度と加速度の関係より)

			float CollisionTime = (int)(( -EDistance + sqrt(D) ) / (2.0*MissileAcceleration));//float値ですがこの際気にしない事にします

	//衝突時間と敵の進行方向から、衝突座標を求めます。

			//衝突絶対座標
			VECTOR CollisionPosition = VAdd(VScale(VSub(VGet(0,0,0),TargetObject->GetInertia()),CollisionTime-5),TargetObject->GetPosition());

			//衝突相対座標
			VECTOR CollisionRelativePosition = VSub(CollisionPosition,Position);

			//衝突相対座標への方角
			VECTOR CollisionDirection = VNorm(CollisionRelativePosition);


			//その軸
			//VECTOR RotAxis = VNorm(VCross(CollisionDirection,AxisZ));

			//AxisZ = VNorm(ReactionQuaternion(RotAxis,AxisZ,DX_PI_F/60));

			AxisZ = CollisionDirection;

			VECTOR Thrust = VScale(AxisZ,30);//推力

			//Inertia = VAdd(Thrust,Inertia);//慣性っぽい何か

			Position = VAdd(Position,Thrust);

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#47

投稿記事 by softya(ソフト屋) » 10年前

予測されている未来座標の予測と現在の位置の相対座標の変化をログにして頂きたいのです。
と言うより、ちゃんとデバッグですべき事を行わないといつまで経っても解決できなくなります。
必要な情報を取り、「近づくはず」の仮定の部分を確実な情報として見せてもらえないでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#48

投稿記事 by 珈琲 » 10年前

1つのミサイルのログファイルを出力してみました。
10フレームごとに間引きするとこんな感じです。

コード:

ミサイル生成
相対速度:15.510621,相対距離:2909.810059,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.629437,ターゲット方向のミサイルの速度:0.118817,ターゲット方向のミサイルの加速度:1.299961
相対速度:16.047192,相対距離:2769.192871,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.159813,ターゲット方向のミサイルの速度:0.112620,ターゲット方向のミサイルの加速度:1.299979
相対速度:16.356335,相対距離:2632.620117,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.462652,ターゲット方向のミサイルの速度:0.106318,ターゲット方向のミサイルの加速度:1.299991
相対速度:16.468275,相対距離:2497.969482,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.568268,ターゲット方向のミサイルの速度:0.099992,ターゲット方向のミサイルの加速度:1.299996
相対速度:16.469135,相対距離:2363.652100,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.562078,ターゲット方向のミサイルの速度:0.092943,ターゲット方向のミサイルの加速度:1.299992
相対速度:16.441847,相対距離:2229.079346,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.525736,ターゲット方向のミサイルの速度:0.083889,ターゲット方向のミサイルの加速度:1.299986
相対速度:16.402082,相対距離:2094.048828,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.474276,ターゲット方向のミサイルの速度:0.072192,ターゲット方向のミサイルの加速度:1.299979
相対速度:16.356842,相対距離:1958.447388,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.414366,ターゲット方向のミサイルの速度:0.057523,ターゲット方向のミサイルの加速度:1.299969
相対速度:16.311914,相対距離:1822.221313,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.351570,ターゲット方向のミサイルの速度:0.039656,ターゲット方向のミサイルの加速度:1.299956
相対速度:16.272587,相対距離:1685.369263,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.290976,ターゲット方向のミサイルの速度:0.018388,ターゲット方向のミサイルの加速度:1.299940
相対速度:16.230865,相対距離:1547.940186,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.237354,ターゲット方向のミサイルの速度:0.006489,ターゲット方向のミサイルの加速度:1.299920
相対速度:16.160023,相対距離:1410.028931,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.195227,ターゲット方向のミサイルの速度:0.035204,ターゲット方向のミサイルの加速度:1.299894
相対速度:16.100815,相対距離:1271.775269,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.168818,ターゲット方向のミサイルの速度:0.068003,ターゲット方向のミサイルの加速度:1.299862
相対速度:16.056856,相対距離:1133.359497,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.162016,ターゲット方向のミサイルの速度:0.105159,ターゲット方向のミサイルの加速度:1.299821
相対速度:16.031273,相対距離:994.999695,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.178232,ターゲット方向のミサイルの速度:0.146960,ターゲット方向のミサイルの加速度:1.299770
相対速度:16.026487,相対距離:856.946045,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.220192,ターゲット方向のミサイルの速度:0.193704,ターゲット方向のミサイルの加速度:1.299704
相対速度:16.043945,相対距離:719.472595,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.289625,ターゲット方向のミサイルの速度:0.245679,ターゲット方向のミサイルの加速度:1.299617
相対速度:16.083612,相対距離:582.865417,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.386742,ターゲット方向のミサイルの速度:0.303129,ターゲット方向のミサイルの加速度:1.299499
相対速度:16.143230,相対距離:447.407318,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.509399,ターゲット方向のミサイルの速度:0.366169,ターゲット方向のミサイルの加速度:1.299332
相対速度:16.217010,相対距離:313.349060,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.651581,ターゲット方向のミサイルの速度:0.434569,ターゲット方向のミサイルの加速度:1.299065
相対速度:16.292582,相対距離:180.873764,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.799284,ターゲット方向のミサイルの速度:0.506702,ターゲット方向のミサイルの加速度:1.298516
相対速度:16.318422,相対距離:50.061359,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:16.880564,ターゲット方向のミサイルの速度:0.562142,ターゲット方向のミサイルの加速度:1.294957
命中
衝突予測時間が0.0になってます・・・
そのため比例航法ではなく純粋追尾航法になってます
ターゲット方向のターゲットの速度は、あってるかはわかりません。少なくともまっすぐすすんでいたはずですが
ターゲット方向のミサイルの速度が極端に遅いです。計算が間違ってると・・
ターゲット方向のミサイルの加速度は、角度制限をしていないので多分あってると思います。

ついでに、機体の前を蝿が飛ぶように~という挙動は見えませんでした。変えた覚えは無いんですが・・・

ターゲット方向のミサイルの速度を直してみます。

コード:

	//直線でミサイルが進んでいったとして、衝突時間の近似値を求めます
			//敵へ直で向く直座標角度
			VECTOR EDirection = VNorm(VSub(TargetObject->GetPosition(),Position));
			//距離
			float EDistance = VSize(VSub(TargetObject->GetPosition(),Position));

			//ミサイルからターゲットの方角に対してターゲットの移動ベクトルはどれぐらいの速度を出しているか
			float TargetSpeed = VSize(VScale(TargetObject->GetInertia() , VDot(EDirection,VNorm(TargetObject->GetInertia()))));
			//↑とほぼ同じで、現在のミサイルの速度
			float MissileSpeed = VSize(VScale(Inertia , VDot(EDirection,VNorm(Inertia))));
			//ミサイルの加速度(スカラ)はミサイルの向きによって倍率が決まる。当然ミサイルが逆を向いていたら・・・
			float MissileAcceleration = 1.3 * VDot(EDirection,AxisZ);

			float s = TargetSpeed - MissileSpeed;//現在の相対速度
			float D = EDistance*EDistance + 4*MissileAcceleration*s; //二次方程式 at^2 + vt - s = 0を解く(距離と速度と加速度の関係より)

			float CollisionTime = (int)(( -EDistance + sqrt(D) ) / (2.0*MissileAcceleration));//float値ですがこの際気にしない事にします

	//衝突時間と敵の進行方向から、衝突座標を求めます。

			//衝突絶対座標
			VECTOR CollisionPosition = VAdd(VScale(VSub(VGet(0,0,0),TargetObject->GetInertia()),CollisionTime-5),TargetObject->GetPosition());

			//衝突相対座標
			VECTOR CollisionRelativePosition = VSub(CollisionPosition,Position);

			//衝突相対座標への方角
			VECTOR CollisionDirection = VNorm(CollisionRelativePosition);

			
			  FILE *outputfile;         // 出力ストリーム
			  outputfile = fopen("Missile.txt", "a");  // ファイルを書き込み用にオープン(開く)
			  if (outputfile != NULL) {          // オープンに失敗した場合
	  			  if(LifeTime%10 ==0)fprintf(outputfile, "相対速度:%f,相対距離:%f,衝突予測時間:%f,ターゲット方向のターゲットの速度:%f,ターゲット方向のミサイルの速度:%f,ターゲット方向のミサイルの加速度:%f\n",s,EDistance,CollisionTime,TargetSpeed,MissileSpeed,MissileAcceleration); // ファイルに書く
				  fclose(outputfile);          // ファイルをクローズ(閉じる)
			  }

珈琲

Re: ドリフトっぽい動きをするミサイル

#49

投稿記事 by 珈琲 » 10年前

あ、ミサイルの速度が極端に遅いのはInertiaから採取しているからですね、このコードでは慣性を適用・更新していないので移動ベクトルは0に近いはず・・・

そして、比例航法・慣性ありでのミサイルです。

コード:

相対速度:3.391714,相対距離:4771.581055,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:12.622540,ターゲット方向のミサイルの速度:9.230826,ターゲット方向のミサイルの加速度:1.297628
相対速度:-8.726135,相対距離:4738.934082,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:13.502605,ターゲット方向のミサイルの速度:22.228741,ターゲット方向のミサイルの加速度:1.298558
相対速度:-21.073757,相対距離:4583.938965,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:14.154613,ターゲット方向のミサイルの速度:35.228371,ターゲット方向のミサイルの加速度:1.299249
相対速度:-33.733990,相対距離:4303.699707,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:14.488743,ターゲット方向のミサイルの速度:48.222733,ターゲット方向のミサイルの加速度:1.299711
相対速度:-46.524059,相対距離:3895.980225,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:14.676105,ターゲット方向のミサイルの速度:61.200165,ターゲット方向のミサイルの加速度:1.299942
相対速度:-59.311420,相対距離:3360.274658,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:14.831799,ターゲット方向のミサイルの速度:74.143219,ターゲット方向のミサイルの加速度:1.299916
相対速度:-71.988609,相対距離:2697.106689,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.015320,ターゲット方向のミサイルの速度:87.003929,ターゲット方向のミサイルの加速度:1.299192
相対速度:-84.248154,相対距離:1908.797729,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.297065,ターゲット方向のミサイルの速度:99.545219,ターゲット方向のミサイルの加速度:1.299625
相対速度:-93.953156,相対距離:1006.208008,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.825150,ターゲット方向のミサイルの速度:109.778305,ターゲット方向のミサイルの加速度:1.299827
相対速度:-22.844223,相対距離:278.259064,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:2.262930,ターゲット方向のミサイルの速度:25.107153,ターゲット方向のミサイルの加速度:0.561417
相対速度:-113.096390,相対距離:1228.232056,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:13.456481,ターゲット方向のミサイルの速度:126.552872,ターゲット方向のミサイルの加速度:-0.224469
相対速度:-117.166359,相対距離:2387.135010,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:14.633555,ターゲット方向のミサイルの速度:131.799911,ターゲット方向のミサイルの加速度:0.246026
相対速度:-114.123688,相対距離:3545.676270,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.124240,ターゲット方向のミサイルの速度:129.247925,ターゲット方向のミサイルの加速度:0.759559
相対速度:-106.073349,相対距離:4645.158203,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.406277,ターゲット方向のミサイルの速度:121.479630,ターゲット方向のミサイルの加速度:1.146539
相対速度:-94.937042,相対距離:5645.524414,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.569898,ターゲット方向のミサイルの速度:110.506943,ターゲット方向のミサイルの加速度:1.299759
相対速度:-82.860809,相対距離:6528.333984,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.657395,ターゲット方向のミサイルの速度:98.518204,ターゲット方向のミサイルの加速度:1.297849
相対速度:-70.501045,相対距離:7288.831055,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.704410,ターゲット方向のミサイルの速度:86.205452,ターゲット方向のミサイルの加速度:1.299803
相対速度:-57.992207,相対距離:7924.902832,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.728870,ターゲット方向のミサイルの速度:73.721077,ターゲット方向のミサイルの加速度:1.299966
相対速度:-45.387932,相対距離:8435.381836,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.739119,ターゲット方向のミサイルの速度:61.127052,ターゲット方向のミサイルの加速度:1.299475
相対速度:-32.730263,相対距離:8819.512695,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.740073,ターゲット方向のミサイルの速度:48.470337,ターゲット方向のミサイルの加速度:1.298535
相対速度:-20.043518,相対距離:9076.922852,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.734326,ターゲット方向のミサイルの速度:35.777843,ターゲット方向のミサイルの加速度:1.298988
相対速度:-7.330834,相対距離:9207.318359,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.723159,ターゲット方向のミサイルの速度:23.053993,ターゲット方向のミサイルの加速度:1.299668
相対速度:5.383698,相対距離:9210.558594,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.705681,ターゲット方向のミサイルの速度:10.321982,ターゲット方向のミサイルの加速度:1.299977
相対速度:13.262461,相対距離:9086.776367,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.669497,ターゲット方向のミサイルの速度:2.407037,ターゲット方向のミサイルの加速度:1.299923
相対速度:0.477683,相対距離:8836.117188,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.618776,ターゲット方向のミサイルの速度:15.141093,ターゲット方向のミサイルの加速度:1.299505
相対速度:-12.304964,相対距離:8458.737305,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.556381,ターゲット方向のミサイルの速度:27.861345,ターゲット方向のミサイルの加速度:1.298689
相対速度:-25.063698,相対距離:7955.003418,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.483901,ターゲット方向のミサイルの速度:40.547600,ターゲット方向のミサイルの加速度:1.298883
相対速度:-37.790173,相対距離:7325.367676,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.403247,ターゲット方向のミサイルの速度:53.193420,ターゲット方向のミサイルの加速度:1.299711
相対速度:-50.430058,相対距離:6570.507813,衝突予測時間:0.000000,ターゲット方向のターゲットの速度:15.318812,ターゲット方向のミサイルの速度:65.748871,ターゲット方向のミサイルの加速度:1.299992
衝突予測時間が0.0ということは、純粋追尾航法・慣性有りのと全く動きということですよね

当加速運動の、到達時間の求め方がよくわからない・・・高校では習ったような習わなかったような

珈琲

Re: ドリフトっぽい動きをするミサイル

#50

投稿記事 by 珈琲 » 10年前

あれ?
TargetSpeed - MissileSpeedで求まった相対速度が+ということは、ミサイルのほうが遅いということですか

アバター
usao
記事: 1887
登録日時: 11年前

Re: ドリフトっぽい動きをするミサイル

#51

投稿記事 by usao » 10年前

話の流れと関係ない感じで申し訳ないですが,No42のシンプルなことをちょっとやってました.
{2D,ターゲットは等速直線運動}という状態で.

結果:
まぁとりあえず当たりますが動きが楽しいかと問われると微妙.速度一定で進むので慣性っぽさがない予感.
 ↓
「一定距離進む」のところを「その方向に加速する」に変更してみると,
”ターゲットの周りを衛星状態”に陥ること多数
→毎フレーム ミサイル速度を減衰させる処理を入れることでかなり軽減できる模様.

需要ないでしょうけど一応コード貼っておきます.(ログ的な意味で)
#描画と表示などにOpenCVを使っていますが,動かしてみたい場合,書き換えは容易かと.
► スポイラーを表示

珈琲

Re: ドリフトっぽい動きをするミサイル

#52

投稿記事 by 珈琲 » 10年前

usao さんが書きました:話の流れと関係ない感じで申し訳ないですが,No42のシンプルなことをちょっとやってました.
{2D,ターゲットは等速直線運動}という状態で.

結果:
まぁとりあえず当たりますが動きが楽しいかと問われると微妙.速度一定で進むので慣性っぽさがない予感.
 ↓
「一定距離進む」のところを「その方向に加速する」に変更してみると,
”ターゲットの周りを衛星状態”に陥ること多数
→毎フレーム ミサイル速度を減衰させる処理を入れることでかなり軽減できる模様.

需要ないでしょうけど一応コード貼っておきます.(ログ的な意味で)
#描画と表示などにOpenCVを使っていますが,動かしてみたい場合,書き換えは容易かと.
ベジエ曲線による座標の予測ですよね、ありがとうございます。
厚かましいのですが、できたら距離によって予測するフレーム数を調整できたりしないでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#53

投稿記事 by softya(ソフト屋) » 10年前

ロギング情報自体の原因究明が出来ていないようですが値的にはおかしく感じます。
こちらで検証できないので、それ以上は言えないんですが、私やGRAMさんのコード上で動くようには出来ないのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ドリフトっぽい動きをするミサイル

#54

投稿記事 by 珈琲 » 10年前

Soft屋さんのソースコードを弄って、現在のコードに近づけてみました。
描画数値を見てみるとそれっぽい・・・?
しかし、左右へ旋回が使い分けられてないというのもあり、加速が意味ない・・・

コード:

#include "DxLib.h"
#include "math.h"
 
#define MARK_MAX (256)
 
//  共通描画
void Draw(VECTOR pos,VECTOR mark[MARK_MAX],int size,int r,int g,int b)
{
    //  マーク表示
    for( int i=0 ; i<MARK_MAX ; i++ ){
        if( mark[i].x != 0 && mark[i].y != 0 ) {
            float bright = (float)(MARK_MAX - i) / (float)MARK_MAX;
            DrawPixel( mark[i].x, mark[i].y, GetColor(r*bright,g*bright,b*bright) );
        }
    }
    
    //  表示
    DrawCircle( pos.x, pos.y, size, GetColor(r,g,b), TRUE );
}
 
//  共通マーク処理
void SetMark(VECTOR pos,VECTOR mark[MARK_MAX])
{
    //  マーク保存
    for( int i=MARK_MAX-1 ; i>=1 ; i-- ){
        mark[i] = mark[i-1];
    }
    mark[0] = pos;
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
    ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    //  初期値
    VECTOR targetPos = VGet(320,400,0);
    VECTOR targetVec = VGet(-2,0,0);
    VECTOR targetMark[MARK_MAX] = {{0}};
    MATRIX targetRotMatrix = MGetRotZ( 3.141592 / 180.0 * 1 ) ;
    int targetSize = 5;
    
    VECTOR misslePos = VGet(160,360,0);
    VECTOR missleVec = VGet(0.1,0,0);
	VECTOR missleDir = VNorm(missleVec);//ミサイルの向きを追加
    VECTOR missleMark[MARK_MAX] = {{0}};
	float missleAcl = 3.20;				//加速度を追加。ちょっと増やしました。
    int missleSize = 3;
 
    // while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
    int hitCount = 0;
    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
        
        //  表示
        if( hitCount > 0 ) {
            hitCount--;
            Draw(targetPos,targetMark,targetSize,255,0,0);
        } else {
            Draw(targetPos,targetMark,targetSize,255,255,255);
        }
		Draw(VAdd(misslePos,VScale(missleDir,5)),missleMark,missleSize,0,200,0);
        Draw(misslePos,missleMark,missleSize,0,255,0);
        
        //  マーク処理
        SetMark(targetPos,targetMark);
        SetMark(misslePos,missleMark);
        
        //   運動ベクトル計算
        {
            
            VECTOR mis2tarVec = VSub( targetPos,misslePos );//  ターゲットへのベクトル
			float mis2tarLen = VSize(mis2tarVec);			//  ターゲットへの方角
            
			float tarSpdLine = VSize(VScale(targetVec , VDot(mis2tarVec,VNorm(targetVec))));//ターゲット方向のターゲットの移動ベクトルの内積
			float misSpdLine = VSize(VScale(missleVec , VDot(mis2tarVec,VNorm(missleVec))));//ターゲット方向のミサイルの移動ベクトルの内積
			float misAclLine = missleAcl * VDot(mis2tarVec,VNorm(missleVec));				//ターゲット方向のミサイルの加速度の内積

			float relSpd = tarSpdLine - misSpdLine;									//相対速度
			float relDis = mis2tarLen*mis2tarLen + 4*misAclLine*relSpd;				//二次方程式 at^2 + vt - s = 0を解く(距離と速度と加速度の関係より)
			float colTime = (( -mis2tarLen + sqrt(relDis) ) / (2.0*misAclLine));	//衝突予測時間が算出できる(と思う)
			
			//衝突予想時間の近似値がわかったので、衝突予測座標と衝突予測座標へのベクトル・角度を算出します。

			VECTOR colPos = VAdd( targetPos , VScale( targetVec , colTime ) );	//相手が今後旋回するとかは無視します。
			VECTOR colVec = VSub( colPos , misslePos );							//ターゲットの衝突予測座標へのベクトル
			VECTOR colDir = VNorm( colVec );									//ターゲットの衝突予測座標への方角



			VECTOR PorN = VCross(colDir,missleDir);//外積の正負でどちらのほうが近いかわかるらしい??GRAMさんNo.35のソースコードから
			float theta;
			if(PorN.z < 0){
				theta = DX_PI_F/180 * 1;								//回転値を固定に。
			}else{
				theta = DX_PI_F/180 * -1;								//回転値を固定に。
			}
            //  推進ベクトル確定
            MATRIX rotaMatrix = MGetRotZ( theta ) ;						//ミサイルの角度を
			missleDir = VTransform(missleDir,rotaMatrix);				//    回転させます。
			misslePos = VAdd(misslePos , VScale(missleDir,missleAcl));	//ミサイルの移動ベクトルとミサイルの向きに発生する推力を合成

			int Color = GetColor(0,255,0);
			DrawFormatString(20,20,Color,"ターゲット方向の線上のターゲットの速度:%f",tarSpdLine);
			DrawFormatString(20,40,Color,"ターゲット方向の線上のミサイルの速度:%f",misSpdLine);
			DrawFormatString(20,60,Color,"ターゲット方向の線上のターゲットの速度:%f",misAclLine);

			DrawFormatString(20,80,Color,"相対速度:%f",relSpd);
			DrawFormatString(20,100,Color,"衝突予測時間:%f",colTime);
        }
        
        //  命中判定
        float diffX = targetPos.x-misslePos.x;
        float diffY = targetPos.y-misslePos.y;
        float size = targetSize+missleSize;
        if( (diffX*diffX)+(diffY*diffY) < (size*size) ) {
            hitCount = 30;
        }
        
        
        //  ターゲットの周回
        targetVec = VTransform(targetVec,targetRotMatrix);
        
        //  移動
        targetPos = VAdd(targetPos,targetVec);
        misslePos = VAdd(misslePos,missleVec);
    }
 
    DxLib_End(); // DXライブラリ終了処理
    return 0;
}

珈琲

Re: ドリフトっぽい動きをするミサイル

#55

投稿記事 by 珈琲 » 10年前

88~94行目がなんとかできれば、伝えられるかと思うんですが、・・

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#56

投稿記事 by GRAM » 10年前

自分としてはイメージを共有したいのですが…。~っぽいとか~みたいなという表現ではなく
①どういう条件下で誘導するのかという点を
②どの数字をいじってどの数字を固定するのか、どの数字とどの数字にはどういう関係性があるのか
という点を明確に語ってほしいです。個人的にはそこさえ共有できればアルゴリズムやソースコードなどどうとでもできると思うのです

どうやら慣性がキーワードっぽいので、ミサイルに向きの概念を導入し推力ベクトルをミサイルの方向ベクトルと180°逆の方向へ固定
スラスト力をヨーモーメントのことだと勝手に解釈して、違う追尾アルゴリズムを組んでみました。
これがなに航行かはよく知りません。未来位置の予測もしてませんが(相対速度をとって慣性系には持ち込んでいるのである意味してるともいえるのかな?)、とりあえず衝突しおそらく今度こそドリフトはしてるとおもいます。
(回転角度量制限パラメータや加速度パラメータの設定によっては凶悪度が増しますが)
DxTest.rar
(516.96 KiB) ダウンロード数: 130 回
動きを見やすくするためフレームを間引いて1/10にしてあります

まとめると今回自分がミサイルに課した条件は
①いわゆるF=maでいうところのFはミサイル後方へのみ働く
②なんらかの偶力がミサイルに働いて、ミサイルの機首方向は変えられる
③ミサイルの運動は質点のそれに従う
④ミサイルの機首方向とミサイルの進行方向は一致しなくてもよい。
⑤ミサイルの機首を変えられる量に制限がある
⑥剛体の回転運動に関する物理法則は無視する
(1,4と5はまとめると、加速度ベクトルの回転量に制約があるということと同意)
ってことにしてくみました。

理想的な速度ベクトルを(Starget-Smissile)と(Vmissile-Vtarget)とが平行になるようなVmissileだと仮定し、
その速度ベクトルを得るような加速度aを求め、
さらにその理想的な加速度ベクトルと現在のミサイルの向きとの差から回転量を求めるようにしました。
今までとの違いは
今までは速度ベクトルと向きが一致するようになっていたのに対し
今度は加速度ベクトルと向きが一致するようになっているという点です。
ただし制御が適当なので加速度ベクトルの収束が遅いです。
► スポイラーを表示
追記:バグを修正しました

珈琲

Re: ドリフトっぽい動きをするミサイル

#57

投稿記事 by 珈琲 » 10年前

ミサイルの挙動には以下の様な法則があります。
①毎フレーム、座標に、移動ベクトルが加算される。
②毎フレーム、移動ベクトルに、ミサイルの方向ベクトルと加速度の積が加算される。
③操作できるのはミサイルの方向ベクトルを回転のみ。

そして、目標への距離から衝突時間を求め、衝突時間から衝突座標を求めます。
①ミサイルから目標への(直線)ベクトルを基とした一次元座標系で、目標の速度・ミサイルの速度・ミサイルの加速度から、衝突時間(近似値)を求める。
②現在の目標の移動ベクトルと衝突時間の積と、目標座標の和から、衝突座標が求められる。

これらの条件下で
「ミサイルの移動ベクトルを衝突座標の向けるには、ミサイルの方向ベクトルをどのように回転させたらいいか」
とイメージです。

移動ベクトルは加速度ベクトル(方向ベクトル*加速度)を足し続けているので、まっすぐ進めばそのままどんどん加速します。
逆に、移動ベクトルと加速度ベクトルの方向が反対の時、移動ベクトルは徐々にスピードを落とし、加速度ベクトル方向へ移動し始めます。
この「徐々に」、の部分を慣性と言ってます。※厳密には違うかもしれません。

珈琲

Re: ドリフトっぽい動きをするミサイル

#58

投稿記事 by 珈琲 » 10年前

コード:

                if(  (direction_^neededA).z < 0.0 )     //外積の正負で左回りか右回りかを判別
これってどのような原理でわかるのでしょうか・・

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#59

投稿記事 by GRAM » 10年前

疑問というか確認なんですが
移動ベクトルとは単純に速度ベクトルということでいいですかね
ミサイルの方向ベクトルと加速度の積というのは「方向ベクトルと加速度の大きさ」の積ということでしょうか
(この場合方向ベクトルは正規化つまり大きさが1である必要があるでしょうしそう解釈します。加速度もベクトルなので一応確認です)
そういう意味だとしたら、「加速度ベクトルは正規化された方向ベクトルの定数倍」といったほうが正確かと思います。

文章を読んだ限り、自分の最後のプログラムを以下のように修正すればすべての条件が満たされると思います。

コード:

				//double maxRotate = cos(20*PHI/180);
				//if( Cos < maxRotate )   Cos =  maxRotate; 
とこの部分をコメントアウトする。
ただしそれが珈琲さんの理想とする挙動でないのだとしたら、それはコーディングする以前になにかがおかしいということだと思います。
珈琲 さんが書きました:これってどのような原理でわかるのでしょうか・・
direction_^neededAは2つのベクトルの外積をとるという意味で自分は使っています。
aとbの外積はaベクトルをbベクトルへ時計回りに回した場合の右ねじの進む向きなので、
二つのベクトルがxy平面上にあれば、zベクトルの正負でaベクトルに対してbベクトルが左か右かが判別できます。
ただし2Dでしか意味はあんまりないと思います。
ここら辺の処理は単にベクトルの回転量が知りたいだけなので、ほかにも書き方がありますし書きやすいように書けばよいかと

珈琲

Re: ドリフトっぽい動きをするミサイル

#60

投稿記事 by 珈琲 » 10年前

ありがとうございます。

>ミサイルの方向ベクトルと加速度の積というのは「方向ベクトルと加速度の大きさ」の積ということでしょうか
>(この場合方向ベクトルは正規化つまり大きさが1である必要があるでしょうしそう解釈します。加速度もベクトルなので一応確認です)

はい、そうです。

>そういう意味だとしたら、「加速度ベクトルは正規化された方向ベクトルの定数倍」といったほうが正確かと思います。
なるほど、この文章のほうが正確と・・・
私が言った文章だと、どんな感じに勘違いされるというか、誤解されてしまうのでしょうか?
ベクトルを使ったのこれが初めてなもので、後学のためにも・・・


>とこの部分をコメントアウトする。
理想とするものに近いです。先読みもしてるし、終末誘導も直線的です。
ですが、ソースコードが私にはちょっとわかりにくく、おんぶにだっこになってしまいますが、もし良ければ少し詳しいコメントを書いてもらえないでしょうか?
特に、ミサイルと目標の距離から目標の先読みするあたりが知りたいです。(私のコードでは0.0固定になってしまうので

珈琲

Re: ドリフトっぽい動きをするミサイル

#61

投稿記事 by 珈琲 » 10年前

> direction_^neededAは2つのベクトルの外積をとるという意味で自分は使っています。
> aとbの外積はaベクトルをbベクトルへ時計回りに回した場合の右ねじの進む向きなので、
> 二つのベクトルがxy平面上にあれば、zベクトルの正負でaベクトルに対してbベクトルが左か右かが判別できます。

おお、時計で言うなら12時の方向ベクトルと、右側にある12~6時までの方向ベクトルで外積をすると+、とかいう感じですか!
座標系によって正負が逆転するというのはこういうことですか

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#62

投稿記事 by GRAM » 10年前

珈琲 さんが書きました:>そういう意味だとしたら、「加速度ベクトルは正規化された方向ベクトルの定数倍」といったほうが正確かと思います。
なるほど、この文章のほうが正確と・・・
いえ、よく読むと文脈から明らかに違うということはわかるのですが、最初の言い方だと方向ベクトルと加速度ベクトルの内積か外積かどちらかかと
思ってしまいました。(ベクトルの掛け算は内積か外積、また方向ベクトルの大きさが1かどうかも分からなかったので)

コードの解説ですが、まず前提となる物理法則を説明します。
①静止している座標系に対し等速直線運動することなる座標系を慣性系という。
②もとの座標系における加速度と、慣性系における加速度は「同じ」である
③ターゲットがその座標系において固定点となるような慣性系を考えれば、ミサイルはその慣性系においてターゲットへ直線的に向かうよう
  アルゴリズムをくめばいい(これはある意味ターゲットの未来位置を予測している)
④慣性系においても加速度はもとの座標系と変わらないので、慣性系で加速度を求めて元の座標系に反映する(固定点に向かわせたほうが考えが楽だから)
⑤ミサイルの挙動のうち制御できるのは加速度ベクトルの向きだけなので、この方法で構わない

ということでまず慣性系における諸パラメーターを求めます。
①まず話を簡単にするため、ミサイルの座標を原点に取ります
Vec s = Starget - Smissile;

②次に慣性系におけるミサイルの速度を求めます。これはターゲットの速度をミサイルの速度から引くだけです
Vec v = Vmissile - Vtargetl;

③これで必要な変数はそろいました。
いまミサイルが最速でsにむかって飛んでいくには、sベクトルとvベクトルが同じ向きである場合です。
その理想的な速度ベクトルvはこうすれば求まります
1. sを正規化する。2. そのべくとるにvの大きさを掛ける
ということで videal = s.Normalize()*v.length となります。

④速度ベクトルを理想的な値にするために必要な加速度ベクトルを求める
neededA = videal - v;

⑤あとは自分の向きを変えて、加速度ベクトルをneededAになるよう調整します。
1: neededAの大きさが自分の加速度の最大値より大きい場合(if文がfalseの場合)
  自分の向きがneededAと同じ向きになるよう、回転させます。

2: neededAの大きさが自分の加速度の最大値より小さい場合(if文がtrueの場合)
  ひつような加速度だけ得られるよう目標となるneededAの値を調整します。
  そうすることで、あまった加速度ベクトルは速さを増やす意味での加速に回せます
  

コード:

if( nALength < accel )
				{
					Vec nan = neededA/nALength;									//まずneededAを正規化します
					Vec n = direction_ - nan*(nan*direction_);					//neededAに対し垂直で、かつdirectionとの角が90度以下のベクトルを求めます
					n = n.Normalize();											//nを正規化します
					double nLength = sqrt( accel*accel - nALength*nALength );	//最大加速度を斜辺、必要な加速度を底辺とするような直角三角形の高さを求めます
					n *= nLength;											
					neededA = n + neededA;										//ほんとうに必要な加速度ベクトルは底辺と高さのベクトルを足した斜辺方向のベクトルです
					nALength = neededA.Length();								//ということでneededAを更新します
				}
緑のベクトルが方向ベクトル、赤が必要な加速度ベクトル、黄色の長さが加速度ベクトルの最大値だとすれば
本当に必要な加速度を得るには、わざわざ赤の方向を向かなくても斜め方向の黄色のベクトルぶんだけで十分だということになります
無題.png
無題.png (4.1 KiB) 閲覧数: 19350 回

珈琲

Re: ドリフトっぽい動きをするミサイル

#63

投稿記事 by 珈琲 » 10年前

えーと、赤い矢印に移動ベクトルを合わせるにはそれより手前の斜めの黄色矢印でいいんですか?
斜めの黄色い矢印が目標への方向で、赤矢印が現在の進行方向で、緑矢印が正規化された方向ベクトル、ということではないんですか?

赤い矢印が必要なら、赤い矢印を軸に線対称にした方向に方向ベクトルが必要だと思うんですけど・・・
画像

イマイチ理屈をよく理解できないまま真似てみたのですが、やっぱり何か違う・・・

VScaleはベクトルとfloat値の掛け算です

コード:

			VECTOR RelativeInertia = VSub( TargetObject->GetInertia() , Inertia);
			VECTOR RelativePosition = VSub( TargetObject->GetPosition() , Position);

			VECTOR IdealLine =VScale( VNorm(RelativePosition) , VSize(RelativeInertia));
			VECTOR NeedAcceleration = VSub(IdealLine, RelativeInertia);

			float NeedALen =VSize(NeedAcceleration);

			float Accel = 0.03;
			
            if( NeedALen > 0.0001 ){
				if(NeedALen < Accel){
					VECTOR NNeedAcceleration = VNorm(NeedAcceleration);//正規化
					VECTOR n = VSub(AxisZ , VScale(NNeedAcceleration,VDot(NNeedAcceleration,AxisZ)));
					n = VNorm(n);
					float nLength = sqrt( Accel*Accel - NeedALen*NeedALen );
					n = VScale(n,nLength);
					NeedAcceleration = VAdd(n,NeedAcceleration);
				}
			}

			AxisZ = VNorm(NeedAcceleration);//方向ベクトルに設定

			VECTOR Thrust = VScale(AxisZ,Accel);//推力

			Inertia = VAdd(Thrust,Inertia);//移動ベクトルを更新

			Position = VAdd(Position,Inertia);座標を更新

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#64

投稿記事 by GRAM » 10年前

珈琲 さんが書きました:えーと、赤い矢印に移動ベクトルを合わせるにはそれより手前の斜めの黄色矢印でいいんですか?
斜めの黄色い矢印が目標への方向で、赤矢印が現在の進行方向で、緑矢印が正規化された方向ベクトル、ということではないんですか?
残念ながらあまり意図が伝わっていないのではないかと思います。
自分はこう定義しました。
「緑のベクトルが方向ベクトル、赤が必要な加速度ベクトル、黄色の長さが加速度ベクトルの最大値」だと。
どこにも「目標への方向」なんて単語は出ていないと思います。

またこの話を一般化してもらっても困ります。
あくまでこの話は

コード:

if( nALength < accel )
の場合だけです
つまり自分の加速度の大きさの最大値が必要な加速度の大きさよりも大きいのなら、必要な加速度を表すベクトルと同じ方向を向いてしまったら
余計に加速度ベクトルを加算しちゃう。だから必要な分だけ加速するよう向きを調整しよう。ということを言っているのです
要はif文の中身は最後にターゲットへまっすぐ向くようにする処理なのです。
まずif文の中身以外の処理を理解してください。
もしなぜこのif文が必要なのかを理解していただけないのでしたら、if文全体をコメントアウトして何が起こるかを調べてください。

珈琲

Re: ドリフトっぽい動きをするミサイル

#65

投稿記事 by 珈琲 » 10年前

なんとなーくですが、理解出来た・・・とおもいます
必要なベクトルの長さちょうどにするように角度をずらすというか・・・

Cosが2回定義されるのですが、両方共視覚というか・・・

コード:

                double Cos = (neededA*direction_)/nALength;
                if( Cos > 1.0 ) Cos = 1.0;
                if( Cos < -1.0 ) Cos = -1.0;
                double maxRotate = cos(20*DX_PI/180);          //回転量の最大量を設定(10°)
                if( Cos < maxRotate )   Cos =  maxRotate;   //回転量が最大量より大きければ(コサインの性質に注意)丸め込み
                double Sin = sqrt( 1.0-Cos*Cos );
                if(  (direction_^neededA).z < 0.0 )     //外積の正負で左回りか右回りかを判別
                {
                    Sin = -Sin;
                }
                direction_ = VRotate2D( direction_, Sin, Cos );             //ベクトルを回転
                direction_.Normalize();
VRotate2Dもよく理解できず・・・atan2みたいなものでしょうか?
2次元から3次元に起こすのがちょっと困難です・・・

coffee

Re: ドリフトっぽい動きをするミサイル

#66

投稿記事 by coffee » 10年前

加速し終わってから、方向転換するイメージ・・?

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#67

投稿記事 by GRAM » 10年前

珈琲 さんが書きました:なんとなーくですが、理解出来た・・・とおもいます
必要なベクトルの長さちょうどにするように角度をずらすというか・・・
その通りです。
珈琲 さんが書きました: Cosが2回定義されるのですが、両方共視覚というか・・・
VRotate2Dもよく理解できず・・・atan2みたいなものでしょうか?
2次元から3次元に起こすのがちょっと困難です・・・
初めの 
double Cos = (neededA*direction_)/nALength;
はベクトルの内積の定義から明らかだと思います。 neededAとdirection_の二つのベクトルの角度のコサインを得ます

次に計算誤差によりcosの値が-1.0~1.0に収まらない場合があるので、丸め込みます。
double maxRotate = cos(20*DX_PI/180); //回転量の最大量を設定(10°)
ここはこめんとあうとがまちがってました。20度に設定してますね。
cosは0~180度で単調減少(1.0⇒-1.0)なので、角度が20度以上⇒Cos(20°)>Cos(Θ) ※ΘはneededAとdirection_の二つのベクトルの角度
となります
if( Cos < maxRotate ) Cos = maxRotate;
角度が最大角度より大きいのなら、コサインの値を丸め込みます。
Sinは三角関数の公式よりcosから求まります

コード:

double Sin = sqrt( 1.0-Cos*Cos );
if(  (direction_^neededA).z < 0.0 )     //外積の正負で左回りか右回りかを判別
 {
         Sin = -Sin;
}
sinとcosが分かればその対応する角度分だけ2Dでベクトルを回転させるのは容易です。
(角度を求めてからその角度分回転させるという処理を組んでもいいのですが、acosで角度を求めてそこからcosを割り出すという二度手間なので
やめています)
VRotate2D( direction_, Sin, Cos )は第一引数のベクトルを第二第三引数のsin, cosの値に従って回転させる関数です。(2D専用です)
詳細は2x2回転行列について勉強してください。(何も考えなくてもこの通りですが)
あるベクトルを2DでΘだけ回転させるには
VRotate2D( Vec, sin(Θ), cos(Θ) )と使います。
3次元の場合は珈琲さんがやっているようにクォータニオンを使えばいいとおもいます。
それはアルゴリズムを実現するための手段であって、重要なことではないというのが自分の考えです。
(クォータニオンを使おうが、回転行列を使おうが結果が変わらないのであれば好きなように書けばよい)

ちなみに私は一応3Dに簡単に拡張できるようコードを書いたつもりです。
Vecクラスは3Dに初めから対応しています。
3Dに直すのに必要な変更は以下の回転に関する部分だけです

コード:

double Cos = (neededA*direction_)/nALength;
                if( Cos > 1.0 ) Cos = 1.0;
                if( Cos < -1.0 ) Cos = -1.0;
                double maxRotate = cos(20*PHI/180);          //回転量の最大量を設定(10°)
                if( Cos < maxRotate )   Cos =  maxRotate;   //回転量が最大量より大きければ(コサインの性質に注意)丸め込み
                double Sin = sqrt( 1.0-Cos*Cos );
                if(  (direction_^neededA).z < 0.0 )     //外積の正負で左回りか右回りかを判別
                {
                    Sin = -Sin;
                }
                direction_ = VRotate2D( direction_, Sin, Cos );             //ベクトルを回転

2つのベクトルの角度を求め、角度の最大値を固定。
その角度分だけdirectionを回転させるという処理を3Dように書けばよいのです。
自分はQuaternionを書きませんでしたが、概要はこんな感じでしょう

コード:

double Cos = (neededA*direction_)/nALength;
double maxRotate = cos(20*PHI/180);       
if( Cos < maxRotate )   Cos =  maxRotate;
Vec normal = neededA^direction_;              //2つのベクトルに垂直なベクトルを求める
Quaternion q = CreateQuaternion( normal, acos( Cos ) );   //Vecを回転軸に角度acos( Cos )だけ回転させるクォータニオンを生成
Vec direction_ = q.apply(direction_);
 

珈琲

Re: ドリフトっぽい動きをするミサイル

#68

投稿記事 by 珈琲 » 10年前

やっとプログラムのブロックごとの目的がわかったような、、気がします。
3Dでも、目標に向かって飛んで行くようになりました。

ですが、なんか、やっぱり飛んでる目標にまったくあたりませんね・・・
直進してるだけの敵にも当たらないので、・・・またコードを間違ってるのでしょうか

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ドリフトっぽい動きをするミサイル

#69

投稿記事 by ISLe » 10年前

現実のミサイルは当たらないものだと思いますけど。

珈琲

Re: ドリフトっぽい動きをするミサイル

#70

投稿記事 by 珈琲 » 10年前

そ、そうなんですか?
GRAMさんが2Dで再現してくれたコードでは、目標にしっかり命中していたので
少なくとも2Dから3Dに起こした、同じアルゴリズム(のつもり)のコードなら当たると思ったのですけど

当たる手前で直前でミサイルが反転するようなハズレ方をして、なんか、1フレーム分ずれてるのかなぁと・・

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#71

投稿記事 by GRAM » 10年前

珈琲 さんが書きました:ですが、なんか、やっぱり飛んでる目標にまったくあたりませんね・・・
直進してるだけの敵にも当たらないので、・・・またコードを間違ってるのでしょうか
自然な動きに見えるかはともかくとして、
アルゴリズムを完全に理解したうえで、かつ通りに実装していれば3Dでも少なくとも目標には命中するはずです。
そこまでいけば初めて実装の間違いの有無を探す時が来たのではないですかね?
(ただもしかしたら外積が0になっている例外の処理ができてないのかもしれないですね。
自分の最後のコードはあくまでもイメージなので、当然起こりうる例外は実際にはつぶしていただく必要があると思います。)
ISLe さんが書きました:現実のミサイルは当たらないものだと思いますけど。
このトピックの話題とはずれるかもしれませんが、妨害装置を考えないのであれば現実のミサイルはかなりの確率で命中すると思いますよ。
単純な機動力でいえば戦闘機といえども所詮は遅鈍な金属の塊ですからね。人も乗ってますし。

珈琲

Re: ドリフトっぽい動きをするミサイル

#72

投稿記事 by 珈琲 » 10年前

極稀にまったく曲がろうとしないで、加速度全快で正面を突き進んでいくミサイルが生まれるのですが、これは何が原因でしょうか?
ミサイルが当たらないというのと関係はありそうですが・・・
一瞬ならともかく彼方まで飛んで行くので、なんだろうなぁと

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: ドリフトっぽい動きをするミサイル

#73

投稿記事 by GRAM » 10年前

珈琲 さんが書きました:極稀にまったく曲がろうとしないで、加速度全快で正面を突き進んでいくミサイルが生まれるのですが、これは何が原因でしょうか?
ミサイルが当たらないというのと関係はありそうですが・・・
一瞬ならともかく彼方まで飛んで行くので、なんだろうなぁと
といわれましても、この内容では残念ながら私の力ではどうすることもできません。
お力になれずに申し訳ないのですが、自分に同じ問が投げかけられたと想定してください、としか。

閉鎖

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