1
\$\begingroup\$

I am currently working on the 2D Bouncing ball physics that bounces the ball up and down. The physics behaviour works fine but at the end the velocity keep +3 then 0 non-stop even the ball has stopped bouncing. How should I modify the code to fix this issue?

Here is the video shows how it works. Note: Bandicam cannot record the velocity transition between -3 and 0. So, it just shows -3 when the ball stops bouncing.
http://www.youtube.com/watch?v=SEH5V6FBbYA&feature=youtu.be

Here is the generated report: https://www.dropbox.com/s/4dkt0sgmrgw8pqi/report.txt

    ballPos         = D3DXVECTOR2( 50, 100 );
    velocity        = 0;
    acceleration    = 3.0f;

void GameClass::Update()
{
    // v = u + at
    velocity += acceleration;

    // update ball position
    ballPos.y += velocity;

    // If the ball touches the ground
    if ( ballPos.y >= 590 )
    {
        // Bounce the ball
        ballPos.y = 590;
        velocity *= -1;
    }

    // Graphics Rendering
    m_Graphics.BeginFrame();
    ComposeFrame();
    m_Graphics.EndFrame();
}
\$\endgroup\$
  • \$\begingroup\$ I think you are giving very few info for anybody to help. If I were you I would attach the debugger and monitor how the velocity changes. \$\endgroup\$ – concept3d Oct 20 '13 at 11:56
  • \$\begingroup\$ I see. Info updated. \$\endgroup\$ – user Oct 20 '13 at 12:17
2
\$\begingroup\$

The main problem you are encountering is due to the fact that you are using Euler integration. It is very innacurate and assumes a constant acceleration over the whole timestep (in your case an implicit dt = 1), which is wrong in general, but in the case of a bounce, very very wrong indeed.

Also, there is no damping. In the real world, energy is always lost due to friction and collisions. In fact, your code is actually giving free energy to the ball: at the moment of impact, you teleport the ball upwards a short distance, while giving it an impossibly perfect eleastic collision, thereby giving the ball free potential energy. The only reason your ball's bouncing becomes smaller is because of the innacurate Euler integration, not something you want to rely on.

To make your code better, I would first introduce an explicit timestep, then you can call your integration function multiple times per frame with smaller timesteps to get better accuracy, or have an adaptive timestep.

You could also look into higher order integration functions. 4th Order Runge-Kutta is very accurate, but overkill for what you want, but perhaps a second order leapfrog method.

You could also look into Verlet integration. While it is still not very accurate, it is easy to control and very stable.

You should also add some damping. The easiest way is to multiply the velocity by a number slightly smaller than 1 (which is equivalent to adding a small force proportional to velocity, in the opposite direction):

vel *= 0.9999; <- energy loss every frame, air resistance
if ( ballPos.y >= 590 )
{
    ballPos.y = 590;
    vel *= -0.95; <-larger energy loss in collision
}

So, to sum up, here is a list of keywords to research to improve your simulation:

leapfrog integration, runge-kutta integration, verlet integration, adaptive timestep, collision detection/resolution, rigid body stacking, resting contact, impulse collisions,

You can easily find lots of easy to understand tutorials, samples and papers relating to this. That's probably a lot deeper than you need/desire to go. But writing a simple, but solid, physics simulation is a great learning experience and a whole lot of fun.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Your acceleration will negate any upward velocity at the point that speed <= 3.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ how can I block velocity += accelaration when the ball stops bouncing? \$\endgroup\$ – user Oct 20 '13 at 16:54
  • \$\begingroup\$ You can just check whether speed is less than or equal to the acceleration when you reverse velocity. If it is, set velocity to 0. \$\endgroup\$ – Drew Cummins Oct 20 '13 at 16:59
  • \$\begingroup\$ The ball cannot bounce anymore after applying your solution. \$\endgroup\$ – user Oct 21 '13 at 10:21
  • \$\begingroup\$ ur solution doesn't work as every bounce it will meet <=3 condition. So, I need to find the way to stop the increasing velocity when the ball stops bouncing. Here is the generated report: dropbox.com/s/4dkt0sgmrgw8pqi/report.txt \$\endgroup\$ – user Oct 21 '13 at 13:31
  • \$\begingroup\$ What you want to happen is unclear from your problem description. Of course the ball doesn't bounce when velocity is zero. If you want the ball to bounce off the floor in your simplified physics simulation, you have to allow upward velocity to grow larger than the amount downward velocity grows in that time-step. \$\endgroup\$ – Drew Cummins Oct 21 '13 at 14:14
-1
\$\begingroup\$

Put a isBounce flag to make the velocity to zero when the ball stops bouncing.

 void GameClass::Update()
{
    if ( isBounce )
    {
        // v = u + at
        velocity += acceleration;

        // update ball position
        ballPos.y += velocity;
    }
    else
    {
        velocity = 0;
    }

    // If the ball touches the ground
    if ( ballPos.y >= 590 )
    {
        if ( isBounce )
        {
            // Bounce the ball
            ballPos.y = 590;
           velocity *= -1;
        }


        if ( velocity == 0 )
        {
            isBounce = false;
        }
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I'm afraid this code is clearly wrong. If it's giving you the results you want, it's probably entirely by accident. \$\endgroup\$ – MrCranky Oct 23 '13 at 8:49
  • \$\begingroup\$ The code I already tested and works fine. \$\endgroup\$ – user Oct 23 '13 at 8:53
  • \$\begingroup\$ Perhaps you missed some code off the answer then. Because isBounce is never set to true anywhere. Even if it is declared as a member variable and initialised to true, the code is still massively flawed. Velocity is set to zero if isBounce is false, but isBounce only because false if velocity is already zero. The odds of velocity becoming exactly zero is vanishingly small if you're using floating point numbers for velocity. Even if you're using ints, it would rely on an exact coincidence of maths to happen. Try changing acceleration to 4, or the ground plane to 587, and see if it still works. \$\endgroup\$ – MrCranky Oct 24 '13 at 7:36
  • \$\begingroup\$ Either way, this site is supposed to be about authoritative answers to problems posed, and no-one else should come to this answer and think it is right. You might have found some way to make it work for you, but it is not a good example of how bouncing ball code should work. It's an example of how to do it badly. DaleyPaley's answer is far, far better, and actually addresses the fundamentals behind the question. \$\endgroup\$ – MrCranky Oct 24 '13 at 7:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.