From 55c45dab365ef7502f6d29250611700a1fcae242 Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Sat, 28 Feb 2026 16:25:50 -0700 Subject: [PATCH] Updates to messaging --- scenes/UIScene.js | 309 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 285 insertions(+), 24 deletions(-) diff --git a/scenes/UIScene.js b/scenes/UIScene.js index c2d3c7a..7990506 100644 --- a/scenes/UIScene.js +++ b/scenes/UIScene.js @@ -11,6 +11,149 @@ 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; +// Resting positions for the two bottom-bar text objects +const MSG_X = 700; +const MSG_Y = BOTTOM_BAR_Y + BOTTOM_BAR_HEIGHT / 2; // 845 +const SUB_Y = BOTTOM_BAR_Y + BOTTOM_BAR_HEIGHT / 2 + 30; // 875 + +const pick = arr => arr[Phaser.Math.Between(0, arr.length - 1)]; + +// ── Message pools ───────────────────────────────────────────────────────────── + +const LOSS_MESSAGES = [ + 'Thou Hath Sinned.', + 'The Darkness Consumes Thee.', + 'Sin Claims Its Tithe.', + 'The Devil Takes His Due.', + 'Wretched Soul!', + 'Thy Coin Belongs to Evil.', + "Hell's Coffers Grow Richer.", + 'Condemned by Fortune.', + 'Behold Thy Folly!', + 'The Serpent Strikes Again!', + 'Damnation Draws Near.', + 'Thy Faith Was Wanting.', + 'The Wicked Path Claims Thee.', + 'Evil Rejoices This Hour!', + 'Another Soul Slips Away.', + 'The Pit Calls Thy Name.', + 'Darkness Prevails.', + "Sin's Ledger Grows.", + 'The Fallen Laugh at Thee.', + 'Thy Virtue Wavers.', + 'The Shadow Feeds.', + "Perdition's Price Is Paid.", + 'The Infernal Reels Mock Thee.', + 'Evil Creeps Ever Closer.', + 'The Unholy Slots Claim Thee.', + 'Darkness Demands Its Toll.', + 'The Abyss Grows Richer.', + 'Thy Coins Serve the Beast.', + 'Sin Savors Thy Defeat.', + 'The Hellfire Burns Brighter.', +]; + +const LOSS_SUBS = [ + 'Redeem Yourself!', + 'Pray Harder!', + 'Repent and Spin Again.', + 'Thy Soul Hangs in the Balance.', + 'Only Grace Can Save Thee Now.', + 'Kneel Before the Righteous Reels.', + 'The Lord Awaits Thy Return.', + 'Seek Salvation in the Next Spin.', + 'Sin Grows Bold — Shall Ye Falter?', + 'Heaven Watches and Weeps.', + 'Rise, Faithful Servant!', + 'Cast Out the Darkness!', + 'Penance Must Be Paid.', + 'Confess and Spin Anew.', + 'Thy Redemption Awaits.', + 'Do Not Yield to Evil!', + "The Lord's Mercy Is Boundless.", + 'Turn from the Wicked Path!', + 'Fight Back with Faith!', + 'Let the Light Guide Thy Hand.', + 'A Holy Victory Is Within Reach.', + 'Fortify Thy Spirit!', + 'The Divine Is Patient with Thee.', + 'Evil Shall Not Have the Last Word.', + 'Courage, Faithful One!', + 'One More Spin for Glory.', + 'Grace Favors the Persistent.', + 'The Pious Press On.', + 'Thy Virtue Must Endure.', + 'Arise and Challenge the Darkness!', +]; + +const WIN_MESSAGES = [ + '✝ Blessed Are the Righteous! ✝', + 'The Lord Smiles Upon Thee!', + 'Holy Fortune Shines Bright!', + "Heaven's Reward Is Thine!", + 'Grace Has Found Thee!', + 'Divine Providence Strikes!', + 'The Faithful Are Rewarded!', + 'Thy Virtue Bears Fruit!', + "God's Glory Fills Thy Coffers!", + 'Righteousness Prevails!', + 'The Angels Rejoice!', + 'Sacred Fortune Blesses Thee!', + 'The Holy Reels Align!', + 'Light Conquers the Darkness!', + 'Heaven Opens Its Gates!', + "The Lord's Hand Guides Thee!", + 'Faith Moves Mountains and Reels!', + 'Hallelujah — A Holy Match!', + 'Thy Piety Is Rewarded!', + 'The Divine Plan Unfolds!', + 'Blessed Be This Spin!', + 'The Righteous Shall Inherit!', + 'Favor of the Almighty!', + 'A Miracle Upon the Reels!', + "Heaven's Treasury Opens!", + 'Sin Retreats in Shame!', + 'The Virtuous Triumph!', + 'Glory to the Highest!', + 'The Light Pierces the Darkness!', + "God's Grace Rewards Thee!", +]; + +const WIN_SUBS = [ + 'Press On, Faithful One!', + 'The Lord Provides — Spin Again!', + 'Grace Continues to Flow.', + 'Heaven Cheers Thy Victory!', + 'Righteousness Is Its Own Reward.', + 'The Holy Spirit Guides Thy Hand.', + 'May the Divine Light Shine On.', + 'Sin Cowers Before Thy Faith.', + 'The Righteous Walk in Fortune.', + 'Let Virtue Lead Every Spin.', + 'The Angels Record Thy Victory.', + 'Keep the Faith — Keep Spinning!', + 'Thy Pious Heart Is Noticed.', + 'The Lord Multiplies Thy Blessings.', + 'Walk Boldly in the Light.', + 'Evil Cannot Touch the Faithful.', + 'Another Spin for His Glory!', + 'The Righteous Path Pays Off.', + "Heaven's Ledger Grows in Thy Favor.", + 'Consecrated Luck Is Upon Thee.', + 'The Devout Are Never Forgotten.', + 'Thy Coin Returns Manifold.', + 'Spin Again — Heaven Is Watching.', + "The Lord's Grace Has No Limit.", + 'Persist and Multiply in Faith!', + 'Sin Is Losing Ground.', + 'The Holy Reels Await Once More.', + 'Blessed Is the Hand That Spins.', + 'Fortune Favors the Faithful.', + 'The Kingdom Grows with Each Spin.', +]; + +// ───────────────────────────────────────────────────────────────────────────── + export default class UIScene extends Phaser.Scene { constructor() { super({ key: 'UIScene' }); @@ -78,7 +221,7 @@ export default class UIScene extends Phaser.Scene { 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', { + this.messageText = this.add.text(MSG_X, MSG_Y, 'Press SPIN or SPACE to begin', { fontSize: '22px', fontFamily: 'Georgia, serif', color: '#e8d8b0', @@ -86,8 +229,8 @@ export default class UIScene extends Phaser.Scene { 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, '', { + // Secondary sub-message (hidden by default) + this.redeemText = this.add.text(MSG_X, SUB_Y, '', { fontSize: '16px', fontFamily: 'Georgia, serif', color: '#ff9944', @@ -121,7 +264,6 @@ export default class UIScene extends Phaser.Scene { this.spinBtnHitArea.on('pointerover', () => { if (!this._spinDisabled) this._drawSpinBtn(true); }); this.spinBtnHitArea.on('pointerout', () => { if (!this._spinDisabled) this._drawSpinBtn(false); }); - // Store button center for layout reference this._btnX = btnX; this._btnY = btnY; this._btnW = btnW; @@ -156,31 +298,14 @@ export default class UIScene extends Phaser.Scene { } _bindEvents() { - this.game.events.on('win', ({ playerGain, lordGain, symbol }) => { + this.game.events.on('win', () => { 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._showWinMessage(pick(WIN_MESSAGES), pick(WIN_SUBS)); }, 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._showLossMessage(pick(LOSS_MESSAGES), pick(LOSS_SUBS)); }, this); this.game.events.on('spinning-started', () => { @@ -196,6 +321,7 @@ export default class UIScene extends Phaser.Scene { }, this); this.game.events.on('insufficient-funds', () => { + this._resetMessageTexts(); this.messageText.setText('Insufficient funds to spin! You have been consumed by Sin.'); this.messageText.setColor('#ff4444'); }, this); @@ -203,6 +329,7 @@ export default class UIScene extends Phaser.Scene { this.game.events.on('vial-winner', ({ winner }) => { this._gameOver = true; this._setSpinDisabled(true); + this._resetMessageTexts(); const isLord = winner.toLowerCase().includes('lord'); this.messageText.setText( isLord @@ -214,6 +341,140 @@ export default class UIScene extends Phaser.Scene { }, this); } + // ── Animated message display ────────────────────────────────────────────── + + /** Restore both text objects to their neutral resting state. */ + _resetMessageTexts() { + this.tweens.killTweensOf(this.messageText); + this.tweens.killTweensOf(this.redeemText); + this.messageText.setPosition(MSG_X, MSG_Y).setAlpha(1).setScale(1); + this.redeemText.setPosition(MSG_X, SUB_Y).setAlpha(0).setScale(1); + } + + /** + * Infernal Slam — main text crashes in from the left, sub-text rises from hell. + */ + _showLossMessage(main, sub) { + this.tweens.killTweensOf(this.messageText); + this.tweens.killTweensOf(this.redeemText); + + // Dark red flash across the bar + const flash = this.add.rectangle(800, MSG_Y, 1600, BOTTOM_BAR_HEIGHT, 0x990000) + .setAlpha(0.5); + this.tweens.add({ + targets: flash, alpha: 0, duration: 350, + onComplete: () => flash.destroy(), + }); + + // Main text — slam in from the left with overshoot + this.messageText + .setText(main) + .setColor('#ff3333') + .setPosition(-320, MSG_Y) + .setAlpha(0) + .setScale(1.15); + + this.tweens.add({ + targets: this.messageText, + x: MSG_X, alpha: 1, scale: 1, + duration: 480, ease: 'Back.easeOut', easeParams: [4], + onComplete: () => { + // Sharp horizontal tremble on arrival + this.tweens.add({ + targets: this.messageText, + x: { from: MSG_X - 6, to: MSG_X + 6 }, + duration: 40, yoyo: true, repeat: 5, ease: 'Sine.easeInOut', + }); + }, + }); + + // Sub-text — rises up from below the canvas + this.redeemText + .setText(sub) + .setColor('#ff9944') + .setPosition(MSG_X, 920) + .setAlpha(0) + .setScale(1); + + this.tweens.add({ + targets: this.redeemText, + y: SUB_Y, alpha: 1, + duration: 420, delay: 380, ease: 'Cubic.easeOut', + onComplete: () => { + this.tweens.add({ + targets: this.redeemText, + alpha: { from: 1, to: 0.3 }, + duration: 850, yoyo: true, repeat: -1, + }); + }, + }); + } + + /** + * Divine Descent — main text drops from the heavens, sub-text blooms into being. + */ + _showWinMessage(main, sub) { + this.tweens.killTweensOf(this.messageText); + this.tweens.killTweensOf(this.redeemText); + + // Golden flash across the bar + const flash = this.add.rectangle(800, MSG_Y, 1600, BOTTOM_BAR_HEIGHT, 0xffd700) + .setAlpha(0.4); + this.tweens.add({ + targets: flash, alpha: 0, duration: 500, + onComplete: () => flash.destroy(), + }); + + // Floating ✦ sparkles scatter across the bar + for (let i = 0; i < 7; i++) { + const sp = this.add.text( + Phaser.Math.Between(100, 1300), MSG_Y + Phaser.Math.Between(-20, 20), + ['✦', '✝', '★', '✧'][Math.floor(Math.random() * 4)], + { fontSize: `${Phaser.Math.Between(12, 26)}px`, color: '#ffd700' } + ).setOrigin(0.5).setAlpha(0); + + this.tweens.add({ + targets: sp, + y: sp.y - Phaser.Math.Between(25, 55), + alpha: { from: 1, to: 0 }, + scale: 1.4, + delay: i * 55, + duration: 650, + onComplete: () => sp.destroy(), + }); + } + + // Main text — descends from just above the bar, scales down to normal + this.messageText + .setText(main) + .setColor('#ffd700') + .setPosition(MSG_X, BOTTOM_BAR_Y - 28) + .setAlpha(0) + .setScale(1.35); + + this.tweens.add({ + targets: this.messageText, + y: MSG_Y, alpha: 1, scale: 1, + duration: 460, ease: 'Back.easeOut', easeParams: [2.5], + }); + + // Sub-text — blooms up from a tiny point at its resting position + this.redeemText + .setText(sub) + .setColor('#c8a87e') + .setPosition(MSG_X, SUB_Y) + .setAlpha(0) + .setScale(0.15); + + this.tweens.add({ + targets: this.redeemText, + scale: 1, alpha: 1, + duration: 380, delay: 280, ease: 'Back.easeOut', easeParams: [3], + }); + } + + // ───────────────────────────────────────────────────────────────────────── + _updateFundDisplays() { this.playerText.setText(`$${GameState.playerFunds}`); this.lordText.setText(`$${GameState.lordFunds}`);