7
\$\begingroup\$

Alright, so I've got hold of some simple physics mechanics, and am currently trying to implement bouncing. Based on the first answer of this question, I've developed the following algorithm:

    Vector2 velocity;

    float gravity;
    float elasticity;

    Hitbox dummy;

    // ---

    void bounce() {     
        dummy.MoveY(velocity.Y);
        velocity.Y += gravity;

        if (dummy.ThereWasContact.South) velocity.Y *= -elasticity;
    }

Gravity can be any value, and Elasticity is always between 0.0f and 1.0f. Velocity.Y's initial value can also be anything.

Weight factors aside, which would determine a minimal rebound force for the object to be able to leave the ground again and (probably) aren't related to the problem, this is apparently fallacious.

What happens here is somewhat like this:

enter image description here

If I drop an object from a height of 128 units, for example, 0u marking ground height, with a gravity of 1u and elasticity of 0.9, the object would bounce once, reach a maximum height of ~126u from the rebound, and from then on keep alternating on maximum heights between this and ~122u.

This example is based on one of my own experiments, in which I drop an object from a height of 64 pixels and there is a floor at 192 pixels. The maximum height will keep going from ~66 pixels to ~70.

What am I missing? Does weight after all do more than I think? If I need to explain something better or details appear to be missing, let me know.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Each bounce needs to subtract some small amount of energy from the ball. This accounts for the internal friction of the flexing of the ball and the sound and heat generated from the bounce. \$\endgroup\$
    – House
    Jan 31, 2013 at 20:58

2 Answers 2

3
\$\begingroup\$

Whenever the ball hit the ground, first you add gravity, then you invert the direction, thus the ball is going to spring back with greater speed. Let's step through a case where elasticity is 1, gravity is 1 and the ball's initial speed is 10:

  1. The ball moves 10 and hit the ground.
  2. The speed is increased to 11.
  3. The ball's speed is changed to -11.

Next update:

  1. The ball moves -11.
  2. The speed is decreased to -10.

So the ball impacted the ground with speed 10 and left with speed -11, next time it hit the ground it will be at speed 11, and it will leave at speed -12 etc.

A very simple fix is to split gravity application into two, half before collision detection and half after.

The future

Your next error will be that the ball get stuck in the ground. This happens because you let the ball pass into the ground before registering a collision, and sometimes the ball will have lost so much speed that the following move doesn't take it out of the ground, so your collision detection invert its direction again. The easy fix is to check that the ball is actually moving towards the object that it is colliding with before inverting the direction.

\$\endgroup\$
8
  • \$\begingroup\$ Sorry to not include such detail, but I'm not letting the ball pass into the ground. The Hitbox's MoveY() method resolves the collision - if it hits Point B which is between its starting position Point A and destination Point C, it will be sent back to Point B. \$\endgroup\$
    – Mutoh
    Jan 31, 2013 at 21:47
  • \$\begingroup\$ With this aside --- Should I, then, add Gravity/2 before the collision, and Gravity/2 after the collision? \$\endgroup\$
    – Mutoh
    Jan 31, 2013 at 21:47
  • \$\begingroup\$ Yep, that is it. \$\endgroup\$ Jan 31, 2013 at 21:58
  • \$\begingroup\$ Of course, ideally you would calculate an amount of bounceback in the same frame that the ball hit the ground and apply gravity based on how much of that frame was spent going up and down respectively. \$\endgroup\$ Jan 31, 2013 at 22:05
  • \$\begingroup\$ If anyone else is struggling to get it right, I wrote a pseudocode implementation (with the operations in the right order) here. \$\endgroup\$ Jul 19, 2013 at 8:46
5
\$\begingroup\$

Your 'elasticity' should be removing energy from the system so that it settles down. The first thing that comes to mind given that that isn't working, and that you mention measuring in pixels, is: make sure that your velocity is floating-point, not an integer.

If that isn't the problem, then the first thing I would do to debug is calculate the energy (ignoring mass) of the ball: pow(velocity.Length(), 2) + position.Y * gravity. If your units are right and your simulation is good, this should slowly decrease with each bounce. If it doesn't, then the bounce is a problem. If it increases continuously while not bouncing, then your basic simulation step is wrong.

\$\endgroup\$
2
  • \$\begingroup\$ Alright then, I will try this out (and yes, the position is measured with floats). Pardon my ignorance, though, but how would I calculate the magnitude of the velocity? \$\endgroup\$
    – Mutoh
    Jan 31, 2013 at 21:25
  • \$\begingroup\$ @Mutoh Your Vector2 type should have an operation to do that (might be called length instead); if it doesn't, get a better one or write one. Any basic "vectors for computer graphics" reference should have all the details if you really need them. \$\endgroup\$
    – Kevin Reid
    Jan 31, 2013 at 21:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .