Loading recipe…
The minimum code
const lineLayer = new PIXI.Container();
reelSet.addChild(lineLayer);
reelSet.events.on('win:group', (win, cells) => {
const gfx = new PIXI.Graphics();
const pts = cells.map(c => {
const b = reelSet.getCellBounds(c.reelIndex, c.rowIndex);
return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
});
gfx.moveTo(pts[0].x, pts[0].y);
for (let i = 1; i < pts.length; i++) gfx.lineTo(pts[i].x, pts[i].y);
gfx.stroke({ color: paletteFor(win), width: 6 });
lineLayer.addChild(gfx);
fadeOutAfter(gfx, 1200);
});
const presenter = new WinPresenter(reelSet); // no line drawing in core
await presenter.show(wins);
Why events, not an injected renderer
Overlays vary: payline polylines, cluster outlines, numbered badges, Spine
line rigs, particle trails. Baking any one into the core API would either
force a single look on every game, or grow a config surface that outlasts
the feature. Events plus reelSet.getCellBounds keeps the decision on
your side. draw whatever fits the art.
The event contract
| Event | Fires | Payload |
|---|---|---|
win:start | once per show() call | ordered wins list |
win:group | once per win per cycle | win, cell positions |
win:symbol | once per cell per win per cycle | symbol, cell, win |
win:end | once per show() | 'complete' or 'aborted' |
Dim is applied before win:group fires, so a listener taking a snapshot
sees the live state.