Virtue-Slots/scenes/GameScene.js

143 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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=202690)
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=100790), 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');
});
}
);
}
}
}