import { MatchBanner } from './MatchBanner.js'; export class WinAnimation { // playerBoxCenter, lordBoxCenter: { x, y } screen positions of fund boxes play(scene, originX, originY, playerBoxCenter, lordBoxCenter, symbol, onComplete) { new MatchBanner().play(scene, symbol.label, () => { // Flash the screen gold scene.cameras.main.flash(1200, 255, 215, 0, true); const totalCoins = 20; const playerCoins = Math.round(totalCoins * 0.6); const lordCoins = totalCoins - playerCoins; let finished = 0; // --- Split labels --- const spawnSplitLabel = (lx, topLine, pctLine, borderColor, textColor) => { const ly = 158; const PW = 240, PH = 86, PR = 10; const ctr = scene.add.container(lx, ly).setScale(0).setAlpha(0).setDepth(5); const bg = scene.add.graphics(); // Panel fill bg.fillStyle(0x0d0520, 0.96); bg.fillRoundedRect(-PW / 2, -PH / 2, PW, PH, PR); // Inner gold border bg.lineStyle(3, borderColor, 1); bg.strokeRoundedRect(-PW / 2, -PH / 2, PW, PH, PR); // Outer glow bg.lineStyle(12, borderColor, 0.2); bg.strokeRoundedRect(-PW / 2 - 6, -PH / 2 - 6, PW + 12, PH + 12, PR + 6); // Arrow tip pointing up toward the box above bg.fillStyle(borderColor, 1); bg.fillTriangle(-11, -PH / 2 + 2, 11, -PH / 2 + 2, 0, -PH / 2 - 15); const t1 = scene.add.text(0, -20, topLine, { fontSize: '13px', fontFamily: 'Georgia, serif', color: '#a89878', letterSpacing: 2, }).setOrigin(0.5, 0.5); const t2 = scene.add.text(0, 18, pctLine, { fontSize: '36px', fontFamily: 'Georgia, serif', fontStyle: 'bold', color: textColor, stroke: '#05020e', strokeThickness: 5, shadow: { offsetX: 0, offsetY: 0, color: textColor, blur: 16, fill: true }, }).setOrigin(0.5, 0.5); ctr.add([bg, t1, t2]); // Punch in scene.tweens.add({ targets: ctr, scale: 1, alpha: 1, duration: 380, delay: 120, ease: 'Back.easeOut', easeParams: [3.5], onComplete: () => { // Vigorous shake scene.tweens.add({ targets: ctr, x: { from: lx - 11, to: lx + 11 }, duration: 55, yoyo: true, repeat: 8, ease: 'Sine.easeInOut', onComplete: () => { // Pulse the percentage number scene.tweens.add({ targets: t2, scale: 1.3, duration: 120, yoyo: true, repeat: 3, ease: 'Sine.easeInOut', }); // Gentle breathe on the whole panel scene.tweens.add({ targets: ctr, scale: 1.05, duration: 500, yoyo: true, repeat: -1, ease: 'Sine.easeInOut', }); }, }); }, }); return { ctr, stopBreath: () => scene.tweens.killTweensOf(ctr) }; }; const { ctr: playerLabel, stopBreath: stopPlayer } = spawnSplitLabel( playerBoxCenter.x, 'YOUR WINNINGS', '60%', 0x55cc77, '#55cc77' ); const { ctr: lordLabel, stopBreath: stopLord } = spawnSplitLabel( lordBoxCenter.x, "THE LORD'S TITHE", '40%', 0xaa88ff, '#aa88ff' ); const spawnCoin = (targetX, targetY) => { const radius = 26; const gfx = scene.add.graphics(); // Main coin body gfx.fillStyle(0xffd700, 1); gfx.fillCircle(0, 0, radius); // Outer ring gfx.lineStyle(3, 0xffa500, 1); gfx.strokeCircle(0, 0, radius); // Inner highlight gfx.fillStyle(0xffe980, 0.6); gfx.fillCircle(-6, -6, radius * 0.38); const coinLabel = scene.add.text(0, 1, '$', { fontSize: '22px', fontFamily: 'Georgia, serif', fontStyle: 'bold', color: '#5a3000' }).setOrigin(0.5, 0.5); const startX = originX + Phaser.Math.Between(-70, 70); const startY = originY + Phaser.Math.Between(-30, 30); const container = scene.add.container(startX, startY, [gfx, coinLabel]); container.setScale(0.1); const delay = Phaser.Math.Between(0, 700); // Arc peak: shoot upward between origin and target, then fall to box const peakX = startX + (targetX - startX) * 0.35 + Phaser.Math.Between(-100, 100); const peakY = Math.min(startY, targetY) - Phaser.Math.Between(180, 340); const spinDir = Phaser.Math.Between(0, 1) ? 1 : -1; // Phase 1: pop in at origin scene.tweens.add({ targets: container, scale: 1.5, duration: 220, delay, ease: 'Back.easeOut', onComplete: () => { // Phase 2: arc up to peak scene.tweens.add({ targets: container, x: peakX, y: peakY, angle: spinDir * Phaser.Math.Between(120, 200), duration: 480, ease: 'Cubic.easeOut', onComplete: () => { // Phase 3: fall to target box, shrink and fade at arrival scene.tweens.add({ targets: container, x: targetX, y: targetY, scale: 0.4, angle: `+=${spinDir * Phaser.Math.Between(200, 400)}`, alpha: { from: 1, to: 0 }, duration: 900, ease: 'Cubic.easeIn', onComplete: () => { container.destroy(); finished++; if (finished === totalCoins) { stopPlayer(); stopLord(); scene.tweens.add({ targets: [playerLabel, lordLabel], alpha: 0, scale: 0.7, duration: 380, ease: 'Cubic.easeIn', onComplete: () => { playerLabel.destroy(); lordLabel.destroy(); if (onComplete) onComplete(); } }); } } }); } }); } }); }; // Halo glow ring expanding from center const halo = scene.add.graphics(); halo.lineStyle(6, 0xffd700, 0.8); halo.strokeCircle(0, 0, 10); halo.setPosition(originX, originY); scene.tweens.add({ targets: halo, scaleX: 8, scaleY: 8, alpha: 0, duration: 1800, ease: 'Cubic.easeOut', onComplete: () => halo.destroy() }); // Spawn coins to player box (60%) for (let i = 0; i < playerCoins; i++) { spawnCoin(playerBoxCenter.x, playerBoxCenter.y); } // Spawn coins to lord box (40%) for (let i = 0; i < lordCoins; i++) { spawnCoin(lordBoxCenter.x, lordBoxCenter.y); } }); } }