basketball.casa

A basketball world simulated from the body up. Watch only.

The replay cuts close when the ball is stolen

The replay's wide camera sits far enough back to see half the court, which is right for following a possession and wrong for the plays that end one. From 20 metres a hand is a few pixels, so a steal looked like the ball changing hands for no reason anyone could see. The replay now does what a broadcast director does: it cuts close for the plays that matter, and it knows which ones they are before they happen.

The wide view: a pass being intercepted near the three-point line, the players small and the ball a few pixels across
The wide view at the moment of the steal.

Marked by the simulation, not guessed

Every steal, strip and charge in a game is an event the simulation recorded, with the time it happened and the spot where the ball was taken. The replay reads that short list with the game, so the camera knows about each one before the moment arrives. In the game shown here there are twelve: seven intercepted passes, four strips and one charge.

A second and a half before each one, the camera eases in to about 3.5 metres from the spot, 2 metres up, staying on its own side of the court so it never crosses the line. It holds there until a second after the ball is taken, then eases back out. Each ease takes half a second, so the picture never jumps.

Close in: the blue ball handler dribbles with a red defender in front, arms out wide, half a second before the pass
Half a second before: the camera already in close.
Close in: the red defender reaches up with both hands and takes the pass above the head of the blue player
The steal: the defender reaches up and takes the pass.

Hold on the place, not the ball

The first version followed the ball. For an interception that meant a camera chasing a pass through the air, looking up at it and framing nothing but sky. It now looks at the spot where the ball is taken, at the height of the players' middles, so the pass arrives into a still frame with the bodies in it.

How close is decided by one function of the replay's clock, so a paused picture, a scrub and normal play all show the same framing at the same moment:

export function closeness(t, marks) {
  const smooth = (x) => (x <= 0 ? 0 : x >= 1 ? 1 : x * x * (3 - 2 * x));
  let best = null;
  for (const [at, , x, y] of marks) {
    const w = Math.min(smooth((t - (at - CLOSE_BEFORE_S - EASE_S)) / EASE_S),
                       smooth((at + CLOSE_AFTER_S + EASE_S - t) / EASE_S));
    if (w > 0 && (best === null || w > best.w)) best = { at: [x, y, LOOK_Z], w };
  }
  return best;
}

The weight rises from 0 to 1 on a smooth step and falls the same way, and the camera moves that far from the wide view toward the close one. Only the automatic TV and broadcast views cut. A camera someone has chosen, or moved with a key, is never taken away from them.

Where the numbers come from

How long a cut lasts and how close it goes are drawing choices, judged by watching the replay at normal speed. Two searches for measured broadcast shot lengths found nothing to cite, so the numbers are named as choices in the code. They are set from the plays themselves: a strip happens as the hand arrives, an interception at the end of the pass's flight, and a charge at the contact.