import { GameState } from '../state/GameState.js'; import { SlotMachine } from '../objects/SlotMachine.js'; import { WinAnimation } from '../objects/WinAnimation.js'; import { LossAnimation } from '../objects/LossAnimation.js'; import { VialDisplay } from '../objects/VialDisplay.js'; export default class GameScene extends Phaser.Scene { constructor() { super({ key: 'GameScene' }); } create() { // Background image — stretched to fill the canvas this.add.image(800, 450, 'bg-gates').setDisplaySize(1600, 900); // Gradient backdrop behind title — opaque on left, fades to transparent const titleBg = this.add.graphics(); titleBg.fillGradientStyle(0x000000, 0x000000, 0x000000, 0x000000, 0.62, 0, 0.62, 0); titleBg.fillRect(0, 110, 700, 120); // Title above the machine — left aligned with padding this.add.text(40, 150, 'VIRTUE SLOTS', { fontSize: '42px', fontFamily: 'Georgia, serif', color: '#ffd700', stroke: '#5a3000', strokeThickness: 4, shadow: { offsetX: 2, offsetY: 2, color: '#000', blur: 6, fill: true } }).setOrigin(0, 0.5); this.add.text(40, 195, '✝ May Fortune Favor the Faithful ✝', { fontSize: '18px', fontFamily: 'Georgia, serif', color: '#c8a87e', alpha: 0.8 }).setOrigin(0, 0.5); // Slot machine — vertically centered to match The Reckoning panel (y=202–690) this.slotMachine = new SlotMachine(this, 710, 446); this.winAnim = new WinAnimation(); this.lossAnim = new LossAnimation(); // ── Right section: The Reckoning vials ────────────────────────────────── // Panel vertically centered in play area (y=100–790), with ~87px right margin const sectionBg = this.add.graphics(); sectionBg.fillStyle(0x0c0620, 0.65); sectionBg.fillRoundedRect(1085, 202, 428, 488, 14); sectionBg.lineStyle(1, 0xffd700, 0.3); sectionBg.strokeRoundedRect(1085, 202, 428, 488, 14); this.add.text(1299, 220, 'THE RECKONING', { fontSize: '13px', fontFamily: 'Georgia, serif', color: '#c8a87e', letterSpacing: 5, }).setOrigin(0.5, 0.5); this.add.text(1299, 238, 'First to $2,000 wins', { fontSize: '10px', fontFamily: 'Georgia, serif', color: '#4a5a6a', }).setOrigin(0.5, 0.5); this.add.text(1295, 443, 'VS', { fontSize: '20px', fontFamily: 'Georgia, serif', fontStyle: 'bold', color: '#2a1a4a', stroke: '#000000', strokeThickness: 3, }).setOrigin(0.5, 0.5); this.lordVial = new VialDisplay(this, 1193, 258, 'The Lord', 0xffd700, 0xc8a87e); this.sinVial = new VialDisplay(this, 1398, 258, 'Sin', 0xff4444, 0xff6666); // Keyboard: Space to spin this.input.keyboard.on('keydown-SPACE', () => this._triggerSpin()); // Listen for spin button events from UIScene via global event bus this.game.events.on('spin', () => this._triggerSpin(), this); } _triggerSpin() { if (GameState.spinning) return; if (GameState.playerFunds < GameState.spinCost) { this.game.events.emit('insufficient-funds'); return; } GameState.playerFunds -= GameState.spinCost; GameState.spinning = true; this.game.events.emit('funds-updated'); this.slotMachine.spin((result) => this._handleResult(result)); } _handleResult({ win, symbols, payout }) { if (win) { const playerGain = Math.round(payout * 0.6); const lordGain = payout - playerGain; this.game.events.emit('win', { playerGain, lordGain, symbol: symbols[0] }); // Resolve UI box positions from UIScene const uiScene = this.scene.get('UIScene'); const playerBox = uiScene ? uiScene.getPlayerBoxCenter() : { x: 267, y: 60 }; const lordBox = uiScene ? uiScene.getLordBoxCenter() : { x: 800, y: 60 }; this.winAnim.play( this, this.slotMachine.getCenterX(), this.slotMachine.getCenterY(), playerBox, lordBox, symbols[0], () => { GameState.playerFunds += playerGain; GameState.lordFunds += lordGain; this.game.events.emit('funds-updated'); this.lordVial.animateUpdate(GameState.lordFunds, lordBox.x, 115, () => { GameState.spinning = false; this.game.events.emit('spin-complete'); }); } ); } else { this.game.events.emit('loss', { sinAdded: GameState.spinCost }); const uiScene = this.scene.get('UIScene'); const sinBox = uiScene ? uiScene.getSinBoxCenter() : { x: 1333, y: 60 }; this.lossAnim.play( uiScene || this, this.slotMachine.getCenterX(), this.slotMachine.getCenterY(), sinBox, () => { GameState.sinTotal += GameState.spinCost; this.game.events.emit('funds-updated'); this.sinVial.animateUpdate(GameState.sinTotal, sinBox.x, 115, () => { GameState.spinning = false; this.game.events.emit('spin-complete'); }); } ); } } }