Virtue-Slots/scenes/GameScene.js

161 lines
4.9 KiB
JavaScript

import { GameState } from '../state/GameState.js';
import { SlotMachine } from '../objects/SlotMachine.js';
import { WinAnimation } from '../objects/WinAnimation.js';
import { LossAnimation } from '../objects/LossAnimation.js';
export default class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' });
}
create() {
// Background gradient-ish
const bg = this.add.graphics();
bg.fillGradientStyle(0x1a0a2e, 0x1a0a2e, 0x2a0a4e, 0x2a0a4e, 1);
bg.fillRect(0, 0, 1600, 900);
// Decorative stars — floating, twinkling, pulsing
const starColors = [0xffffff, 0xffffff, 0xffffff, 0xffe8a0, 0xd0c8ff];
for (let i = 0; i < 70; i++) {
const x = Phaser.Math.Between(0, 1600);
const y = Phaser.Math.Between(120, 760);
const r = Phaser.Math.Between(1, 3);
const baseAlpha = Phaser.Math.FloatBetween(0.2, 0.75);
const color = starColors[Math.floor(Math.random() * starColors.length)];
const starGfx = this.add.graphics();
starGfx.fillStyle(color, 1);
starGfx.fillCircle(0, 0, r);
starGfx.setPosition(x, y);
starGfx.setAlpha(baseAlpha);
// Gentle drift — each star wanders a small random distance
this.tweens.add({
targets: starGfx,
x: x + Phaser.Math.Between(-18, 18),
y: y + Phaser.Math.Between(-12, 12),
duration: Phaser.Math.Between(3500, 8000),
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
delay: Phaser.Math.Between(0, 5000),
});
// Twinkle — alpha fades in and out independently
this.tweens.add({
targets: starGfx,
alpha: { from: baseAlpha * 0.15, to: baseAlpha },
duration: Phaser.Math.Between(600, 2800),
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
delay: Phaser.Math.Between(0, 3000),
});
// Scale pulse — grows and shrinks on its own rhythm
this.tweens.add({
targets: starGfx,
scale: Phaser.Math.FloatBetween(1.4, 3.2),
duration: Phaser.Math.Between(1200, 4500),
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
delay: Phaser.Math.Between(0, 4000),
});
}
// Title above the machine
this.add.text(800, 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.5, 0.5);
this.add.text(800, 195, '✝ May Fortune Favor the Faithful ✝', {
fontSize: '18px',
fontFamily: 'Georgia, serif',
color: '#c8a87e',
alpha: 0.8
}).setOrigin(0.5, 0.5);
// Slot machine at center of play area
this.slotMachine = new SlotMachine(this, 800, 490);
this.winAnim = new WinAnimation();
this.lossAnim = new LossAnimation();
// 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;
GameState.playerFunds += playerGain;
GameState.lordFunds += lordGain;
this.game.events.emit('win', { playerGain, lordGain, symbol: symbols[0] });
this.game.events.emit('funds-updated');
// 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.spinning = false;
this.game.events.emit('spin-complete');
}
);
} else {
GameState.sinTotal += GameState.spinCost;
this.game.events.emit('loss', { sinAdded: GameState.spinCost });
this.game.events.emit('funds-updated');
const uiScene = this.scene.get('UIScene');
const sinBox = uiScene ? uiScene.getSinBoxCenter() : { x: 1333, y: 60 };
this.lossAnim.play(
this,
this.slotMachine.getCenterX(),
this.slotMachine.getCenterY(),
sinBox,
() => {
GameState.spinning = false;
this.game.events.emit('spin-complete');
}
);
}
}
}