[Gravity] General Advice on Specific Code

This is a discussion on [Gravity] General Advice on Specific Code within the Game Programming forums, part of the General Programming Boards category; I've implemented gravity in what probably a non-standard way, but the calculus involved in actual rigid-body physics is too much ...

  1. #1
    C++ Enthusiast M.Richard Tober's Avatar
    Join Date
    May 2011
    Location
    Georgia
    Posts
    56

    [Gravity] General Advice on Specific Code

    I've implemented gravity in what probably a non-standard way, but the calculus involved in actual rigid-body physics is too much math for me at my current ability.

    CBall is my Ball class containing x and y positions, and x and y velocities. I have a vector of CBall pointers. I process them in this function named 'Gravity' detailed below.

    I was curious to any comment at all on how to improve my design, or a new direction. This function runs once per frame, and processes every CBall pointed to in vpCBall (vector of pointers to CBall).

    Code:
    void Gravity(vector<CBall*> &vpCBall, int Gravity_Setting, sf::String &Text)
    {
        // Is gravity on?
        if (Gravity_Setting == WEIGHTLESS) return;
    
        // Iterate through the CBall list
        // Reset Active Balls counter each loop
        int ActiveBalls = 0;
        for (vector<CBall*>::iterator iter = vpCBall.begin(); iter != vpCBall.end(); ++iter)
        {
            if((*iter)->AtRest) continue;
            ++ActiveBalls;
            // Spreed: Copy the Class members to local variables
            float x_pos = (*iter)->x_pos;
            float x_vel = (*iter)->x_vel;
            float y_pos = (*iter)->y_pos;
            float y_vel = (*iter)->y_vel;
    
            y_vel += GRAVITY; //0.82
            y_pos += y_vel;
    
            x_vel *= DRAG; // 0.995
            x_pos += x_vel;
    
            // If Collided with Floor...
            if (y_pos > SCREEN_BOTTOM)
            {
                // Reverse momentum - albeit weaker (80-95% strength)
                y_vel *= -INERTIA; // 0.95
    
                // Is Kinetic energy exhausted?
                // Note: Cutoff must be less than GRAVITY
                // Reason: This section takes care of the problem of the "vibrating" balls.
                // No point to vibrating balls, so after a CUTOFF in movement in
                // the x and y axis, simply zero out both and mark it AtRest=true
                assert(CUTOFF < GRAVITY);
                if (fabs(y_vel) < CUTOFF && fabs(x_vel) < CUTOFF)
                {
                    //cout << "Resting Ball..." << endl;
                    x_vel = 0;
                    y_vel = 0;
                    (*iter)->AtRest = true;
                }
    
                // Set Ball to just above floorline
                // Reason: This garuntees the ball will not be caught next time
                // through the loop and re-considered for -another- immediate
                // velocity inversion
                y_pos = SCREEN_BOTTOM - 0.001;
            }
            // Check Screen Bounds
            // Reason: If the balls roll off the screen to 105% of the screen
            // width, simply stop considering them for physics calculations.
            if (x_pos > (SCREEN_RIGHT * 1.05))
            {
                x_vel = 0;
                y_vel = 0;
                (*iter)->AtRest = true;
            }
    
            // Put the locals back into the Class
            (*iter)->x_pos = x_pos;
            (*iter)->x_vel = x_vel;
            (*iter)->y_pos = y_pos;
            (*iter)->y_vel = y_vel;
        }
        // String stream used for screen message
        stringstream ss("");
        ss << "Active Balls: " << ActiveBalls << " / " << vpCBall.size();
        Text.SetText(ss.str());
    }
    There are some kludges, like artificially adjusting the y position after a velocity inversion (the part where I multiply y_vel by a negative INERTIA) so that the y_vel isn't flipped again on the following loop/frame.
    Eventually, I decided that thinking was not getting me very far and it was time to try building.
    Rob Pike, "The Text Editor sam"

  2. #2
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Where is your frame delta?

    Simple ugly Euler integration is:

    Code:
    Vector3 forces = ComputeForces();
    Vector3 acceleration = forces / mass;  // mass is a scalar
    velocity += acceleration * frameDelta;  //frameDelta is in seconds - ~16.6667 ms at 60 FPS
    position += velocity * frameDelta;
    You can throw in friction which can be assumed to act opposite of velocity but I left it out for clarity. Friction is actually not this simple but for most models this will suffice.

  3. #3
    C++ Enthusiast M.Richard Tober's Avatar
    Join Date
    May 2011
    Location
    Georgia
    Posts
    56
    I'm using SFML's App.SetFramerateLimit() function set to 30 frames per second. This -should- be enforcing a 33 millisecond time frame. I can confirm the main loop is constrained to 30 runs per second, due to this
    Code:
        // End of program status report.
        cout << TotalLoops << " in " << Clock.GetElapsedTime() << " seconds." << endl;
        cout << "(" << TotalLoops / Clock.GetElapsedTime() << " loops per second.)" << endl;
        cout << vpCBall.size() << " balls present at exit." << endl;
    I use the DRAG constant of 0.995 for velocity dampening along the x-axis, but not y.

    Brb, gonna grab some tacos. Thank you as always VA for any insight! =D
    Last edited by M.Richard Tober; 01-08-2012 at 01:20 PM.
    Eventually, I decided that thinking was not getting me very far and it was time to try building.
    Rob Pike, "The Text Editor sam"

  4. #4
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    And what happens if the framerate falls below 30? All your constants are meaningless at that point. Frame delta is used so that the game runs the same speed regardless of the speed of the computer it is on. Some systems will run faster than others but the game should run the same on all systems. Clamping your framerate to 30 FPS is perfectly valid and usually needed in physics calculations but you still must use the frameDelta or some provided delta so that your update is not out of sync with your render.

  5. #5
    C++ Enthusiast M.Richard Tober's Avatar
    Join Date
    May 2011
    Location
    Georgia
    Posts
    56

    [Solved]

    Code:
    if (KeyArray[sf::Key::W]) BallCoords.y -= SPEED * App.GetFrameTime();
    I've gone through and started adding in things like this. I ran several tests for frame rate, both constrained by my monitor's refresh, and unrestrained. I've observed first hand now the impact changes in loop execution speed and frame-time delta can have on the physics.

    Allright. Back to my laboratory. Thank you again VA, you're advice and instruction are valued.
    Eventually, I decided that thinking was not getting me very far and it was time to try building.
    Rob Pike, "The Text Editor sam"

  6. #6
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Glad you have it working. Best of luck on your project.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. General Advice
    By ph5 in forum C Programming
    Replies: 3
    Last Post: 02-23-2011, 03:16 AM
  2. Programming - general advice
    By progcomputeach in forum Projects and Job Recruitment
    Replies: 8
    Last Post: 08-03-2010, 12:16 PM
  3. Fortran programmer new to c++. Looking for general advice.
    By Duff-Man in forum C++ Programming
    Replies: 12
    Last Post: 10-14-2009, 12:33 AM
  4. General Advice (RTS Game)
    By b00l34n in forum Game Programming
    Replies: 2
    Last Post: 05-07-2005, 12:34 PM
  5. general advice on jobs
    By Unregistered in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 07-25-2002, 08:36 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21