Client-side interpolation loop (requestAnimationFrame)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- javascript, react, typescript
Research direction
Start with ui/src/util/simulate.ts and the rAF loop in App.tsx, then read ui/src/util/playbackBuffer.ts to understand tick release and timing. Extend the existing simulation math for fractional steps and reconcile to server values on each released tick. Done means motion is smooth between ticks without accumulated drift; the issue names tests for simulation, buffering, reducer resync, and App rAF wiring.
Written by the indexing model from the issue text.
Description
Drive smooth motion from a requestAnimationFrame loop (extrapolating from simulate.ts) so animation stays fluid even when SSE frames arrive irregularly (e.g. behind a buffering proxy/tunnel) instead of relying on per-event CSS transitions.
Effort: M
Migrated from ENHANCEMENTS.md (§5 Polish, performance & accessibility).
Implementation notes
Priority: medium — Polish on top of an already-shipped rAF/jitter-buffer smoothing system (App.tsx + playbackBuffer.ts) — improves perceived fluidity for all spectators but doesn't fix a correctness/stability gap or unblock other work.
Purpose
Bot motion currently jumps by a whole tick's worth of movement the instant a buffered tick group is released, so even though App.tsx already paces release via requestAnimationFrame + PlaybackBuffer (ui/src/util/playbackBuffer.ts), position/rotation still steps discretely (~every NOMINAL_TICK_MS=100ms) rather than gliding every frame. Sub-tick extrapolation makes the arena visibly fluid at 60fps regardless of SSE/tick cadence, improving the core spectating experience with no server changes.
Implementation approach
ui/src/util/simulate.tscurrently mutates full-tick deltas (position viaspeed, rotation viabodyOrientationVelocity, etc.) in one call fromarenaReducer.ts'stickbranch. Add a fractional-dtvariant (or ascale/fractionparam on the existing function) so the same movement/rotation formulas can be applied per-rAF-frame proportional to elapsed time within the current tick window, instead of only once per whole tick.- In
App.tsx's existing rAF loop (~lines 279-311), afterbuffer.current.drain(...)releases a tick-group (authoritative resync viaapplyArenaEvent), extrapolate every intermediate frame forward using the fractional Simulate call, based onPlaybackBuffer's knowntickMs/speedFactor— this is new logic layered on top of, not replacing, the existing jitter buffer. - Must snap back to server-authoritative values (
bodyOrientationTarget,x/yfrombotTurn/botAccelerateevents) on each real tick release so extrapolation error never accumulates/drifts — same reconciliation pattern already used for the discrete jump. - No bot-facing API or
compiler.tschange; this is purelyui/client rendering. Serverutil/simulation.tsmath (speed/rotation formulas) must stay mirrored in the extendedsimulate.tsper the existing comment convention.
Key details to plan
- No DB/service or REST/MCP contract changes.
- No sandbox/security implications (client rendering only).
- Determinism: extrapolation is visual-only and must not feed back into any state sent to the server; the seeded-PRNG server simulation remains sole source of truth, reconciled each tick.
- Testing: extend
ui/test/simulate.test.ts(fractional-step math),ui/test/playbackBuffer.test.ts/playbackClock.test.ts(frame pacing),ui/test/arenaReducer.test.ts(resync behavior), andui/test/App.test.tsxfor the rAF wiring. - Watch for interaction with bullet/path rendering (
arenaBotPath.test.ts) which currently only records path vertices on discrete tick application. - Effort M is reasonable; risk is low-medium — mainly getting reconciliation/anti-drift right and avoiding double-counting motion already applied by
PlaybackBuffer.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 8m
- Merged PRs (30d)
- 8
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from LeeAdcock/robocodeJs.com
-
priority: medium tech-debt
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
LeeAdcock/robocodeJs.com#411 ·
Maintainers usually reply within 1 day
-
enhancement priority: medium
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
LeeAdcock/robocodeJs.com#254 ·
Maintainers usually reply within 1 day
-
good first issue priority: low tech-debt
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
LeeAdcock/robocodeJs.com#146 ·
Maintainers usually reply within 1 day
-
dependencies priority: low tech-debt
Difficulty 1/5 Under an hour Newbie friendliness 15/100
LeeAdcock/robocodeJs.com#413 ·
Maintainers usually reply within 1 day
-
priority: low tech-debt
Difficulty 3/5 Half a day Newbie friendliness 32/100
LeeAdcock/robocodeJs.com#412 ·
Maintainers usually reply within 1 day
All issues in LeeAdcock/robocodeJs.com
Similar issues
-
ai-driven-qa bug claude Minor
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
linagora/twake-contacts-frontend#241 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
ui(ListToolbar): search takes the full row on a phone instead of sharing it with the result countOpen
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
Maintainers usually reply within 1 day
-
priority:high
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
ahmedkhaleel2004/gitdiagram#228 ·