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) 
} 

**注意:大多数函数都使用 for 循环numOfBalls作为计数器,但为了测试碰撞,我只使用 2 个球,因此balls[0]andballs[1]

4

2 回答 2

1

这里有一些要考虑的事情。

如果 (xSpeed,ySpeed) 的长度大致可与.ballRadius两个球在模拟时钟的“滴答”之间“穿过”彼此的距离(一步)进行比较。考虑两个完全垂直运动的球,一个向上,一个向下,一个水平 .ballRadius分开。.ySpeed在现实生活中,它们显然会发生碰撞,但如果~ ,您的模拟很容易错过这个事件.ballRadius

其次,你改变球的矢量会导致每个球静止,因为

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

是一种非常奇特的写作方式

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

对于物理几乎正确的东西,您只需要反转垂直于接触平面的分量。换句话说collision_vector,成为球中心之间的向量(只需从另一个点的坐标中减去一个点的坐标)。因为你有球体,所以这也恰好是碰撞平面的法线。现在对于每个球,你需要分解它们的速度。该A组件将与colision_vector您通过一些矢量算术获得它对齐A = doc(Speed, collision_vector) * collision_vector。这将是你想要反转的东西。您还想提取B与碰撞平面平行的组件。因为它是平行的,所以不会因为碰撞而改变。你通过减去得到它A从速度矢量。最后,新速度将类似于B - A。如果你想让球旋转,你需要一个 方向的角动量A - BA如果球的质量不同,那么您将需要在第一个公式中使用重量比作为乘数。

这将使碰撞看起来合法。检测仍然需要正确进行。确保速度明显小于球的半径。对于相当或更大的速度,您将需要更复杂的算法。

注意:上面的大部分内容都是矢量算术。此外,这里已经很晚了,所以我可能混淆了一些迹象(对不起)。在纸上举一个简单的例子并解决它。它还将帮助您更好地理解解决方案。

于 2013-10-18T22:03:05.393 回答