import { Assets, Container } from 'pixi.js'; import { IBone, Spine } from 'pixi-spine'; import { Updatable } from '../types/Entity'; import { ITrackEntry } from '../types/ITrackEntry'; interface IBoneExtended extends IBone { x: number; y: number; } /** * @class WinLine * @extends Container * @implements Updatable * @description * The `WinLine` class represents a visual line in a slot machine game that can be animated to show winning lines. * It extends the `Container` class and implements the `Updatable` interface. * The class uses Spine animations to display the win line and provides methods to set the line's position, * update the animation state, and trigger idle and win animations. */ export default class WinLine extends Container implements Updatable { spine: Spine; slotSize: { x: number, y: number }; constructor() { super(); this.spine = new Spine(Assets.get('win_line').spineData); this.spine.autoUpdate = false; this.spine.state.timeScale = 1; this.spine.alpha = 0.8; this.idle(); this.addChild(this.spine); this.spine.state.addListener({ event: (_, event) => { if (event.data.name === 'end') { this.idle(); } } }); this.zIndex = 10100; this.slotSize = { x: 200, y: 200 }; this.scale.set(0.52); this.position.set(0, this.slotSize.y * 0.5 * this.scale.y); } /** * Sets the positions of the control bones based on the provided line map. * @param lineMap - An array of numbers representing the slot indices for each reel. * @returns void */ set(lineMap: number[]): void { (this.spine.skeleton.findBone('control_0') as IBoneExtended).y = -lineMap[0] * this.slotSize.y; (this.spine.skeleton.findBone('control_6') as IBoneExtended).y = -lineMap[lineMap.length - 1] * this.slotSize.y; lineMap.forEach((slotIndex: number, reelIndex: number) => { const control = this.spine.skeleton.findBone(`control_${reelIndex + 1}`) as IBoneExtended; if (!control) return; control.y = -slotIndex * this.slotSize.y; }); } /** * Updates the spine animation with the given delta time. * @param dt - The delta time in milliseconds. * @returns void */ update(dt: number): void { this.spine.update(dt * 0.001); } /** * Sets the animation to 'idle' on the spine state. * @returns {ITrackEntry} The track entry of the animation. */ idle(): ITrackEntry { return this.spine.state.setAnimation(0, 'idle', false); } /** * Triggers the 'win' animation on the spine state. * @returns {ITrackEntry} The track entry of the animation. */ win(): ITrackEntry { return this.spine.state.setAnimation(0, 'win', false); } }