web-dev-qa-db-ja.com

バウンス角の計算方法は?

私はしばらくそれをいじりましたが、私は単にそれを理解することができません。

私はミサイルを発射する戦車を作り、ミサイルが壁にぶつかったとき、それらを跳ね返らせたいが、直角に跳ね返らせたい。

今のところ、障害物はありません。ミサイルは私が作ったviewportRectangleの外に出ると跳ね返ります。

私が探している解決策は非常に高度ですか?

比較的簡単な方法はありますか?

62
Moulde

これを行う簡単な方法は、角度を計算する代わりにミサイルの速度を使用することだと思います。 xVelocityyVelocityを持つミサイルがあり、その動きを水平および垂直に表しているとします。これらの速度は、左、右、上、または下を表すために正または負にすることができます。

  • ミサイルが上部または下部の境界に当たると、yVelocityの符号が反転します。
  • ミサイルが左または右の境界に当たると、xVelocityの符号が反転します。

これにより、反対側の軸の動きが同じになります。

ChrisFの答え から画像を借用して、ミサイルが位置Iで開始したとしましょう。

Angle of Reflection

xVelocityyVelocityが両方とも正の場合(2Dグラフィックでは通常、右と下が正である)、ミサイルは指示された方向に移動します。の値を割り当てましょう

xVelocity = 3
yVelocity = 4

ミサイルが位置[〜#〜] c [〜#〜]で壁に当たった場合、そのxVelocityは変更されません。しかし、そのyVelocityは-4に反転して、上方向に戻りますが、右方向に進み続ける必要があります。

この方法の利点は、ミサイルのxPositionyPositionxVelocity、およびyVelocityのみを追跡する必要があることです。これら4つのコンポーネントとゲームの更新レートだけを使用すると、ミサイルは常に正しい位置に再描画されます。まっすぐな角度ではない、または動いているより複雑な障害物に遭遇すると、角度よりもXおよびYの速度で作業する方がはるかに簡単になります。

66
Bill the Lizard

壁は座標軸と整列しているため、特別なケースコードを記述するのが理にかなっていると思うかもしれません(垂直壁の場合は速度のx座標を無効にし、水平壁の場合は速度のy座標を無効にします) )。ただし、垂直と水平の壁でゲームがうまく機能したら、おそらく次に考えるのは「任意の角度の壁はどうですか?」そのため、最初から一般的なケースについて考える価値があります。

一般的なケースでは、ミサイルに速度vがあり、表面法線n

Missile with vector v about to obliquely hit a wall with surface normal n.

vを壁に垂直なコンポーネントuwそれと平行。

Right-angled triangle with hypotenuse for v, short side u parallel to wall and long side w parallel to wall.

どこで:

u=(v n/nnn
w=v-u

ここで、vnベクトルvnのドット積 。計算方法の説明については、リンクを参照してください。内積nnは、長さの2乗に評価されます法線ベクトル;法線を常に unit vector の形式で保持する場合、nn=1。除算は省略できます。

バウンス後、壁に平行な運動の成分は摩擦fの影響を受け、壁に垂直な成分は弾性の影響を受けます。これは 反発係数r

したがって、衝突後の速度はv '= fw-ru。 Ina完全に弾性、摩擦のない衝突、v '=w- u;つまり、Billの答えにある図のように、衝突点での動きが法線について反映されます。

このアプローチは、3次元でも同じように機能します。

(明らかにこれは跳ね返りの非常に単純化された概念です; angular運動量または変形を考慮しません。しかし多くの種類のビデオゲームではこの種の単純化は完全に適切です。)

188
Gareth Rees

完全な粒子(&光)の場合、この図(commons.wikimedia.orgから)に示されているように、反射角は入射角に等しくなります。

Angle of Reflection

Googleで「反射角」(引用符なし)を検索します。

オブジェクトの弾力性と材質、障害物を考慮すると、少し複雑になります;)

9
ChrisF

私はこの問題を抱えていましたが、私が見つけた唯一の方法は衝突軸を分離することでした!

それを試してみてください:

x += velocity * Math.cos(angle * Math.PI /180);
y += velocity * Math.sin(angle * Math.PI /180);

if (x < 0 || x > canvas.width) {
     angle = 180 - angle;   
}
else if (y < 0 ||y > canvas.height) {
     angle = 360 - angle; 
}

これがお役に立てば幸いです!

6

あなたが求めている特定の物理学の質問とは別に、ウェンディ・スタラーによる「ゲームプログラマーのための数学と物理学の始まり」という本をお勧めします。ゲーム/物理プログラミングプロジェクトに非常に役立ちました。

この本に付属するコードはC++ですが、C#を知っていれば、変換は非常に簡単です。

良いものを持っている!

5
itsmatt

まったく複雑ではありません-擬似コード:

angleObjectHitWall = a;
bounceAngle = 180-a;

もちろん、これは非常に単純な計算であり、材料、重力、まっすぐではない壁などの要因を考慮し始めると、まったく無関係になります...

3
Yuval Adam

180-aは、Xが増加しているときに上面で跳ね返るだけでない限り、すべてのインスタンスで機能するわけではありません。

方向性の1つは、XNAフォーラムまたはXNAサンプルコードの入手です。 C#であり、ゲームを構築するためのものです。 XNAでゲームを構築したいとは言いませんが、すばらしいツールであり、無料です。

3

これは実際には物理学の質問なので、もしあなたが物理学者でないなら(そしてあなたがこの質問をしているので、あなたはそうではないと思います)、それを正しくするためには多くの読書とブレーンストーミングが必要になります。

this ウィキペディアのエントリを読んで、質問の深さに関する基本的な考えを理解することをお勧めします。

「もっともらしい」ようにしたいだけなら、あまり気にせず、Bill the Lizardの答えを使いますそれを正しくするためには、かなりの冒険があります。これを怖がらせないでください!がんばろう!

0
David Božjak