Reputation: 1329
This is a general problem that I have encountered across many languages. When I am first learning the language, one of the first things I attempt to do is to make a bouncing ball.
However, every time I do it, I am left with a very annoying problem - the ball just keeps on bouncing just a little bit at the bottom.
Here is an example of the problem I came across today while learning about the Html5 Canvas - http://pastebin.com/aM1svKMJ
You can just copy and paste that into a HTML file and run it yourself if you like. Even though I have it set to lose 20% of its 'energy' after each bounce, it continues to bounce a little at the bottom.
I would be very grateful if someone could point out my error
Upvotes: 2
Views: 2713
Reputation: 909
To solve that bug the only thing i had to do was change where i put the ball after the colision.
Instead of putting it above the barrier, you put it on the barrier.
if ball.py >= surface.get_height() - self.radius:
ball.sy = - ball.sy * ball.elasticity
ball.py = surface.get_height() - self.radius - 1
As you can see, it still detects collision on the next frame because vy will be so small that it only moves one pixel up and puts it back on the place so it doesn't move.
if you still didn't solve it's because you have to alter the order of events.
Upvotes: 0
Reputation: 6525
This is a pretty common problem, but most of the answers don't seem to address the actual issue: You have constant gravity accelerating the ball, but you only have proportional deceleration from contact with the ground. This means that the ball is gaining energy when it's going slow enough: the ball gains velocity from gravity that would take it through the ground. You detect that and move the ball back up to ground level, but then you reverse the velocity (only taking out part of what it gained from gravity). So the ball jumps up a little bit. You need to detect resting contact.
Upvotes: 0
Reputation: 1329
I solved this myself after tinkering with it for a bit.
Turns out everything is ok once the required steps are taken in the right order.
This means that Accelerations should be added first, then Velocities, then position checks then the drawing.
All I needed to change was
this.vx += this.ax;
this.vy += this.ay;
this.x += this.vx;
this.y += this.vy;
Upvotes: 1
Reputation: 1751
you can use the original y-coordinate of the ball and use its ratio with the current y-coordinate to decrement "e" divided by a constant for sensitivity. works for me:
//line 46 add:
var initHeight = height / 2;
//line 83:
this.vy *= -1 * e;
e = e - (e* (initHeight / this.y ) / 10);
here's a working sample: http://jsfiddle.net/57tx3/
Upvotes: 3
Reputation: 49816
You could also deduct a small amount of energy on each bounce (could be fixed, could be randomly chosen). At some point that will dominate the calculation, and take your energy to zero.
Upvotes: 1
Reputation: 57
If you keep dividing by 20%, you'll never reach zero. Eventually, you'll be "bouncing" 20% of some infinitesimally small numbers. When it hits an amount of "energy" near the bottom percent of the original amount (say 20% or under), you'll have to hard code it to 0%.
Or better yet, every bounce needs to divide by 20% of the original amount, not the current. That will only be 5 bounces, but say you make it 5%, that's 20 bounces till zero.
Upvotes: 1