0

ボールが壁やお互いに跳ね返るアプリケーションを作ろうとしています。壁からの跳ね返りはうまくいきますが、お互いに跳ね返らせるのに苦労しています。別のボールで跳ね返らせるために使用しているコードは次のとおりです(テスト用にボールは2つしかありません)

 // Calculate the distance using Pyth. Thrm.
        GLfloat x1, y1, x2, y2, xd, yd, distance;
        x1 = balls[0].xPos;
        y1 = balls[0].yPos;
        x2 = balls[1].xPos;
        y2 = balls[1].yPos;

        xd = x2 - x1;
        yd = y2 - y1;

        distance = sqrt((xd * xd) + (yd * yd));

        if(distance < (balls[0].ballRadius + balls[1].ballRadius))
        {
            std::cout << "Collision\n";
            balls[0].xSpeed = -balls[0].xSpeed;
            balls[0].ySpeed = -balls[0].ySpeed;

            balls[1].xSpeed = -balls[1].xSpeed;
            balls[1].ySpeed = -balls[1].ySpeed;

        }

何が起こるかというと、それらはランダムに跳ね返ったり、お互いをすり抜けたりします。私が見逃している物理学はありますか?

編集:これが完全な機能です

// Callback handler for window re-paint event 
void display()  
{    
    glClear(GL_COLOR_BUFFER_BIT);    // Clear the color buffer 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);


    // FOR LOOP 
    for (int i = 0; i < numOfBalls; i++) 
    { 
        glLoadIdentity();                // Reset model-view matrix 
        int numSegments = 100; 
        GLfloat angle = 0; 
        glTranslatef(balls[i].xPos, balls[i].yPos, 0.0f);  // Translate to (xPos, yPos) 

        // Use triangular segments to form a circle 
        glBegin(GL_TRIANGLE_FAN); 
        glColor4f(balls[i].colorR, balls[i].colorG, balls[i].colorB, balls[i].colorA);   
        glVertex2f(0.0f, 0.0f);       // Center of circle 

        for (int j = 0; j <= numSegments; j++) 
        { 
            // Last vertex same as first vertex 
            angle = j * 2.0f * PI / numSegments;  // 360 deg for all segments 
            glVertex2f(cos(angle) * balls[i].ballRadius, sin(angle) * balls[i].ballRadius); 
        } 
        glEnd(); 

        // Animation Control - compute the location for the next refresh 
        balls[i].xPos += balls[i].xSpeed; 
        balls[i].yPos += balls[i].ySpeed; 

        // Calculate the distance using Pyth. Thrm.
        GLfloat x1, y1, x2, y2, xd, yd, distance;
        x1 = balls[0].xPos;
        y1 = balls[0].yPos;
        x2 = balls[1].xPos;
        y2 = balls[1].yPos;

        xd = x2 - x1;
        yd = y2 - y1;

        distance = sqrt((xd * xd) + (yd * yd));

        if(distance < (balls[0].ballRadius + balls[1].ballRadius))
        {
            std::cout << "Collision\n";
            balls[0].xSpeed = -balls[0].xSpeed;
            balls[0].ySpeed = -balls[0].ySpeed;

            balls[1].xSpeed = -balls[1].xSpeed;
            balls[1].ySpeed = -balls[1].ySpeed;

        }
        else
        {
            std::cout << "No collision\n";
        }

        // Check if the ball exceeds the edges 
        if (balls[i].xPos > balls[i].xPosMax)  
        { 
            balls[i].xPos = balls[i].xPosMax; 
            balls[i].xSpeed = -balls[i].xSpeed; 
        }  
        else if (balls[i].xPos < balls[i].xPosMin)  
        { 
            balls[i].xPos = balls[i].xPosMin; 
            balls[i].xSpeed = -balls[i].xSpeed; 
        } 

        if (balls[i].yPos > balls[i].yPosMax) { 
            balls[i].yPos = balls[i].yPosMax; 
            balls[i].ySpeed = -balls[i].ySpeed; 
        }  
        else if (balls[i].yPos < balls[i].yPosMin)  
        { 
            balls[i].yPos = balls[i].yPosMin; 
            balls[i].ySpeed = -balls[i].ySpeed; 
        } 
    } 
    glutSwapBuffers();  // Swap front and back buffers (of double buffered mode) 
} 

**注: 関数のほとんどはnumOfBalls、カウンターとして for ループを使用しますが、衝突をテストするために、2 つのボールのみを使用しているため、balls[0]andballs[1]

4

2 に答える 2

1

考慮すべき点がいくつかあります。

(xSpeed,ySpeed) の長さが にほぼ匹敵する.ballRadius場合、シミュレーションのクロックの「ティック」(1 ステップ) の間で 2 つのボールが互いに「通り抜ける」ことができます。完全に垂直に移動している2 つのボールを考えてみましょう.ballRadius。実際には、それらは明らかに衝突しますが、.ySpeed~の場合、シミュレーションでこのイベントを見逃すのは簡単です.ballRadius

次に、ボールのベクトルを変更すると、各ボールが静止します。

balls[0].xSpeed -= balls[0].xSpeed;

とてもエキゾチックな書き方です

balls[0].xSpeed = 0;
于 2013-10-18T07:01:56.733 に答える
0

物理的にほぼ正しいものについては、接触面に垂直なコンポーネントのみを反転する必要があります。言い換えるcollision_vectorと、 はボールの中心間のベクトルになります (ある点の座標を他の点から差し引くだけです)。球体があるため、これはたまたま衝突面の法線にもなります。次に、ボールごとに速度を分解する必要があります。コンポーネントは、いくつかのベクトル演算を実行することで取得できる にA合わせたものになります。これは、反転したいものになります。衝突面に平行なコンポーネントも抽出します。平行なので衝突しても変化しません。引くことで得られるcolision_vectorA = doc(Speed, collision_vector) * collision_vectorBA速度ベクトルから。最終的に新しい速度は のようになりますB - A。ボールを回転させたい場合は、 の方向の角運動量が必要になりますA - BAボールの質量が異なる場合は、最初の式の乗数として重量比を使用する必要があります。

これにより、衝突が正当に見えます。検出は正しく行われる必要があります。速度がボールの半径よりも大幅に小さいことを確認してください。同等以上の速度を得るには、より複雑なアルゴリズムが必要になります。

注: 上記のほとんどはベクトル演算です。また、ここでは遅いので、いくつかの兆候を混同している可能性があります(申し訳ありません)。紙に簡単な例を挙げて、それを解決してください。また、ソリューションをよりよく理解するのにも役立ちます。

于 2013-10-18T22:03:05.393 に答える