React for Data Visualization
Student Login

Game loop animation with a bouncy ball

Let's get our feet wet with my favorite childhood example: a bouncing ball.

I must have built dozens of them back in my Turbo Pascal days using BGI. Endless afternoons playing with different parameters in my bouncy ball examples.

Yes, those Turbo Pascal and BGI are from the 80's. No, I'm not that old. I started young and with old equipment. Coding for DOS is easier when you're a kid than coding for Windows 95.

Try to figure it out on your own first. Then watch my solution. Best way to learn :)

Here's a sandbox I prepared for you earlier:

Remember that gravity is an acceleration pointing down. It impacts the speed of your ball, not its position directly.

  1. Render the ball
  2. Use an effect to start a timer with d3.timer (it's like setInterval but better)
  3. Ensure you clean up with timer.stop()
  4. Move the ball on each timer iteration (also known as a tick)
  5. Adjust the ball's speed to simulate gravity

How do you get the bounce effect at max_h? Look at the direction vY points.

My solution

The key part of my solution is this useEffect that runs a game loop.

useEffect(() => {
function gameLoop() {
setBall((ball) => {
let { y, vy } = ball
if (y > max_h) {
vy = -vy
}
return {
y: y + vy,
vy: vy + 0.1,
}
})
}
const t = d3.timer(gameLoop)
return () => t.stop()
}, [])

That's where all the important things happen.

Start the timer on component mount, make sure it stops when the effect re-runs. Game loop itself is a function that takes current ball state and updates it with middle school physics:

  • if ground reached, invert velocity
  • add velocity to position
  • add gravity to velocity

And you get a bouncy ball ✌️

While powerful, this technique is tedious for most applications. We'll look at using transitions next. That way D3 can do the hard work for us.

Previous:
Animation
Next:
Use transitions for simple animation (7:55)
Created by Swizec with ❤️