2012-03-31 9 views
2

C++で基本的に円を動かし、2つの円が衝突したときにビリヤードボールと同じようにリコシートする小さな物理シミュレーションを作成しています。円がお互いに衝突すると、ほとんどの場合、無限に実際に減速するか、お互いにくっついて静止しているように見えます。場合によっては、1つのボールのみが衝突でリバウンドし、他のボールは軌道を保持することがあります。これは単なる2Dシミュレーションです。円周衝突リバウンドが正しく機能しない

だからここに私は検出/跳ね返るロジックを持っているものです。

bool Ball::BallCollision(Ball &b2) 
{ 
    if (sqrt(pow(b2.x - x, 2) + pow(b2.y - y, 2)) <= b2.radius + radius) // Test for collision 
    { 
     normal[0] = (x - (x + b2.x)/2)/radius; // Finds normal vector from point of collision to radius 
     normal[1] = (y - (y + b2.y)/2)/radius; 
     xvel = xvel - 2 * (xvel * normal[0]) * normal[0]; // Sets the velocity vector to the reflection vector 
     yvel = yvel - 2 * (yvel * normal[1]) * normal[1]; 

     ////x = xprev; // These just move the circle back a 'frame' so the collision 
     ////y = yprev; // detection doesn't detect collision more than once. 
        // Not sure if working? 
    } 
} 

私は私の機能と間違っているかを把握することはできません。事前に助けてくれてありがとう!

編集

void Ball::Move() 
{ 
    xprev = x; 
    yprev = y; 
    x += xvel; 
    y += yvel; 
} 

void Ball::DrawCircle() 
{ 
    glColor3ub(100, 230, 150); 
    glBegin(GL_POLYGON); 
    for (int i = 0; i < 10; i++) 
    { 
     angle = i * (2*3.1415/10); 
     newx = x + r*cos(angle); 
     newy = y + r*sin(angle); 
     glVertex2f(newx, newy); 
    } 
    glEnd(); 
} 

ループ: すべての変数は、フロート

関数として宣言されている

run_prev.clear(); // A vector, cleared every loop, that holds the Ball objects that collided 

    for (int i = 0; i < num_balls; i++) 
    { 
     b[i].Move(); 
    } 

    for (int i = 0; i < num_balls; i++) 
    { 
     b[i].WallCollision(); // Just wall collision detecting, that is working just fine 
    } 

    //The loop that checks for collisions... Am I executing this properly? 
    for (int i = 0; i < num_balls; i++) 
    { 
     for (int j = 0; j < num_balls; j++) 
     { 
      if (i == j) continue; 
      if (b[i].BallCollision(b[j]) == true) 
      { 
       run_prev.push_back(b[i]); 
      } 
     } 
    } 

    for (int i = 0; i < num_balls; i++) 
    { 
     b[i].DrawCircle(); 
    } 

    //xprev and yprev are the x and y values of the frame before for each circle 
    for (int i = 0; i < run_prev.size(); i++) 
    { 
     run_prev[i].x = run_prev[i].xprev; 
     run_prev[i].y = run_prev[i].yprev; 
    } 
+0

丸めなどのキャストエラーを除外できるかどうかを知るために、変数のタイプを通知する必要があります。 – vsz

+0

私はあなたがそのような普通を計算する理由を理解していません。彼らはユニットの長さを持っていますか? –

+0

私は彼らがそうだと思った。私がどこにいなくても私を修正してください。 – Christian

答えて

2
  1. ボールが(動きベクトルを反映)衝突彼らはお互い向かって移動している場合にのみ行います。互いから離れる場合は、衝突を処理しないでください。このルールを破ると、それらは一緒に接着されます。
  2. 衝突を処理するときは、両方のボールを一度に更新します。一度に1つのボールを更新しないでください。
  3. 移動ベクトルの調整が正しくありません。ボールは、異なる速度で動くことができるので、お互いに対して反射することはありません。

正しい動きの調整が(と仮定したボールが等しい質量を持っている)そのようになっているはずです。

pos1 and pos2 = positions; 
v1 and v2 are movement vector (speed); 
n is collision normal == normalize(pos1 - pos2); 
collisionSpeed = dot((v2-v1), n); 
collisionSpeed *= elasticy; (0.0..1.0); 
v1 = v1 - dot(v1, n); 
v2 = v2 - dot(v2, n); 
v1 -= scale(n, collisionSpeed * 0.5); 
v2 += scale(n, collisionSpeed * 0.5); 

は、ニュートン法(特にインパルス)をチェックし、式を理解するために。あるいは、Chris Heckerのゲーム物理に関する論文をチェックしてください。

+0

ありがとうございます。彼らがお互いに向かって動いているかどうか、どのようにテストしますか? – Christian

+0

@ vorbis5:上記の例では、collisionSpeedの符号を確認します。 – SigTerm

+0

誰もが束を助けてくれました。ありがとうございました! – Christian

0

通常の計算あなたのやり方が間違っています。 (x + b2.x)/ 2は、ボールの半径が等しくない場合、衝突の点である必要はない。

+0

これまでのシミュレーションのセットアップ方法は、すべての半径が等しいことです。 – Christian

1

この関数をどのように呼び出すのかはっきりしませんが、私は問題があると思います。

Ball ballABall ballBが現在のフレームで衝突しているとし、ballA.BallCollision(ballB)を実行したとします。

これは、メンバ変数ballAを更新し、フレームに戻します。しかし、ballBの位置や軌跡は更新されません。

ballA.BallCollision(ballB)を呼び出したときにballAがフレームに戻ったため、逆も同様に呼び出しても(ballB.BallCollision(ballA))、衝突を検出しません。

+0

非常に良い洞察力、私は少し私のコードを編集し、それが私の問題を解決するかどうか見てみましょう! – Christian

+0

ええ、問題はまだあります。遅い円が別のものと衝突すると、両者は一緒に固執して動くのをやめ、リバウンド自体は少し外れているように見えます。奇妙なことに、私のコードをもっと上に載せて、もう一度見てみてください。 :) – Christian

1

私はあなたのコードを詳細には見ていませんが、このタイプの衝突は運動量フレームの中心でのみ機能することを考慮していません。さて、私はあなたのボールが同じ質量のものであると仮定します。あなたがすることは、2つの運動量(または同じ質量を持つので速度)の平均をとり、その平均から速度を減算することです。計算を実行し、平均を戻します。 Hereは私がこれに関連するかもしれない質問です。

+0

恐ろしい、私はそれを試してみましょう。 – Christian

+0

申し訳ありませんが、私はそれを試しました、そして今ボールはまだ固まっていて、一緒に詰まっていますが、少なくとも衝突してぶつかると静かにならないでしょう。私はここでの主な問題は、ボールが衝突したときのボールのこだわりです。 – Christian

+0

あなたはボールを互いに遠くに動かして、もはや交差しないようにするコードがありますか?そして私はあなたの法線を計算する方法について完全にはわかりません... – slartibartfast

関連する問題