Originally published in January 2025. Revised to clarify the limits of interpolation and frame-based easing.

The problem behind the pointer

A shared board needs more than a stream of coordinates. In my earlier experiments, updating a remote cursor whenever a message arrived made movement look uneven. The production implementation needed to account for events arriving at irregular intervals.

Why a stream of updates was not enough

My earlier proofs of concept had less demanding requirements. On the shared board, simply moving a cursor to each arriving position made uneven message delivery visible to the user. Basic tweening softened those jumps, but could not reconstruct intermediate positions that had never arrived.

I treated event delivery and rendering as separate problems: preserve enough of the movement history to replay a path, then decide how the receiving client should display it. Batching reduced per-message overhead, while making the timing of playback an explicit tradeoff.

Preserve the path, then render it

I batched position updates and kept a history for each player. The receiving client could reconstruct movement between the positions instead of jumping directly to the newest point.

The implementation used linear interpolation for two points, quadratic interpolation for three, and centripetal Catmull–Rom splines for longer sequences. Those choices made the received path smoother; they could not recover positions that never arrived or remove network delay.

Keep older events from moving the cursor backwards

I compared timestamps within each player’s stream and discarded events older than the latest accepted update. Ordering belongs to the individual stream: clocks from different clients should not be assumed to agree. A sequence number is another way to express that ordering.

Smoothness has a cost

The original implementation moved part of the remaining distance on each animation frame: 50% while moving and 80% after updates paused. These were tuning values for that implementation, not universal settings. Per-frame easing behaves differently at different refresh rates; a revision should use elapsed time and test multiple frame rates.

The useful lesson is to treat delivery, ordering and rendering as separate concerns. Smoothing improves perceived continuity, but introduces lag. The right balance depends on what people need to do together.