【问题标题】:Applying gravity to objects对物体应用重力
【发布时间】:2017-01-18 11:19:33
【问题描述】:

我在对物体实施重力时遇到问题。

我有一堆使用 OpenGL 绘制的圆形对象。我正在使用delta-x 和delta-y 来移动圆圈(球)。我正在尝试在每个帧的y 坐标中添加一个引力常数,以便模拟被拉下,但我不确定该怎么做。

以下是相关代码:

class Ball
{
    public:
        double x;
        double y;
        double radius;
        double deltaX;
        double deltaY;
};


std::vector<Ball> gAllBalls;  // a vector of balls with random positions and delta-values
double gGravity = ?;  // gravitational constant - I know it's 92 m/s^s, but I don't know how to apply that to deltaX and deltaY


void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);

    for (auto &thisBall : gAllBalls)
    {
        // draw
        glColor3d(thisBall.red, thisBall.green, thisBall.blue);
        DrawCircle(thisBall.x, thisBall.y, thisBall.radius);

        // gravity - not working
        if (thisBall.y + thisBall.radius < gScreenHeight - gGravity)
        {
            thisBall.y += gGravity;
        }

        // wall bouncing
        if (thisBall.y + thisBall.radius + thisBall.deltaY >= gScreenHeight)  // up
        {
            thisBall.deltaY = -thisBall.deltaY;
        }

        if (thisBall.y + thisBall.deltaY - thisBall.radius < 0)  // down
        {
            thisBall.deltaY = -thisBall.deltaY;
        }

        if (thisBall.x + thisBall.deltaX - thisBall.radius < 0) // left
        {
            thisBall.deltaX = -thisBall.deltaX;
        }

        if (thisBall.x + thisBall.radius + thisBall.deltaX >= gScreenWidth)  // right
        {
            thisBall.deltaX = -thisBall.deltaX;
        }

        // move
        thisBall.x += thisBall.deltaX;
        thisBall.y += thisBall.deltaY;
    }
    glutSwapBuffers();
    glutPostRedisplay();
}

我遇到的一个大问题是我不知道如何计算重力,因为我使用 deltaX 和 deltaY 而不是使用单独的速度和距离变量来计算 92 m/s^ 2.但是,无论我将重力设置为什么,球的行为都不会像应有的那样 - 无论重力强度如何,所以肯定有其他问题,但我不知道是什么。

【问题讨论】:

  • thisBall.y += gGravity; 这将导致恒定的速度,而不是恒定的加速度。如果你调整 deltaY 而不是 Y,你可能会更接近你想要的。最好使用工程单位,例如米和秒,而不是像素和任意时间步长,然后根据需要在它们之间进行转换。最后,你的“G”值是关闭的,它真的是 9.8 m/sec^2
  • 啊,这当然更有意义。我将其更改为 deltaY 而不是 Y,它最初似乎可以工作,但是球开始越来越快地加速而不是减速。我只是使用 1 作为重力常数。我很想使用更好的单位,但我不确定如何实现它们。您有什么建议或资源吗?
  • "92 m/s^2",你在哪里模拟,某种超木星还是小恒星?
  • 这是什么应用程序?如果你想模拟均匀引力场中的真实运动,你可以使用方程 y_{t} = y_{t-dt} + v_{y,t-dt}dt - 0.5gdt^{2}。 y_{t} 是时间 t 的位置,dt 是调用 display() 之间的时间,v_{y,t-dt} 是上一个时间步的速度(上次调用 display()),g是地球上重力加速度 (9.8m/s^{2}) 的大小。
  • @Grav 顺便说一句,没有真正的理由使用 9.8 m/s^2,除非您尝试对地球上的运动进行逼真的模拟。我在上面发布的方程式仍然会为您提供正确的运动类型,您可以将 g 更改为您认为看起来不错的任何值。

标签: c++ opengl glut


【解决方案1】:

我认为这里的问题在于物理学,而不是编程技术。 在您的情况下,我会将您的 Ball 类的“delta”成员更改为“speed”,因为它们是一个距离单位,可以改变每个周期(时间)对象的位置,但这只是一个建议更容易可视化...

class Ball
{
    public:
        double x;
        double y;
        double radius;
        double speedX;
        double speedY;
};

其次,我在您的代码中,您正在更改“y”成员,而不是速度,并且由于重力会改变速度,因此会出现问题。 尝试这样做,出于调试目的,我会尝试使用准时对象(没有半径,只是简单的 (x,y) 坐标)。

因此,总而言之,我只需将您的重力代码更改为以下内容:

  // gravity - 'fixed'
  if (thisBall.y + thisBall.radius < gScreenHeight - gGravity)
  {
      thisBall.speedY -= gGravity; //notice the '-'
  }

重力的值应该是绝对的和正的,以使事情尽可能简单。如果你尝试这个,你应该有一个理想的简单物理模拟器,有一个恒定速度 X 的球(只改变它的方向,而不是大小)。 请试试这个,让我知道结果如何,祝你好运,继续努力 =)

【讨论】:

  • 作为物理学家,speedY -= gGravity; 在我看来很奇怪。它会使gGravity 本身成为一个负数并对其求和(+=)。
  • 谢谢!这让我更接近预期的结果。但是,我仍然有一个小问题:当球弹起时,它们每次弹起时都会弹得越来越高,而不是放慢速度并最终落到底部。我唯一改变的是重力影响速度而不是位置。您对为什么会发生这种情况有什么建议吗?
  • 我想我也有类似的问题。当球反弹时,我正在翻转 dx 和 dy 的负值。这适用于倾斜表面。我通过只在倾斜的表面上翻转它们并在平面上否定它们来修复它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
相关资源
最近更新 更多