Question

Please see the code below... The ball bounces like a normal ball but then the ball stops and then sinks off the GUI. Any ideas as to what might be wrong with this code?

public void verticalBounce(Container container) {
        deltaY = deltaY - gravity;
        y = y + deltaY;

        if (y >= getHeight()) {
            deltaY = -deltaY;
            deltaY = (int) (deltaY * 0.9);
            y -= -deltaY;
        }
    }
Was it helpful?

Solution

I'm going to use y' to denote the y-position at the end of this time slice and y for the position at the end of the previous time slice, strictly for ease of labeling. This makes the third line of your code:

y' = y + deltaY;

Let's consider the case in which y' is strictly greater than getHeight(). (The case where they are equal will end up being accounted for automatically, as you will see below.) A quick drawing of the situation would be something like this:

           _   o  - y
          |    o
          |    o
----------|--------------------- getHeight()
          |    O
 deltaY - |    O
          |    O
          |_   O  - y'

At some point during the current time slice, the ball hit the floor (at getHeight()). For the remainder of the current time slice, we overshot the floor by the amount:

y' - getHeight()

We need this remainder to be the amount the ball bounced upward during the current time slice. The actual y-position at the end of the current time slice (neglecting your elasticity constant for the moment) would look like this:

                     _   O  - y''
     _   o  - y     |    O
    |    o          |    O
    |    o          |    O
-------------------------------- getHeight()

Now, y'' is getHeight() minus the amount by which we overshot the floor, which we calculated above:

y'' = getHeight() - (y' - getHeight());

(You might be tempted to change this to 2*getHeight() - y', but hang on until we get to the end.)

We'll now quickly pull in the case we neglected earler in which y' == getHeight(). As you can see, y' - getHeight() goes to zero, leaving y'' == getHeight(), just as we need, so there's no extra work to do for this case.

Good, so all we need to do now is take care of the elasticity constant (I assume that's what the 0.9 factor is for, so that the bounce decays over time). We want to apply that to deltaY as you've done, but we also need to apply it to the bounce in the current time slice since it hit the floor:

y'' = getHeight() - 0.9*(y' - getHeight());

Since we haven't mixed y, y' and y'' in the right-hand-side of any of the calculations we can simply replace all of them by y giving us the final if clause (only the last line has been changed):

    if (y >= getHeight()) {
        deltaY = -deltaY;
        deltaY = (int) (deltaY * 0.9);
        y = getHeight() - 0.9*(y - getHeight());
    }

I'm sure if you draw out your previous solution(s) you'll see where they went wrong. Also, using an int for deltaY seems to me to be asking for trouble. I'd rather use floats for all of the calculations and then round only when drawing. You'll notice that I haven't done any casting on the result for y above, which might be necessary depending on the type of y.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top