Virtue-Slots/objects/SlotMachine.js

84 lines
2.4 KiB
JavaScript

import { SYMBOLS } from './Symbol.js';
import { Reel } from './Reel.js';
import { shouldWin, pickResults } from '../utils/RNG.js';
const REEL_GAP = 20;
const REEL_WIDTH = 200;
const REEL_HEIGHT = 330; // 3 * 110 (matches Reel.js SYMBOL_HEIGHT)
export class SlotMachine {
constructor(scene, centerX, centerY) {
this.scene = scene;
this.centerX = centerX;
this.centerY = centerY;
// Draw the machine frame
this.framGfx = scene.add.graphics();
this._drawFrame();
// Three reels, side by side
const totalWidth = REEL_WIDTH * 3 + REEL_GAP * 2;
const startX = centerX - totalWidth / 2;
const startY = centerY - REEL_HEIGHT / 2;
this.reels = [
new Reel(scene, startX, startY),
new Reel(scene, startX + REEL_WIDTH + REEL_GAP, startY),
new Reel(scene, startX + (REEL_WIDTH + REEL_GAP) * 2, startY),
];
// Center line indicator
const lineGfx = scene.add.graphics();
lineGfx.lineStyle(3, 0xffd700, 0.9);
lineGfx.beginPath();
lineGfx.moveTo(startX - 10, centerY);
lineGfx.lineTo(startX + totalWidth + 10, centerY);
lineGfx.strokePath();
this.lastResults = null;
}
_drawFrame() {
const g = this.framGfx;
const cx = this.centerX;
const cy = this.centerY;
const w = REEL_WIDTH * 3 + REEL_GAP * 2 + 60;
const h = REEL_HEIGHT + 60;
// Outer frame
g.fillStyle(0x2a1040, 1);
g.fillRoundedRect(cx - w / 2, cy - h / 2, w, h, 16);
g.lineStyle(4, 0xffd700, 1);
g.strokeRoundedRect(cx - w / 2, cy - h / 2, w, h, 16);
// Inner shadow
g.lineStyle(2, 0x8844aa, 0.6);
g.strokeRoundedRect(cx - w / 2 + 6, cy - h / 2 + 6, w - 12, h - 12, 12);
}
// spin(onComplete) — onComplete receives { win, symbols, payout }
spin(onComplete) {
const win = shouldWin();
const results = pickResults(SYMBOLS, win);
this.lastResults = results;
const payout = win ? results[0].payout : 0;
let doneCount = 0;
const totalReels = this.reels.length;
const stopDelays = [800, 1300, 1800]; // ms before each reel starts decelerating
this.reels.forEach((reel, i) => {
reel.spin(results[i], stopDelays[i], () => {
doneCount++;
if (doneCount === totalReels) {
onComplete({ win, symbols: results, payout });
}
});
});
}
getCenterX() { return this.centerX; }
getCenterY() { return this.centerY; }
}