Inside the most visible part of any slot game, and how to keep reel motion fluid at 60fps
Inside the reel engine: motion state transitions, easing curve math, stop timing and bounce-back, anticipation effects, and holding a steady 60fps frame rate.
Reel animation is the most iconic visual element of a slot game, and the only part players judge by "feel." Two games with identical rules can go from feeling "crisp and decisive" to "sluggish and dragging" purely because their stop timing differs by a few dozen milliseconds. A good reel engine has to deliver a spin that is silky smooth and physically convincing, and that feel has to be tunable and reproducible rather than something stumbled upon by trial and error.
Of these six stages, only the length of "wait for result" is determined externally; the engine controls the other five itself.
At its core, each frame the engine computes the reel's displacement, and when it exceeds the height of one cell, symbol recycling is triggered:
Displacement has to be computed against elapsed time rather than frame count, otherwise the spin speed on a 120Hz display would be double that on a 60Hz one, and the stop timing would come early across the board.
But when the application comes back to the foreground from the background, a single frame's elapsed time can be several seconds, and applying it directly would make the reels skip a huge number of symbols in one frame, so a cap on single-frame time is also required.
An easing function maps "progress ratio" to "displacement ratio": the input runs from 0 to 1 and the output also runs from 0 to 1, but how it gets there determines whether the motion reads as constant speed, acceleration, deceleration or bounce.
What we use most often is the cubic Bezier curve: the start and end points are fixed at 0 and 1, and the only things actually adjustable are two control points, four parameters in total, enough to express rich rhythms yet few enough to hand straight to an artist for fine-tuning.
One implementation detail to watch is that a Bezier curve is defined parametrically, so getting displacement for a given time requires solving rather than direct substitution; the engine samples the curve uniformly at initialization to build a lookup table, and at runtime replaces per-frame solving with table lookup plus interpolation.
A real slot machine has a subtle "overshoot" when it stops. The reel goes slightly past the target position, then springs back into place. This segment can be described with a damped oscillation model, where a spring pulls the reel toward the target while damping dissipates energy, and it has only two intuitive parameters:
The stop as a whole then breaks into three independently adjustable intervals:
Fast-paced games use a smaller overshoot and a quick rebound, while classic-style ones use a more exaggerated bounce to create a mechanical feel.
Another parameter that often gets overlooked is the pre-bounce: a slight backward displacement before the start, then acceleration downward. It lasts only a few dozen milliseconds, yet it noticeably increases the sense of force.
A single column tuned to look good does not mean the whole reel set feels good. When multiple columns move together, what really determines the impression is timing:
These four values have to be tuned as a set, which is why we package them into rhythm presets that can be switched as a whole.
When the player taps again mid-spin, all reels need to stop immediately. The tricky part is this: if you compress the animation time to one tenth, the overshoot and rebound shrink proportionally too, and it looks like a "fast-forward" rather than a "brake."
The better approach is to re-plan the deceleration curve rather than scale the original one: keep the rebound segment at its full length, compress only the deceleration segment in front of it, and recompute the remaining distance from the actual current speed.
Beyond the basic spin and stop, the reel engine also needs to support a variety of special effects, the most important of which is building a sense of anticipation:
There is one line anticipation must never cross: every suspense mechanism is a result-driven presentation-layer behavior. The engine merely picks how to perform based on an already-determined result, and the performance itself never changes where any symbol lands. Write that line into the interface design, and the engine simply has no ability to decide whether to play an anticipation before the result arrives.
Most of the reel engine's performance problems come not from the amount of computation but from per-frame object churn. Creating and releasing display objects every frame causes garbage collection to fire at unpredictable moments, which shows up as a hitch every few seconds.
The point of the object pool is not just to save creation cost but to keep memory usage flat. Two more measures are worth handling alongside it:
When the reels spin at high speed, a symbol may move farther per frame than its own height, and at that point the eye sees a series of discrete positions rather than continuous motion, producing an obvious strobing sensation. There are three ways to handle it:
These three measures are usually used together, and the switching thresholds also need to be verified separately on low-refresh-rate devices: a spin speed that shows no problem on a 120Hz display may already strobe visibly at 60Hz.
The reel engine is about feel, but it does not operate in isolation: it relies on the reuse foundation provided by the layered architecture and on the start/stop commands issued by the state machine, while when assets get loaded and how the stop sound lines up with the visuals belong to the domain of the supporting systems. We discuss those two topics in the other two articles of this series.