import { GameState } from '../state/GameState.js'; const TOP_BAR_HEIGHT = 100; const BOTTOM_BAR_HEIGHT = 110; const BOTTOM_BAR_Y = 900 - BOTTOM_BAR_HEIGHT; // Box centers (x) for the three top fund displays const BOX_WIDTH = 1600 / 3; const PLAYER_BOX_X = BOX_WIDTH * 0 + BOX_WIDTH / 2; const LORD_BOX_X = BOX_WIDTH * 1 + BOX_WIDTH / 2; const SIN_BOX_X = BOX_WIDTH * 2 + BOX_WIDTH / 2; const BOX_CENTER_Y = TOP_BAR_HEIGHT / 2; export default class UIScene extends Phaser.Scene { constructor() { super({ key: 'UIScene' }); } create() { this._buildTopBar(); this._buildBottomBar(); this._buildSpinButton(); this._bindEvents(); this._updateFundDisplays(); } _buildTopBar() { const g = this.add.graphics(); // Background g.fillStyle(0x12082a, 1); g.fillRect(0, 0, 1600, TOP_BAR_HEIGHT); g.lineStyle(2, 0xffd700, 0.8); g.strokeRect(0, 0, 1600, TOP_BAR_HEIGHT); // Dividers g.lineStyle(1, 0xffd700, 0.3); g.beginPath(); g.moveTo(BOX_WIDTH, 8); g.lineTo(BOX_WIDTH, TOP_BAR_HEIGHT - 8); g.strokePath(); g.beginPath(); g.moveTo(BOX_WIDTH * 2, 8); g.lineTo(BOX_WIDTH * 2, TOP_BAR_HEIGHT - 8); g.strokePath(); // Box labels const labelStyle = { fontSize: '13px', fontFamily: 'Georgia, serif', color: '#c8a87e', alpha: 0.8 }; this.add.text(PLAYER_BOX_X, 14, 'YOUR FUNDS', labelStyle).setOrigin(0.5, 0); this.add.text(LORD_BOX_X, 14, 'THE LORD', labelStyle).setOrigin(0.5, 0); this.add.text(SIN_BOX_X, 14, 'SIN', labelStyle).setOrigin(0.5, 0); // Fund value texts const valueStyle = { fontSize: '28px', fontFamily: 'Georgia, serif', color: '#ffd700', stroke: '#2a0a4e', strokeThickness: 3 }; this.playerText = this.add.text(PLAYER_BOX_X, 55, '$1000', valueStyle).setOrigin(0.5, 0.5); this.lordText = this.add.text(LORD_BOX_X, 55, '$0', valueStyle).setOrigin(0.5, 0.5); this.sinText = this.add.text(SIN_BOX_X, 55, '$0', { ...valueStyle, color: '#ff4444' }).setOrigin(0.5, 0.5); } _buildBottomBar() { const g = this.add.graphics(); g.fillStyle(0x12082a, 1); g.fillRect(0, BOTTOM_BAR_Y, 1600, BOTTOM_BAR_HEIGHT); g.lineStyle(2, 0xffd700, 0.8); g.strokeRect(0, BOTTOM_BAR_Y, 1600, BOTTOM_BAR_HEIGHT); this.messageText = this.add.text(700, BOTTOM_BAR_Y + BOTTOM_BAR_HEIGHT / 2, 'Press SPIN or SPACE to begin', { fontSize: '22px', fontFamily: 'Georgia, serif', color: '#e8d8b0', align: 'center', wordWrap: { width: 1100 } }).setOrigin(0.5, 0.5); // Secondary redemption message (hidden by default) this.redeemText = this.add.text(700, BOTTOM_BAR_Y + BOTTOM_BAR_HEIGHT / 2 + 30, '', { fontSize: '16px', fontFamily: 'Georgia, serif', color: '#ff9944', align: 'center' }).setOrigin(0.5, 0.5).setAlpha(0); } _buildSpinButton() { const btnX = 1420; const btnY = BOTTOM_BAR_Y + BOTTOM_BAR_HEIGHT / 2; const btnW = 140; const btnH = 60; this.spinBtnGfx = this.add.graphics(); this._drawSpinBtn(false); this.spinBtnHitArea = this.add.zone(btnX, btnY, btnW, btnH) .setInteractive({ useHandCursor: true }); this.spinBtnLabel = this.add.text(btnX, btnY, 'SPIN', { fontSize: '26px', fontFamily: 'Georgia, serif', color: '#1a0a2e', fontStyle: 'bold' }).setOrigin(0.5, 0.5); this.spinBtnHitArea.on('pointerdown', () => { this.game.events.emit('spin'); }); this.spinBtnHitArea.on('pointerover', () => this._drawSpinBtn(true)); this.spinBtnHitArea.on('pointerout', () => this._drawSpinBtn(false)); // Store button center for layout reference this._btnX = btnX; this._btnY = btnY; this._btnW = btnW; this._btnH = btnH; } _drawSpinBtn(hover) { const btnX = 1420; const btnY = BOTTOM_BAR_Y + BOTTOM_BAR_HEIGHT / 2; const btnW = 140; const btnH = 60; this.spinBtnGfx.clear(); this.spinBtnGfx.fillStyle(hover ? 0xffe066 : 0xffd700, 1); this.spinBtnGfx.fillRoundedRect(btnX - btnW / 2, btnY - btnH / 2, btnW, btnH, 12); this.spinBtnGfx.lineStyle(3, hover ? 0xffa500 : 0xc8a000, 1); this.spinBtnGfx.strokeRoundedRect(btnX - btnW / 2, btnY - btnH / 2, btnW, btnH, 12); } _bindEvents() { this.game.events.on('win', ({ playerGain, lordGain, symbol }) => { this._updateFundDisplays(); this.messageText.setText( `✝ The Blessings of the Slots ✝\n+$${playerGain} to you | +$${lordGain} to The Lord (${symbol.label})` ); this.messageText.setColor('#ffd700'); this.redeemText.setAlpha(0); }, this); this.game.events.on('loss', () => { this._updateFundDisplays(); this.messageText.setText('Thou Hath Sinned.'); this.messageText.setColor('#ff6666'); this.redeemText.setText('Redeem Yourself!'); this.redeemText.setAlpha(1); // Pulse the redeem text this.tweens.add({ targets: this.redeemText, alpha: { from: 1, to: 0.3 }, duration: 700, yoyo: true, repeat: 4 }); }, this); this.game.events.on('spin-complete', () => { // Re-enable button visually (it was never disabled, just state-guarded) }, this); this.game.events.on('funds-updated', () => { this._updateFundDisplays(); }, this); this.game.events.on('insufficient-funds', () => { this.messageText.setText('Insufficient funds to spin! You have been consumed by Sin.'); this.messageText.setColor('#ff4444'); }, this); this.game.events.on('vial-winner', ({ winner }) => { const isLord = winner.toLowerCase().includes('lord'); this.messageText.setText( isLord ? '✝ The Lord Has Triumphed! ✝\nHis cup runneth over — glory be!' : '☠ Sin Has Prevailed! ☠\nYou have been consumed by darkness.' ); this.messageText.setColor(isLord ? '#ffd700' : '#ff4444'); this.redeemText.setAlpha(0); }, this); } _updateFundDisplays() { this.playerText.setText(`$${GameState.playerFunds}`); this.lordText.setText(`$${GameState.lordFunds}`); this.sinText.setText(`$${GameState.sinTotal}`); // Flash update on change [this.playerText, this.lordText, this.sinText].forEach(t => { this.tweens.add({ targets: t, scaleX: { from: 1.15, to: 1 }, scaleY: { from: 1.15, to: 1 }, duration: 200, ease: 'Bounce.easeOut' }); }); } // Called by GameScene to position animations toward the right box getPlayerBoxCenter() { return { x: PLAYER_BOX_X, y: BOX_CENTER_Y }; } getLordBoxCenter() { return { x: LORD_BOX_X, y: BOX_CENTER_Y }; } getSinBoxCenter() { return { x: SIN_BOX_X, y: BOX_CENTER_Y }; } }