DEV Community

Cover image for The physics of a wheel a whole Twitch chat can brake
Basanoviat
Basanoviat

Posted on AI-assisted

The physics of a wheel a whole Twitch chat can brake

I'm building RaidPort, a Twitch channel that turns raids into a live gameshow for small streamers. You raid in at the end of your stream, your name gets a slice on a big wheel, and chat spins it. This post is about the wheel itself, because getting it to feel right took longer than anything else.

It runs on the server

The wheel is simulated on the server in Node.js and TypeScript, many times a second. The overlay in OBS only draws what it is told: the server streams the wheel's angle and speed to it over a WebSocket.

That split matters. Chat votes from everyone land on one wheel, and the winner is decided in one place that no viewer's browser can touch.

A slow wheel is a readable wheel

A real prize wheel slows down fast at first, then crawls. The crawl is the good part, because that is when everyone can read the names going past the pointer. So the friction changes with the wheel's speed: strong while it is flying, gentle once it is crawling.

Pure exponential slowdown has a catch: it never actually reaches zero, so the wheel would crawl forever. A small steady drain on top makes sure every spin ends.

Chat picks the spin length first

Before the spin, chat votes on whether it should be a fast spin or a slow one, and the result sets how long the wheel coasts if nobody touches it.

I did not want to tune friction by hand for every length. It turns out the time a spin takes to stop scales cleanly with the friction, so one dry run tells you exactly what friction gives the length you asked for. Pick a length, get that length.

Then chat brakes it

During the spin, anyone in chat can type !stop, and each vote adds friction. The hard part is making that fair for a channel with a handful of people and a channel with hundreds:

  • Per person. Each extra vote from the same person counts for less than the one before. Spamming helps a little, never a lot.
  • Across everyone. The more votes have already landed, the less each new one adds.
  • By audience size. In a bigger chat each vote is weaker, but there are more of them. There are limits at both ends.

Those limits came from a bug. The audience size was being read from the wrong place: the number of slices on the wheel instead of the number of people who could vote. A big raid against a small wheel got almost full strength per vote from hundreds of people, and the wheel stopped nearly at once, which is exactly what the scaling exists to prevent. The other limit covers the opposite case, so one person alone in chat cannot stop the wheel by themselves.

The ghost line

The overlay draws a second, faint speed line: what the wheel would be doing if nobody had typed !stop. The gap between the two lines is what chat did.

For that gap to mean anything, the ghost has to slow down by exactly the same rules as the real wheel. For a while it did not. The real wheel had its own copy of the slowdown math, so tuning the shared version quietly changed only the ghost, and the chart showed a gap chat never made. Now there is one copy and both lines go through it.

Landing on a name

The wheel only lands on channels that are live. If the slice under the pointer belongs to someone who has gone offline, the win moves to the next live slice, and the wheel eases over to it in under a second so it visibly rests on the channel that actually won.

One bug I would warn anyone about

Starting a spin started a fast timer loop. Starting another spin before the first one finished started another, and the old one kept running. After a few rounds the server had several zombie loops and the overlay started to stutter. The fix was one line, stop the old loop first, but it took a long test run to see it.


I'm one person building this. The portal opens Fall 2026, and if you stream, founding member signups are at raidport.tv.

Top comments (0)