DEV Community

Cover image for I built a 3D free-kick game in three.js: Magnus curl in 10 lines, floodlights and a keeper that reads your shot
Jacko (Nightlit)
Jacko (Nightlit)

Posted on

I built a 3D free-kick game in three.js: Magnus curl in 10 lines, floodlights and a keeper that reads your shot

I'm a solo dev and I just shipped Efectazo, a free free-kick football game that runs in the browser, on phones and desktop: https://efectazo.pages.dev

You swipe to shoot, and the shape of your swipe becomes curl on the ball. Here's how the main pieces work.

The ball: gravity, drag and a Magnus force

The physics module is plain JS with no three.js in it, so I can run it headless in tests. Each substep adds three forces to the ball:

// Magnus: CM * (w x v)
export function accel(b, wind) {
  const [vx, vy, vz] = b.v;
  const rx = vx - wind[0], rz = vz - wind[1];
  const sp = Math.hypot(rx, vy, rz);
  const [wx, wy, wz] = b.w;
  const mx = wy * rz - wz * vy, my = wz * rx - wx * rz, mz = wx * vy - wy * rx;
  return [-KD * sp * rx + CM * mx,
          -G - KD * sp * vy + CM * my,
          -KD * sp * rz + CM * mz];
}
Enter fullscreen mode Exit fullscreen mode

Quadratic drag slows the ball, and the cross product of spin and velocity pushes it sideways (side spin) or down (topspin dip). Spin decays exponentially, so the bend gets stronger late in the flight, which is what makes a good free kick look right.

From swipe to shot

  • Direction comes from the first 40% of the swipe
  • Power from swipe speed, height from swipe length
  • Side spin from how much the swipe curves

So if you draw a banana, the ball bends like one.

The goalkeeper

The keeper has a reaction delay, predicts where the ball will cross the line (better keepers read the curl better), and dives with limited speed and reach. A save only happens when the ball actually hits his limbs, so it never feels scripted. The wall (0 to 6 players) jumps when you kick.

Rendering

  • three.js r160, MeshStandard/Physical materials, PMREM image-based lighting
  • Two shadow-casting "floodlight" directional lights with PCF soft shadows
  • A procedural grass shader (mowing stripes plus detail noise) instead of a big texture
  • ACES filmic tone mapping, bloom, and a slow-motion replay with depth of field after goals
  • Quality tiers with an Auto mode that drops a tier if the frame rate stays under ~47 fps for 2 seconds, which matters a lot on phones

The game around it

40 career levels, a seeded Daily Challenge (5 shots, with an emoji grid you can share), an endless Arcade mode and Cups. Coins unlock balls, boots, kits, stadiums (night, day, sunset, rain, snow) and celebrations. English and Spanish. It's free, with an optional one-time Pro upgrade.

Play it here: https://efectazo.pages.dev (also on itch: https://nightlit.itch.io/efectazo)

I'd love to hear how it runs on your device and how the curl feels. Happy to go deeper on any part in the comments.

Top comments (0)