Skip to content

Commit 9c88874

Browse files
committed
add more throttling to position updates
1 parent 8e5edcf commit 9c88874

File tree

1 file changed

+84
-17
lines changed

1 file changed

+84
-17
lines changed

src/frontend/components/TrackMap/TrackCanvas.tsx

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ export interface TrackDrawing {
3535
// currently its a bit messy with the turns, so we disable them for now
3636
const ENABLE_TURNS = false;
3737

38+
// Throttle position updates to 2fps (500ms interval)
39+
const POSITION_UPDATE_INTERVAL = 500;
40+
3841
export const TrackCanvas = ({ trackId, drivers }: TrackProps) => {
3942
const [positions, setPositions] = useState<
4043
Record<number, TrackDriver & { position: { x: number; y: number } }>
@@ -46,6 +49,8 @@ export const TrackCanvas = ({ trackId, drivers }: TrackProps) => {
4649
const lastPositionsRef = useRef<
4750
Record<number, TrackDriver & { position: { x: number; y: number } }>
4851
>({});
52+
const lastUpdateTimeRef = useRef<number>(0);
53+
const pendingDriversRef = useRef<TrackDriver[]>([]);
4954

5055
// Memoize the SVG path element
5156
const line = useMemo(() => {
@@ -137,25 +142,62 @@ export const TrackCanvas = ({ trackId, drivers }: TrackProps) => {
137142
});
138143
}, [drivers]);
139144

145+
// Throttled position update effect
140146
useEffect(() => {
141-
if (!trackConstants || !drivers?.length || !driversChanged) return;
142-
143-
const updatedPositions = drivers.reduce(
144-
(acc, { driver, progress, isPlayer }) => {
145-
const position = updateCarPosition(progress);
146-
return {
147-
...acc,
148-
[driver.CarIdx]: { position, driver, isPlayer, progress },
149-
};
150-
},
151-
{} as Record<number, TrackDriver & { position: { x: number; y: number } }>
152-
);
147+
if (!trackConstants || !drivers?.length) return;
148+
149+
// Store the latest drivers data
150+
pendingDriversRef.current = drivers;
151+
152+
const now = Date.now();
153+
const timeSinceLastUpdate = now - lastUpdateTimeRef.current;
154+
155+
// Only update positions if enough time has passed or if drivers have changed significantly
156+
if (timeSinceLastUpdate >= POSITION_UPDATE_INTERVAL || driversChanged) {
157+
const updatedPositions = drivers.reduce(
158+
(acc, { driver, progress, isPlayer }) => {
159+
const position = updateCarPosition(progress);
160+
return {
161+
...acc,
162+
[driver.CarIdx]: { position, driver, isPlayer, progress },
163+
};
164+
},
165+
{} as Record<number, TrackDriver & { position: { x: number; y: number } }>
166+
);
153167

154-
setPositions(updatedPositions);
155-
lastDriversRef.current = drivers;
156-
lastPositionsRef.current = updatedPositions;
168+
setPositions(updatedPositions);
169+
lastDriversRef.current = drivers;
170+
lastPositionsRef.current = updatedPositions;
171+
lastUpdateTimeRef.current = now;
172+
}
157173
}, [drivers, trackConstants, updateCarPosition, driversChanged]);
158174

175+
// Set up a timer for periodic position updates
176+
useEffect(() => {
177+
if (!trackConstants) return;
178+
179+
const intervalId = setInterval(() => {
180+
const pendingDrivers = pendingDriversRef.current;
181+
if (!pendingDrivers?.length) return;
182+
183+
const updatedPositions = pendingDrivers.reduce(
184+
(acc, { driver, progress, isPlayer }) => {
185+
const position = updateCarPosition(progress);
186+
return {
187+
...acc,
188+
[driver.CarIdx]: { position, driver, isPlayer, progress },
189+
};
190+
},
191+
{} as Record<number, TrackDriver & { position: { x: number; y: number } }>
192+
);
193+
194+
setPositions(updatedPositions);
195+
lastPositionsRef.current = updatedPositions;
196+
}, POSITION_UPDATE_INTERVAL);
197+
198+
return () => clearInterval(intervalId);
199+
}, [trackConstants, updateCarPosition]);
200+
159201
useEffect(() => {
160202
const ctx = canvasRef.current?.getContext('2d');
161203
if (!ctx) return;
@@ -269,10 +311,35 @@ export const TrackCanvas = ({ trackId, drivers }: TrackProps) => {
269311
ctx.restore();
270312
};
271313

314+
// Check if positions have actually changed
315+
const positionsChanged = () => {
316+
const currentPositions = Object.keys(positions);
317+
const lastPositions = Object.keys(lastPositionsRef.current);
318+
319+
if (currentPositions.length !== lastPositions.length) return true;
320+
321+
return currentPositions.some(key => {
322+
const carIdx = parseInt(key);
323+
const current = positions[carIdx];
324+
const last = lastPositionsRef.current[carIdx];
325+
326+
if (!current || !last) return true;
327+
328+
return (
329+
Math.abs(current.position.x - last.position.x) > 0.1 ||
330+
Math.abs(current.position.y - last.position.y) > 0.1 ||
331+
current.isPlayer !== last.isPlayer ||
332+
current.driver.CarNumber !== last.driver.CarNumber
333+
);
334+
});
335+
};
336+
272337
// Only animate if positions have changed
273338
const animate = () => {
274-
draw();
275-
lastPositionsRef.current = { ...positions };
339+
if (positionsChanged()) {
340+
draw();
341+
lastPositionsRef.current = { ...positions };
342+
}
276343
animationFrameIdRef.current = requestAnimationFrame(animate);
277344
};
278345

0 commit comments

Comments
 (0)