Search code examples
c++openglglut

Applying gravity to objects


I'm having trouble with implementing gravity on objects.

I have a bunch of circle objects that I'm drawing using OpenGL. I'm using delta-x and delta-y to move the circles (balls). I'm trying to add a gravitational constant to the y coordinate each frame so it simulates being pulled downward, but I'm not sure exactly how to do that.

Here's the relevant code:

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

A big problem I'm having is that I don't know how to calculate the gravity, since I'm using deltaX and deltaY instead of having separate speed and distance variables to calculate 92 m/s^2. However, no matter what I set the gravity to, the balls don't behave like they should - regardless of gravity strength, so there has to be something else wrong, but I don't know what.


Solution

  • I think the problem here is the physics, rather than the programming technique. In your case, I would change the 'delta' members of your Ball class to 'speed', since they are a unit of distance that change the position of your object per cycle (time), however this is just a suggestion to make it easier to visualize...

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

    In second place, I in your code, you are changing the 'y' member, rather than the speed, and since gravity changes speed, hence the problem. Try doing that, and for debugging purposes, I would try with punctual objects (no radius, just plain (x,y) coordinates).

    So, to conclude, I would simply change your gravity code to the following:

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

    The value of gravity should be absolute and positive, so as to keep things as simple as posible. If you try this, you should have an ideal simple physics simulator, with a ball of constant speedX (only changing its direction, not magnitude). Please try this, and let me know how it went, good luck, keep it up =)