ReelSetBuilder
pixi-reels / index / ReelSetBuilder
Class: ReelSetBuilder
Defined in: core/ReelSetBuilder.ts:85
The configurator you call before every reel set.
ReelSetBuilder is a fluent, chainable builder: every call returns the
builder so you can string setup onto one expression. It hides the
twenty-odd subsystems you would otherwise have to wire by hand, and its
.build() step validates that every required piece is present (throws
at construction, not at first spin).
Required calls (in any order): .reels(n), .visibleCells(n),
.symbolSize(w, h), .symbols((registry) => ...), .ticker(app.ticker).
Optional: .symbolGap(), .weights(), .symbolData(), .speed(),
.bufferSymbols(), .offset(), .frameMiddleware(), .phases(),
.spinningMode().
const reelSet = new ReelSetBuilder()
.reels(5)
.visibleCells(3)
.symbolSize(200, 200)
.symbols((r) => {
r.register('cherry', SpriteSymbol, { textures: { cherry: tex } });
})
.weights({ cherry: 20 })
.ticker(app.ticker)
.build();
Constructors#
Constructor#
new ReelSetBuilder(): ReelSetBuilder;
Returns#
ReelSetBuilder
Methods#
bufferSymbols()#
bufferSymbols(count:
| number
| {
end: number;
start: number;
}): this;
Defined in: core/ReelSetBuilder.ts:616
Set number of buffer symbols either side of the visible window. Default: 1.
start is the edge at the smaller main coordinate (above for
vertical, left for horizontal) and end the larger one. Both are
geometric, not travel-relative: flipping a reel’s direction never
moves a buffer teaser to the opposite edge.
Buffer cells are off-screen cells the reel keeps around the visible
window so symbols can fade/slide in cleanly. The motion layer’s wrap
detection assumes at least one buffer cell each side. the minimum
supported count is 1. Passing 0 (or a negative number) is
clamped to 1 and a single console warning is printed; the builder
does not throw, so existing user code keeps running.
Tumble-only reel sets may drop the end-window buffer entirely
with the object form: bufferSymbols({ start: 1, end: 0 }). A pure
tumble never scrolls the strip, so nothing ever wraps through the
end-window cells. they exist only to be hidden by the mask. This
requires .tumble(...) on the builder (validated at build()), and
strip spins (spin({ mode: 'standard' })) and nudge() throw on
such a set. start keeps the minimum of 1 (drop-in movers are
pre-positioned outside the start edge).
Parameters#
| Parameter | Type |
|---|---|
count | | number | { end: number; start: number; } |
Returns#
this
build()#
build(): ReelSet;
Defined in: core/ReelSetBuilder.ts:964
Build the ReelSet. Validates configuration and assembles all internal objects.
Returns#
cellStacking()#
cellStacking(order: Stacking): this;
Defined in: core/ReelSetBuilder.ts:237
Render order of cells inside each reel. Default 'ascending'. the cell
at the larger main coordinate (bottom for vertical, right for
horizontal) draws in front of its neighbour.
Geometric on purpose: direction('reverse') and per-spin reversal do
NOT flip it, so symbol art lit from above keeps overlapping the way the
artist drew it. Set 'descending' if your art wants the opposite.
Parameters#
| Parameter | Type |
|---|---|
order | Stacking |
Returns#
this
curve()#
curve(curve: ReelCurveInput): this;
Defined in: core/ReelSetBuilder.ts:304
Fake the curvature of the reel cylinder on every reel in the set.
Cells bunch up and squash toward the window edges the way they would on a real drum, while the middle of the window magnifies slightly because it is the part facing you. It is a per-cell transform, so the art stays crisp, there is no render texture or shader, and a flat set (the default) pays nothing at all.
Parameters#
| Parameter | Type | Description |
|---|---|---|
curve | ReelCurveInput | 0 = flat, 1 = a hard barrel. Pass ReelCurveConfig to also tune depth, the cross-axis narrowing that keeps it reading as a drum rather than a squeezed flat strip. |
Returns#
this
Example#
builder.curve(0.35);
builder.curve({ amount: 0.5, depth: 0.3 });
curveBleed()#
curveBleed(pixels: number): this;
Defined in: core/ReelSetBuilder.ts:404
Cross-axis room, in pixels per side, for symbols whose art is WIDER than their cell - an overflowing mystery plate, leaves spilling past the tile.
curveMode('warp') renders each reel into a texture the size of the reel,
so anything hanging over the edge is sliced off at the texture boundary.
This gives the texture room, and the overflow is captured, warped with
everything else, and sticks out over its neighbours.
Costs texture area, so keep it to what the art actually needs. Warp mode
only; ignored under curveMode('symbol'), where symbols are real display
objects and overflow already draws.
Pair it with SharedRectMaskStrategy (or a curveFocus other than
'reel', which selects it for you) or the per-reel mask clips the
overhang straight back off.
Parameters#
| Parameter | Type |
|---|---|
pixels | number |
Returns#
this
Example#
builder.curve(0.45).curveMode('warp').curveBleed(40).renderer(app.renderer);
curveFocus()#
curveFocus(focus: CurveFocus): this;
Defined in: core/ReelSetBuilder.ts:412
Parameters#
| Parameter | Type |
|---|---|
focus | CurveFocus |
Returns#
this
curveMode()#
curveMode(mode: CurveMode): this;
Defined in: core/ReelSetBuilder.ts:364
How the curve is drawn.
'symbol' (default) projects each cell on its own: crisp, free, and a real
keystone - but only for symbols whose content IS a texture. A Container
transform is affine, so a Spine skeleton, a Graphics, or a composite
subtree can only be displaced and scaled by it, never bent.
'warp' renders each reel to a texture and draws it through a mesh whose
VERTICES are displaced by the projection. Everything inside the reel bends
identically - skeletons, atlas sprites, text, effects - and no symbol has
to cooperate. It costs one extra render pass per reel per frame and
resamples the reel once, so hairline art is marginally softer.
'warp' requires ReelSetBuilder.renderer.
Parameters#
| Parameter | Type |
|---|---|
mode | CurveMode |
Returns#
this
Example#
builder.curve(0.5).curveMode('warp').renderer(app.renderer);
curvePerReel()#
curvePerReel(curves: ReelCurveInput[]): this;
Defined in: core/ReelSetBuilder.ts:320
Per-reel curvature override (length must equal reels()). Reels omitted
fall back to curve().
Use it when the reels are not all the same size, or for the common trick of bending the middle reels harder than the outer ones so the board reads as one wide drum rather than five identical ones.
Parameters#
| Parameter | Type |
|---|---|
curves | ReelCurveInput[] |
Returns#
this
Example#
builder.curvePerReel([0.2, 0.35, 0.5, 0.35, 0.2]);
direction()#
direction(direction: Direction): this;
Defined in: core/ReelSetBuilder.ts:273
Default travel direction for every reel. 'forward' (default) heads toward
the larger coordinate (down for vertical); 'reverse' runs the other way
(roll-up on a vertical set).
Parameters#
| Parameter | Type |
|---|---|
direction | Direction |
Returns#
this
directionPerReel()#
directionPerReel(directions: Direction[]): this;
Defined in: core/ReelSetBuilder.ts:282
Per-reel travel direction override (length must equal reels()), for
alternating-column effects. Reels omitted fall back to direction().
Parameters#
| Parameter | Type |
|---|---|
directions | Direction[] |
Returns#
this
frameMiddleware()#
frameMiddleware(middleware: FrameMiddleware): this;
Defined in: core/ReelSetBuilder.ts:846
Add custom frame middleware.
Parameters#
| Parameter | Type |
|---|---|
middleware | FrameMiddleware |
Returns#
this
gsap()#
gsap(instance: typeof gsap): this;
Defined in: core/ReelSetBuilder.ts:834
Inject the GSAP instance the engine should use for tweens.
When you need this: if your app already imports gsap and your
bundler resolves gsap to a different module instance than the one
pixi-reels resolved (common with symlinked workspaces, npm-link, or
misconfigured dedupe), every tween you start on a target the engine
also tweens will fight a separate timeline. Symptoms: spotlights that
render but never finish, animations that double-fire, tweens that
silently drop on hidden tabs in only one of the two instances.
Calling .gsap(myGsap) binds every phase, motion tween, symbol
pin-flight tween, and SpriteSymbol win pulse to the GSAP you pass.
guaranteed to be the same instance that drives your own animations.
Default: the gsap import resolved at the engine’s own
node_modules/gsap path. If your app and the engine resolve to the
same instance (the common case in production bundles with proper
dedupe), you do NOT need to call this.
Per reel set, not process-wide. v1 stored one instance in a module
global, so the last .gsap() call before any build() silently won for
every set. Each set now captures the instance at build() time, so a
composed stage can drive two sets from different instances. Pass the
same instance to driveGsapWithTicker(ticker, instance).
Read at build(). calling it afterwards does not move an existing set.
Parameters#
| Parameter | Type |
|---|---|
instance | typeof gsap |
Returns#
this
Example#
import { gsap } from 'gsap';
const reelSet = new ReelSetBuilder()
.reels(5).visibleCells(3).symbolSize(200, 200)
.symbols(...)
.ticker(app.ticker)
.gsap(gsap) // ensure engine and app share one instance
.build();
initialFrame()#
initialFrame(frame: ColumnTarget[]): this;
Defined in: core/ReelSetBuilder.ts:949
Set the initial symbol grid the reels show before the first spin.
One ColumnTarget per reel. visible lists the symbols in the visible
window; optional bufferStart / bufferEnd prefill cells outside it
([0] is the slot closest to the visible window, later indices go
further out).
Parameters#
| Parameter | Type |
|---|---|
frame | ColumnTarget[] |
Returns#
this
Example#
builder.initialFrame([
{ visible: ['A','B','C'] },
{ visible: ['A','B','C'], bufferStart: ['COIN'] },
{ visible: ['A','B','C'], bufferEnd: ['SCATTER'] },
]);
initialSpeed()#
initialSpeed(name: string): this;
Defined in: core/ReelSetBuilder.ts:745
Set which speed profile to use initially. Default: ‘normal’.
Parameters#
| Parameter | Type |
|---|---|
name | string |
Returns#
this
maskStrategy()#
maskStrategy(strategy: MaskStrategy): this;
Defined in: core/ReelSetBuilder.ts:437
Custom mask strategy for the viewport. Defaults to RectMaskStrategy (one clip rect per reel. clean for pyramid + uniform layouts).
Use SharedRectMaskStrategy when reels have horizontal gaps AND symbols (typically big symbols) need to overlap across reel boundaries. the per-reel default would clip them at the gaps.
Or pass any custom MaskStrategy for non-rectangular masks (rounded
frames, hexagonal grids, etc.).
Parameters#
| Parameter | Type |
|---|---|
strategy | MaskStrategy |
Returns#
this
Example#
import { SharedRectMaskStrategy } from 'pixi-reels';
builder.maskStrategy(new SharedRectMaskStrategy())
motionModel()#
Call Signature#
motionModel(model: "tween"): this;
Defined in: core/ReelSetBuilder.ts:510
Choose how reel.speed gets from one value to the next.
'tween'(default) - phases tween the speed with a GSAP ease. Every existing game uses this and nothing about it changes.'drive'- the reel integrates toward a target speed under an acceleration bound, and phases set that target instead of tweening.
Why the second one exists: an ease applied to a SPEED is a step in
acceleration. power2.out puts peak deceleration on the very first frame
and decays from there, which is why the stock tease reads as the speed
setting changing rather than as the reel slowing down. Bounding
acceleration is the physical model instead - the reel can only change speed
so fast, whatever it is asked for. Add jerk and the acceleration itself
ramps, which is the pedal feel: down over time rather than stamped.
The drive also makes interruption free. A skip press, a mid-tease retarget
or a setSpeed mid-spin is a new target assignment, and the motion stays
continuous by construction - there is no timeline to kill and no leftover
speed to reconcile.
Set at build time only. There is no runtime toggle, because handing the speed field to a second owner while a phase is mid-tween is exactly the failure this design avoids.
Bounds are profile-relative by default: accelFrames: 20 means “reach
whatever the active profile calls full speed in 20 frames”, so Turbo
accelerates harder than Normal in proportion to how much faster it spins.
The absolute form (accel, px/frame^2) is still accepted, but one fixed
number cannot serve the shipped presets - their spinSpeed runs 30 / 50 /
80, so an absolute bound tuned for Normal makes SuperTurbo take 53 frames
to reach speed instead of 20, i.e. a turbo that starts SLOWER than normal.
Parameters
| Parameter | Type |
|---|---|
model | "tween" |
Returns
this
Examples
builder.motionModel('drive', { accelFrames: 20, decelFrames: 34, jerkFrames: 260 })
// Single-profile game, tuned in raw px/frame^2.
builder.motionModel('drive', { accel: 1.5, decel: 0.9, jerk: 0.12 })
Call Signature#
motionModel(model: "drive", config: ReelDriveConfig): this;
Defined in: core/ReelSetBuilder.ts:511
Choose how reel.speed gets from one value to the next.
'tween'(default) - phases tween the speed with a GSAP ease. Every existing game uses this and nothing about it changes.'drive'- the reel integrates toward a target speed under an acceleration bound, and phases set that target instead of tweening.
Why the second one exists: an ease applied to a SPEED is a step in
acceleration. power2.out puts peak deceleration on the very first frame
and decays from there, which is why the stock tease reads as the speed
setting changing rather than as the reel slowing down. Bounding
acceleration is the physical model instead - the reel can only change speed
so fast, whatever it is asked for. Add jerk and the acceleration itself
ramps, which is the pedal feel: down over time rather than stamped.
The drive also makes interruption free. A skip press, a mid-tease retarget
or a setSpeed mid-spin is a new target assignment, and the motion stays
continuous by construction - there is no timeline to kill and no leftover
speed to reconcile.
Set at build time only. There is no runtime toggle, because handing the speed field to a second owner while a phase is mid-tween is exactly the failure this design avoids.
Bounds are profile-relative by default: accelFrames: 20 means “reach
whatever the active profile calls full speed in 20 frames”, so Turbo
accelerates harder than Normal in proportion to how much faster it spins.
The absolute form (accel, px/frame^2) is still accepted, but one fixed
number cannot serve the shipped presets - their spinSpeed runs 30 / 50 /
80, so an absolute bound tuned for Normal makes SuperTurbo take 53 frames
to reach speed instead of 20, i.e. a turbo that starts SLOWER than normal.
Parameters
| Parameter | Type |
|---|---|
model | "drive" |
config | ReelDriveConfig |
Returns
this
Examples
builder.motionModel('drive', { accelFrames: 20, decelFrames: 34, jerkFrames: 260 })
// Single-profile game, tuned in raw px/frame^2.
builder.motionModel('drive', { accel: 1.5, decel: 0.9, jerk: 0.12 })
multiways()#
multiways(config: MultiWaysConfig): this;
Defined in: core/ReelSetBuilder.ts:543
Configure this slot as MultiWays: per-spin cell variation. Pass minCells,
maxCells, and the fixed reel pixel height. After build, call
reelSet.setShape(cellsPerReel) mid-spin to set the next stop’s shape.
Mutually exclusive with big-symbol registration (SymbolData.size).
Mutually exclusive with cascade mode in v1.
Parameters#
| Parameter | Type |
|---|---|
config | MultiWaysConfig |
Returns#
this
offsetConfig()#
offsetConfig(config: OffsetConfig): this;
Defined in: core/ReelSetBuilder.ts:751
Set X-axis offset config (e.g., trapezoid perspective). Default: ‘none’.
Parameters#
| Parameter | Type |
|---|---|
config | OffsetConfig |
Returns#
this
orientation()#
orientation(orientation: Orientation): this;
Defined in: core/ReelSetBuilder.ts:263
Strip travel axis for the whole set. 'vertical' (default) runs strips on
Y with reels marched along X; 'horizontal' runs them on X with reels
marched along Y.
Everything else is orientation-neutral: uniform grids, pyramids
(visibleCellsPerReel), MultiWays, big symbols and cascades all work on
either axis from the same arithmetic. symbolSize(width, height) stays
SCREEN-space, so a horizontal set gives the cell its main extent through
width where a vertical one uses height.
Parameters#
| Parameter | Type |
|---|---|
orientation | Orientation |
Returns#
this
phases()#
phases(configurator: (factory: PhaseFactory) => void): this;
Defined in: core/ReelSetBuilder.ts:864
Override default phases.
Configurators are DEFERRED to build() and run after the built-in
registrations, so a .phases(...) override of a cascade or MultiWays key
wins regardless of where it sits in the chain. Running them at call time
meant .tumble() / .multiways() registered their defaults later, inside
build(), and silently clobbered any 'cascade:*' / 'adjust' override
the caller had made. no error, just the built-in phase.
Multiple calls are kept and applied in call order, so the last override of a given key wins.
Parameters#
| Parameter | Type |
|---|---|
configurator | (factory: PhaseFactory) => void |
Returns#
this
pinMigrationDuration()#
pinMigrationDuration(value: number | ((reelIndex: number) => number)): this;
Defined in: core/ReelSetBuilder.ts:558
AdjustPhase tween duration in ms (MultiWays only). Pass a number for a
uniform duration across reels, or a function (reelIndex) => number
for per-reel control. Default: 200. Pass 0 for an instant snap (no
tween).
AdjustPhase plays on top of whatever stop staggering you’ve configured;
its duration is independent of stopDelay.
Parameters#
| Parameter | Type |
|---|---|
value | number | ((reelIndex: number) => number) |
Returns#
this
pinMigrationEase()#
pinMigrationEase(ease: string): this;
Defined in: core/ReelSetBuilder.ts:573
GSAP easing string used by AdjustPhase tweens (MultiWays only).
Applied to both the cell-resize tween and any pin-overlay migration
tween. Defaults to 'power2.out'. See gsap.com/docs/v3/Eases for
the full vocabulary.
Parameters#
| Parameter | Type |
|---|---|
ease | string |
Returns#
this
Example#
builder.pinMigrationEase('back.out(1.4)') // pop-in feel
builder.pinMigrationEase('expo.inOut') // slow start + slow end
poolCapacity()#
poolCapacity(maxPerSymbol: number): this;
Defined in: core/ReelSetBuilder.ts:792
Override the per-symbol-id recycle-pool capacity. By default the engine
sizes the pool to the whole strip (every visible + buffer cell), so even a
grid that is briefly all one symbol recycles instead of churning through
destroy() + recreate. Set this only to cap memory on very large grids, or
to raise headroom for unusually heavy simultaneous symbol swaps.
Parameters#
| Parameter | Type |
|---|---|
maxPerSymbol | number |
Returns#
this
randomSymbols()#
randomSymbols(pool: SymbolPool, scope?: SymbolPoolScope): this;
Defined in: core/ReelSetBuilder.ts:671
Narrow what the engine may draw when it fills a cell you did not name.
weights() sets the base table for every reel; this layers pools on
top of it, so a symbol can be common on the strip and impossible in
the buffer cells, or heavy on one reel only. Call it once per scope.
Buffer pools apply ON TOP of the spinning ones (see SymbolPoolScope),
and the same pools are reachable at run time as
reelSet.randomSymbols, which is where a game mode switch belongs.
Parameters#
| Parameter | Type |
|---|---|
pool | SymbolPool |
scope | SymbolPoolScope |
Returns#
this
Example#
.randomSymbols({ exclude: ['EMPTY'] }) // every reel
.randomSymbols({ exclude: ['COIN'] }, { slots: 'buffer' }) // buffers only
.randomSymbols({ weights: { WILD: 40 } }, { reel: 2 }) // reel 2 only
reelAnchor()#
reelAnchor(anchor: ReelAnchor): this;
Defined in: core/ReelSetBuilder.ts:222
Vertical alignment of short reels inside the tallest reel’s box. Default ‘center’.
Parameters#
| Parameter | Type |
|---|---|
anchor | ReelAnchor |
Returns#
this
reelExtents()#
reelExtents(heights: number[]): this;
Defined in: core/ReelSetBuilder.ts:216
Per-reel pixel-box heights. Length MUST equal reels().
- Pyramid: defaults to
visibleCellsPerReel[i] * symbolHeight. Override to make all reels the same height with different cell heights per reel. - MultiWays: every entry equals the same fixed reel height. Cell
height per reel is derived as
reelExtent / visibleCells[i].
Precedence: when both reelExtents and reelAnchor are set,
reelExtents wins. anchor is derived from the explicit boxes.
Parameters#
| Parameter | Type |
|---|---|
heights | number[] |
Returns#
this
reelPixelHeights()#
reelPixelHeights(_heights: number[]): never;
Defined in: core/ReelSetBuilder.ts:167
Parameters#
| Parameter | Type |
|---|---|
_heights | number[] |
Returns#
never
Deprecated#
Removed in v2 - throws. Use ReelSetBuilder.reelExtents.
reels()#
reels(count: number): this;
Defined in: core/ReelSetBuilder.ts:174
Set number of reel columns.
Parameters#
| Parameter | Type |
|---|---|
count | number |
Returns#
this
reelStacking()#
reelStacking(order: Stacking): this;
Defined in: core/ReelSetBuilder.ts:247
Render order of reels inside the set. Default 'ascending'. the last
reel draws in front, which reads as “rightmost on top” for vertical and
“bottom-most on top” for horizontal.
Parameters#
| Parameter | Type |
|---|---|
order | Stacking |
Returns#
this
renderer()#
renderer(renderer: Renderer): this;
Defined in: core/ReelSetBuilder.ts:379
The renderer curveMode('warp') draws each reel’s texture with. Required
for warp mode and unused otherwise.
Parameters#
| Parameter | Type |
|---|---|
renderer | Renderer |
Returns#
this
Example#
builder.renderer(app.renderer)
rng()#
rng(fn: () => number): this;
Defined in: core/ReelSetBuilder.ts:780
Inject the source of randomness used to fill the scrolling strip (buffer
fill, the symbols shown during SPIN before setResult lands, nudge
padding). Must return a value in [0, 1). Default: Math.random.
Why you’d set this: server-authoritative outcomes do not make the on-screen strip reproducible — the symbols a player sees scrolling are drawn from this RNG. Injecting a seeded, audited PRNG lets you replay the exact visual sequence from a seed, which provably-fair and regulated real-money deployments are eventually required to produce.
Parameters#
| Parameter | Type |
|---|---|
fn | () => number |
Returns#
this
Example#
import { ReelSetBuilder } from 'pixi-reels';
const seeded = mulberry32(serverSeed); // your audited PRNG
const reelSet = new ReelSetBuilder().reels(5).visibleCells(3)
.symbols(...).ticker(app.ticker).rng(seeded).build();
skipMode()#
skipMode(mode: SkipMode): this;
Defined in: core/ReelSetBuilder.ts:875
What a skip press does to the reels it frees when the call does not say:
'slam' places them (the default), 'quicken' asks each for its landing
sooner. See SkipMode. requestSkip({ mode }) and skipSpin({ mode })
override it per press; slamStop() is always a slam.
Parameters#
| Parameter | Type |
|---|---|
mode | SkipMode |
Returns#
this
speed()#
speed(name: string, profile: SpeedProfile): this;
Defined in: core/ReelSetBuilder.ts:739
Add a named speed profile.
Parameters#
| Parameter | Type |
|---|---|
name | string |
profile | SpeedProfile |
Returns#
this
spinningMode()#
spinningMode(mode: SpinningMode): this;
Defined in: core/ReelSetBuilder.ts:840
Set the spinning mode. Default: StandardMode.
Parameters#
| Parameter | Type |
|---|---|
mode | SpinningMode |
Returns#
this
symbolData()#
symbolData(overrides: Record<string, Partial<SymbolData>>): this;
Defined in: core/ReelSetBuilder.ts:695
Per-symbol metadata overrides (zIndex, unmask, or a custom weight that
replaces the one from weights()). Merged into the final symbolsData map;
any field you don’t specify falls back to the default.
zIndex sorts within ONE reel’s container only. it can never lift a
symbol above the reel to its right (reels are separate containers).
Cross-reel and out-of-mask layering needs unmask: true, which is an
at-rest presentation: while the reel spins the symbol stays masked
like everything else; on land, visible-cell instances are lifted into
the viewport-wide unmaskedContainer (above every reel and the mask)
and pulled back down when the next spin starts.
Parameters#
| Parameter | Type |
|---|---|
overrides | Record<string, Partial<SymbolData>> |
Returns#
this
Example#
.symbolData({
wild: { zIndex: 5 }, // above reel-mates (same reel only)
bonus: { zIndex: 10, unmask: true }, // landed: above all reels + mask
})
symbolGap()#
symbolGap(x: number, y: number): this;
Defined in: core/ReelSetBuilder.ts:586
Set gap between symbols. Default: { x: 0, y: 0 }.
Parameters#
| Parameter | Type |
|---|---|
x | number |
y | number |
Returns#
this
symbols()#
symbols(configurator: (registry: SymbolRegistry) => void): this;
Defined in: core/ReelSetBuilder.ts:644
Configure symbols via a registry callback.
Parameters#
| Parameter | Type |
|---|---|
configurator | (registry: SymbolRegistry) => void |
Returns#
this
symbolSize()#
symbolSize(width: number, height: number): this;
Defined in: core/ReelSetBuilder.ts:579
Set symbol dimensions in pixels.
Parameters#
| Parameter | Type |
|---|---|
width | number |
height | number |
Returns#
this
symbolZIndex()#
symbolZIndex(resolver: SymbolZIndexResolver): this;
Defined in: core/ReelSetBuilder.ts:730
Decide every symbol view’s zIndex yourself instead of taking the
engine’s symbolData.zIndex * 100 + cellStackingIndex.
The resolver is the single source of symbol draw order once set: the
engine asks it again whenever a symbol’s id, cell, reel shape or rest
state changes (every wrap, snap, swap, reshape, landing and departure).
It must be pure and cheap. Return ctx.defaultZIndex for the ids you do
not care about.
Cross-reel order only exists for symbols that share a container: an
unmask: true symbol at rest is lifted into the viewport-wide
unmaskedContainer, where the value orders it against every other
lifted symbol. A masked symbol stays inside its reel’s own container,
which has its own zIndex (reelStacking), so a resolver’s reel term
does nothing for it. ctx.atRest tells the two situations apart: the
usual shape keeps the engine’s order in motion and grades at rest.
Parameters#
| Parameter | Type |
|---|---|
resolver | SymbolZIndexResolver |
Returns#
this
Example#
.symbolZIndex((ctx) => {
if (!ctx.atRest || ctx.visibleCell === null) return ctx.defaultZIndex;
const grade = GRADES[ctx.symbolId];
return grade === undefined
? ctx.defaultZIndex
: grade * 1000 + ctx.visibleCell * 10 + ctx.reelIndex;
})
ticker()#
ticker(ticker: Ticker): this;
Defined in: core/ReelSetBuilder.ts:758
Set the PixiJS ticker for frame updates.
Parameters#
| Parameter | Type |
|---|---|
ticker | Ticker |
Returns#
this
tumble()#
tumble(config?: TumbleConfig): this;
Defined in: core/ReelSetBuilder.ts:915
Enable tumble cascade mechanics. Replaces strip-spin + bounce-stop with a three-phase pipeline:
cascade:fall. onspin(), existing visible symbols fall off the bottom of the viewport.cascade:place. whensetResult()arrives, new symbol identities swap into the buffer at their final grid positions.cascade:dropIn. new symbols animate from above (and survivors slide down to fill holes) into the grid.
For a Moment B refill after wins are cleared, call
reelSet.refill({ winners, grid }). that skips fall + wait and runs
place + dropIn only, with gravity-correct geometry driven by the
winners list (untouched symbols don’t animate; survivors slide;
new symbols come from above).
Every phase boundary fires a cascade:* event on
reelSet.events. per-symbol events (cascade:fall:symbol /
cascade:dropIn:symbol) carry the symbol, view, and the timing the
library is about to apply, so listeners can run parallel tweens on
any other property in sync with the library’s view.y motion.
Override any individual phase via .phases(f => f.register('cascade:fall', MyPhase)).
Chain position does not matter. .phases(...) is applied after these
defaults regardless. Subclasses of the cascade phases need
registerFactory and the extra constructor args, which
resolveTumbleConfig(config) produces.
Parameters#
| Parameter | Type |
|---|---|
config? | TumbleConfig |
Returns#
this
Example#
builder.tumble({
fall: { duration: 300, ease: 'sine.in', cellStagger: 60 },
dropIn: { duration: 600, ease: 'power2.out', cellStagger: 60, distance: 'perHole' },
});
visibleCells()#
visibleCells(count: number): this;
Defined in: core/ReelSetBuilder.ts:187
Number of visible cells per reel (uniform across all reels).
Mutually exclusive with visibleCellsPerReel(). calling both throws
at build().
Parameters#
| Parameter | Type |
|---|---|
count | number |
Returns#
this
Example#
builder.reels(5).visibleCells(3) // classic 5x3
visibleCellsPerReel()#
visibleCellsPerReel(cells: number[]): this;
Defined in: core/ReelSetBuilder.ts:199
Per-reel static cell counts. Length MUST equal reels(). Mutually
exclusive with visibleCells(); calling both throws at build().
Parameters#
| Parameter | Type |
|---|---|
cells | number[] |
Returns#
this
Example#
builder.reels(5).visibleCellsPerReel([3, 5, 5, 5, 3]) // pyramid
visibleRows()#
visibleRows(_count: number): never;
Defined in: core/ReelSetBuilder.ts:155
Parameters#
| Parameter | Type |
|---|---|
_count | number |
Returns#
never
Deprecated#
Removed in v2 - throws. Use ReelSetBuilder.visibleCells.
TypeScript catches a v1 call at compile time, but an untyped consumer would otherwise get “x.visibleRows is not a function”, which names neither the replacement nor the codemod. These stubs do.
visibleRowsPerReel()#
visibleRowsPerReel(_cells: number[]): never;
Defined in: core/ReelSetBuilder.ts:160
Parameters#
| Parameter | Type |
|---|---|
_cells | number[] |
Returns#
never
Deprecated#
Removed in v2 - throws. Use ReelSetBuilder.visibleCellsPerReel.
weights()#
weights(weights: Record<string, number>): this;
Defined in: core/ReelSetBuilder.ts:650
Set weights for random symbol generation.
Parameters#
| Parameter | Type |
|---|---|
weights | Record<string, number> |
Returns#
this