A hand up at the shot: contested shots are now drawn as contests in the basketball replay
A contested shot used to look like any other in the 3-D replay: the defender who got close stood there with their arms down. The simulation knew the shot was contested, because how close the defence got changes how often a shot goes in, but the picture did not show it. Now the defender reaches for the ball.
Who reaches, and when
For every shot, the simulation records which defenders got close enough to bother it. The replay takes the one of them nearest the ball at the moment it leaves the shooter's hands, and raises the arm on the side nearer the ball. The arm rises while the shooter gathers and goes up, is fully raised while the ball is in the air, and comes down the way it went up. A shot nobody got close to is drawn with no hand up at all.
const nearest = e.contesting.reduce((best, i) => (gap(i) < gap(best) ? i : best));
Only as far as their own arm reaches
The hand moves toward the point where the ball leaves the shooter, along the same arm every figure in the replay has, drawn at that player's own length. So a defender a step away gets a hand right up to the ball, and one further off reaches toward it and comes up short. The arm is never stretched to make the picture look closer than the play was.
What is not drawn
The defender's feet stay on the floor. A contest in the simulation is decided by how close the defender gets, not by a jump, so the replay draws none: everything in the picture comes from what the game itself decided.