pixi-reels
All recipes

Hold & Win: mystery value coin

A coin lands as a blank gold disc and its amount is unknown until, on lock, a strip of candidate values spins inside the coin face and decelerates onto the real number. The value lives in coin.data; the board never reads it.

Loading recipe…

Press Run. Coins land as blank gold discs; the moment each one locks, a column of candidate amounts rolls past inside the coin and decelerates onto the value it actually held — then the number paints in the game’s gold digit font.

The value never touches the board

Each hit is { cell, id: 'coin', data: { value } }. HoldAndWinBuilder stores the coin exactly as it landed and never interprets data. The reveal is entirely game-layer: a coin:locked handler reads coin.data.value, runs the roll, and paints the label. Swap the payload for a multiplier or a jackpot tier and the board does not change.

The reveal is a true looping reel

A value reveal is just a one-row reel whose symbols are numbers. A small set of K gold-font rows is recycled with a modulo wrap — a row leaving one edge of the masked window reappears at the other — so a handful of labels scroll forever like a real strip. Row 0 carries the real value; the rest are decoys:

const TOTAL = K * ROW_H;
const wrap = (v) => { const m = ((v % TOTAL) + TOTAL) % TOTAL; return m > TOTAL / 2 ? m - TOTAL : m; };
const layout = (offset) => rows.forEach((t, i) => { t.y = centerY + wrap(i * ROW_H - offset); });

Because row 0 is centred whenever offset is a multiple of TOTAL, one eased tween over several whole turns spins the digits and decelerates exactly onto the value — no pre-built ending strip, no teleport:

gsap.to(state, { offset: TURNS * TOTAL, duration: 1.5, ease: 'expo.out', onUpdate: () => layout(state.offset) });

expo.out gives the fast blur-then-settle a physical reel has. When it lands, the strip is destroyed, the final amount is painted, and board.symbolAt(cell).playWin() plays the coin’s own flourish as the “ding”. For the engine-native variant — a nested 1×1 ReelSet of number symbols that gets the real spin physics (bounce, anticipation) for free — see the sprite starter for how cheaply a second reel composes.

Gate the respins on the reveals

Every reveal promise is pushed into a pendingFx batch; the run loop await Promise.all(pendingFx.splice(0)) before the next board.respin(...), so no coin ever lands on top of a roll still in flight.