ニートが頑張るブログ

ニートが現実逃避するために創作活動など色々とカオスに頑張ってみる
ニートが頑張るブログ TOP  >  ニートメソッド >  3Dシューティングのレーザープログラミング

3Dシューティングのレーザープログラミング

「長さと太さを持った3Dのレーザーとの当たり判定」をどうやるか
割と簡単なようで、結構奥が深い様な気がします。

今回自分がやったやり方の解説をします。

レーザービーム
基本的に使う変数とかはこんな感じとします。

カマキリのx座標がahox、y座標がahoy
レーザーのx座標がbakax、y座標がbakay
レーザーの太さがwidth、長さがlength
レーザーの角度がrot

こんだけ

これらの変数を使って、
カマキリレーザーの範囲内にいるかどうか」の判定をしていきます。
(今のところ、分かりやすくするために2Dにしています)


で、そのやり方も色々考えられますが、
一番賢いのを考えよう、という話。


 

①中学生的やり方

レーザービーム

レーザーの角度rotから出せるタンジェント君 tan(rot)を使って、
直線を4本作ります。(ピンク色の線、つまりレーザーの範囲そのもの)
直線の通る点(a,b)は、length、widthをrot回転させた値から出せます。

そして、その4本の直線と、
x=ahox、y=ahoyとの交点を出します。

その交点と、カマキリのahox、ahoyとの大小を比較すれば、
それが当たり判定になります。


これが中学生的なやり方だと思います。
割と実直なやり方です。

このやり方だと、3次元に拡張する場合は、
「4直線との上下関係」ではなくて、「6面との裏表関係」になります。
その辺がメンドクサイところですね。


あと、直線のベクトルを出して、
そのベクトルに対してカマキリがどちら側にいるかを
判定していくのも、本質的にはこれと同じことです。


②高校生的やり方

レーザービーム

実際自分がググっていて出てきたやり方がこれです。
(ていうかこういうのしか出てこないからこそ、こんな記事を書いている)

カマキリからレーザーへ引いた
垂線y=-1/tan(x-ahox)+ahoy
その垂線と、レーザーy=tan(x-bakax)+bakayとの交点を求めます。
それが垂線の足です。(きみどり色の点)


ここで、
レーザーの中心から、垂線の足との距離を求めることで、
カマキリがレーザーの長さ内にいるかの判定が出来ます。
(この図ではカマキリは長さ内にいます)

さらに、
垂線の足から、カマキリahox,ahoyとの距離を求めることで、
カマキリがレーザーの太さ内にいるかの判定が出来ます
(この図ではカマキリは太さ内にいません)

この組み合わせで、当たり判定になります。

で、なんかややこしそうに書いてますが、
「点と直線への距離」とか、そういうのは公式化できるので
実際の重さは①と変わらないでしょう。


これが高校生的なやり方だと思います。

このやり方の場合のメリットは
「四角いところてんのレーザー」
「パスタのように丸いレーザー」にも出来るところです。

(3次元でも垂線の距離とかは変わらないわけですから)

中学生的なやり方でパスタにするのは難しいと思います。


③ニート的やり方

レーザービーム

で、これが今回やった、ニートのやり方
メチャクチャ単純です。

全体の座標系を、レーザーの中点bakax,bakayを中心にして
-rot回転させるだけです。

といっても、実際にはカマキリ側の座標を回転させるだけでいいのです。

ahox2 = ahox - bakax
ahoy2 = ahoy - bakay

として、
ahox = ahox2*cos + ahoy2*sin
ahoy = ahoy2*sin - ahoy2*cos

とするだけ。

するともう、あとはこれだけです。
if( |ahox| < length) { 死ぬ }
if( |ahoy| < width ) { 死ぬ }



メチャクチャ単純です。
もはやただの不等式なので、
小学生的やり方といっていいかも知れない。


でも、プログラムってそういうことではないですか?
ちょっと工夫すればムチャクチャ軽いトコロに持っていけるのです。


毎フレーム、レーザーとの当たり判定を計算するのに
ベクトルとか垂線法線いるのか、という話です。


ここで逆回転に使っているrotのsinやcosだって、
実際はレーザーを描画するときに既に計算しているので
垂線やベクトルのようにわざわざ出す必要もなく、すぐ使えます。


そして3Dへの拡張、パスタ化も簡単だということ。


レーザービーム

実際3Dのレーザーでは、Z座標が加わると同時に、
レーザーを管理する角度がY軸回転とZ軸回転の2軸になります。


レーザービーム

で、これも同様に
カマキリサイドZ軸逆回転させてからY軸逆回転させると、
カマキリにとってレーザーは、
傾きを持たないタダの直方体に成り下がります。

だから、やはりもうこれだけでいいのです。
if( |ahox| < length) { 死ぬ }
if( |ahoy| < width ) { 死ぬ }
if( |ahoz| < width ) { 死ぬ }



3Dのレーザーを実際に描画する際に
レーザーの先端の座標をY軸回転させてからZ軸回転させているわけですが、
その時のsinとcosをそのまま流用すれば逆回転は簡単にできるのです。


そしてこの時、
if( ahoy3^2 + ahoz^2 < width^2 ) { 死ぬ }
とするだけで、
ところてんレーザーを簡単にパスタレーザーにすることが出来ます。

ピタゴラスさまさまですね。


・・・以上レポっす。チラシの裏すんません。

関連記事
[ 2011/06/05 17:31 ] ニートメソッド | TB(0) | CM(2)
ダメージ判定も含めた当たり判定
 ほとんど考えずに書いてます。

 レーザー光線っちゅーと太さが変わらずにどこまでも進むような気はするんですが、やっぱり距離の自乗に反比例して威力が減ってゆくような気はするのですよ。その場合、概念上のレーザーはところてんでもなくパスタでもなく、円錐形になるわけですが。

 で、レーザー光線を(長さ固定の)ベクトルで表現したときに、カマキリの位置との内積を取ってみたらどうかと思うんですよ。

 するってぇと、まぁ、なんかしらの値は出ますわな? で、それをレーザー光線のノルムとカマキリの位置のノルムで割ると、カマキリの向きとレーザー光線の向きの相関(角度のコサイン)が出るわけです。この値は、1(向き一致)と-1(正反対)の間にあるわけです。

 で、こいつの分子と分母を逆転したらどないだ?みたいなコトを考えるわけですよ。

 カマキリ位置ノルムをレーザー光線とカマキリ位置の内積で割ると、レーザー光線がカマキリに与える“威力”が求められそうな気がするわけで、それが0より大きくて、レーザー光線ノルムに比例した一定値よりも大きければ、“当たり”であると同時にその“威力”も求められるんではないかと。

 実際には、三角関数なんかの初等関数の計算にかかる手間というのは乗算一回分とそう変わらないので、効率っちゅー意味では大した意味はないわけですが、考え方としてはあるんでないかと思います。

 理屈通ってない可能性はあるので、話半分に聞いといてくれるとよろしいんですが。
[ 2011/06/06 13:26 ] [ 編集 ]
Re: ダメージ判定も含めた当たり判定
> Mr.Moto さん


>レーザー光線っちゅーと太さが変わらずにどこまでも進むような気はするんですが

それは分かりますww
自分がレーザーの長さを有限にしているのは、色々理由があります。

・レーザー攻撃が無限の長さだと、
 避けるための軸が「1軸」しかないワケですからゲーム性が低くなります。
 要は避けにくすぎるということです。

・無限のレーザーは、描画しづらい。
 自分は、先端の座標に合わせてスプライトを引き伸ばして、レーザーを描画しているので
 長さ無限のレーザーだと色々面倒です。はみ出ますw

そんな感じで、長さは有限なのですね。
それに、仮に無限長レーザーにするなら、
単にlengthの判定を消せばいいだけですから。


>やっぱり距離の自乗に反比例して威力が減ってゆくような気はするのですよ。その場合、概念上のレーザーはところてんでもなくパスタでもなく、円錐形になるわけですが。

その場合は、無限長と同じで、常に長さ方向に当たり判定がある上で、
ダメージを 1/(Z座標差)^2 にすればいい感じですかね?


自分が「パスタ」にこだわるのは、
ところてんの当たり判定が、多少アンフェアであるからです。

ところてんは、当たる場所と当たらない場所の比が、
最大で√2倍もあるわけですから。

そういうのが、パスタだとなくなりますからね。
条件を「x^2 + y^2 + z^2*定数」として、定数を1以下にすれば、
卵型の当たり判定にもできます。


>  するってぇと、まぁ、なんかしらの値は出ますわな? で、それをレーザー光線のノルムとカマキリの位置のノルムで割ると、カマキリの向きとレーザー光線の向きの相関(角度のコサイン)が出るわけです。この値は、1(向き一致)と-1(正反対)の間にあるわけです。

まさに、内積をそれぞれのベクトルの長さで割ると、コサインがでますよね。
それはもう、定義通りですね。

そして、確かにそのコサインによって、レーザーの一定範囲内に入るかどうかの判定になりますし、
レーザーの威力が出そうですね。

自分のやり方の場合、
ベクトルとか考える必要もなく長さ方向の比較に持ち込めるので
内積を長さで割る必要もなく、そのコサインはタダの比として算出できます。
ここにはそういう事が書いてあります。


ーーーーーーーーーーーーーーーーーーーーー
でもどうなんでしょうね。

たしかにレーザーの減衰とかをリアルに考えればそうなんでしょうが、
やはりゲームというのは
「一回当たったら、一つダメージを受ける」という風に
シンプルにしておいた方がいいような気もします。


「レーザーを近くで喰らえば喰らうほど痛い」ということにもなりますからね。
シビアですね。


でもそういう、当たったときの距離によってダメが変わるというのは、
ボスの攻撃とかで考えてみようかなぁと思います。
(コレも言ってるだけですがw)
[ 2011/06/07 21:10 ] [ 編集 ]
コメントの投稿












管理者にだけ表示を許可する
トラックバック
この記事のトラックバックURL

月別カレンダー
04 ≪│2017/05│≫ 06
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 - - -