Here's the bounce code with the adjustment made.
You don't need to worry about the details unless you particularly want to, but the upshot is:
- Calculate how much overrun there was at the bottom
- Adjust the y-velocity using simple scaling -- if we only overran a little, we only need to tweak the velocity a little, etc.
- Make use of the overrun to reposition the object at the exact bottom
Now it really does bounce perfectly -- to the exact bottom every time, and never rebounding past its starting height.