How do you code a bouncing ball?
Gravity, a floor and a restitution factor make a bouncing ball — but a naive floor check changes the energy. Handle the impact time exactly, in JavaScript.
How do you code a bouncing ball?
Each physics step does three things: apply gravity to the velocity, move the ball, and — if it went through the floor — reverse the velocity and multiply it by the restitution . The catch is the last part: where you put the ball when it crosses the floor decides whether energy is conserved. A common shortcut loses energy even with .
This is the code companion to How a bouncing ball works, which explains restitution and the heights we test against below.
The full loop in about 35 lines
const G = 9.81; // m/s²
const E = 0.8; // restitution
const FIXED_DT = 1 / 120; // physics step, seconds
const ball = { y: 2, vy: 0 }; // metres above the floor, m/s upward
// Advance under constant gravity for dt seconds — exact, not an approximation.
function fall(b, dt) {
b.y += b.vy * dt - 0.5 * G * dt * dt;
b.vy -= G * dt;
}
function step(b, dt) {
let left = dt;
while (left > 0) {
const yEnd = b.y + b.vy * left - 0.5 * G * left * left;
if (yEnd >= 0) { fall(b, left); return; } // no impact this step
// Impact inside the step: solve y + v·τ − ½gτ² = 0 for τ
const tau = (b.vy + Math.sqrt(b.vy * b.vy + 2 * G * b.y)) / G;
fall(b, tau); // advance exactly to the floor
b.y = 0;
b.vy = -E * b.vy; // bounce
left -= tau; // spend the remaining time
if (Math.abs(b.vy) < 0.01) { b.vy = 0; return; } // resting: stop micro-bounces
}
}
// Fixed-timestep loop: render at any frame rate, step physics at 120 Hz
let acc = 0;
function frame(frameSeconds) {
acc += Math.min(frameSeconds, 0.25); // clamp huge frames (tab was hidden)
while (acc >= FIXED_DT) { step(ball, FIXED_DT); acc -= FIXED_DT; }
}Does it match the physics?
Dropping the ball from m with and recording each peak, the code reproduces the geometric heights to within the sampling of the step:
| Bounce | Theory (m) | Code (m) |
|---|---|---|
| 1 | 1.280 | 1.280 |
| 2 | 0.819 | 0.818 |
| 3 | 0.524 | 0.524 |
| 4 | 0.336 | 0.335 |
Why not just clamp the ball to the floor?
The shortcut is if (y < 0) { y = 0; vy = -e * vy; }. When the ball overshoots the floor by a few millimetres, that snap throws away the height it should have had and adds energy at the wrong moment. Even with a perfectly elastic , a ball dropped from m should return to m every time. Measured at 30 physics steps per second:
| Collision handling | First peaks for e = 1 (m) |
|---|---|
| Clamp and flip | 1.85, 1.86, 1.66, 1.67, 1.47 — decaying |
| Mirror the penetration | 1.92, 2.00, 1.92, 2.00 — wobbling |
| Exact impact time | ≈ 2.00 every time |
What PhysicsHub does
The Bouncing Ball simulation runs on a fixed 1/120 s step with the shared engine. Its Bounds element compensates for the work gravity does while the ball overlaps the floor inside a step, so restitution 1 really is lossless and the heights match the theory rather than drifting down.
Frequently asked questions
Why use a fixed time step for a bouncing ball?
Why does my ball lose energy even with restitution 1?
How do I stop the infinite tiny bounces at the end?
Can I use this for a ball that also moves sideways?
Keep exploring
- The physics first: How does a bouncing ball work?.
- Watch it run: Bouncing Ball simulation.
- Integrators for oscillators, with measured error: Simulating a pendulum in code.