Spaces:
Running
Running
| ```javascript | |
| class SlotMachine extends HTMLElement { | |
| constructor() { | |
| super(); | |
| this.balance = 1000; | |
| this.bet = 10; | |
| this.isSpinning = false; | |
| this.symbols = ['π', 'π', 'π', 'π', 'β', 'π', '7οΈβ£']; | |
| this.symbolValues = { | |
| 'π': 2, | |
| 'π': 3, | |
| 'π': 4, | |
| 'π': 5, | |
| 'β': 10, | |
| 'π': 20, | |
| '7οΈβ£': 50 | |
| }; | |
| } | |
| connectedCallback() { | |
| this.attachShadow({ mode: 'open' }); | |
| this.render(); | |
| this.setupEventListeners(); | |
| this.updateDisplay(); | |
| } | |
| render() { | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| display: block; | |
| max-width: 500px; | |
| margin: 0 auto; | |
| } | |
| .slot-container { | |
| background: linear-gradient(135deg, #1e293b, #334155); | |
| border: 2px solid #ef4444; | |
| border-radius: 1rem; | |
| padding: 2rem; | |
| box-shadow: 0 10px 30px rgba(239, 68, 68, 0.2); | |
| } | |
| .balance-display { | |
| text-align: center; | |
| margin-bottom: 1rem; | |
| font-size: 1.25rem; | |
| font-weight: bold; | |
| } | |
| .reels { | |
| display: flex; | |
| gap: 0.5rem; | |
| justify-content: center; | |
| margin: 2rem 0; | |
| background: #000; | |
| padding: 1.5rem; | |
| border-radius: 0.5rem; | |
| border: 3px solid #374151; | |
| } | |
| .reel { | |
| width: 80px; | |
| height: 80px; | |
| background: linear-gradient(to bottom, #fbbf24, #f59e0b); | |
| border: 2px solid #92400e; | |
| border-radius: 0.5rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 2.5rem; | |
| font-weight: bold; | |
| transition: transform 0.1s; | |
| } | |
| .reel.spinning { | |
| animation: spin 0.3s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: translateY(-20px); opacity: 0.5; } | |
| 100% { transform: translateY(20px); opacity: 1; } | |
| } | |
| .controls { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1rem; | |
| } | |
| .bet-controls { | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| gap: 1rem; | |
| } | |
| .bet-btn { | |
| width: 40px; | |
| height: 40px; | |
| border: none; | |
| border-radius: 50%; | |
| background: #ef4444; | |
| color: white; | |
| font-weight: bold; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| } | |
| .bet-btn:hover { | |
| background: #dc2626; | |
| transform: scale(1.1); | |
| } | |
| .bet-btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| .spin-btn { | |
| background: linear-gradient(45deg, #ef4444, #dc2626); | |
| color: white; | |
| border: none; | |
| padding: 1rem 3rem; | |
| border-radius: 0.5rem; | |
| font-size: 1.25rem; | |
| font-weight: bold; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| } | |
| .spin-btn:hover:not(:disabled) { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 25px rgba(239, 68, 68, 0.3); | |
| } | |
| .spin-btn:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| .message { | |
| text-align: center; | |
| margin-top: 1rem; | |
| font-size: 1.125rem; | |
| font-weight: 600; | |
| min-height: 1.5rem; | |
| } | |
| .win { | |
| color: #22c55e; | |
| animation: pulse 0.5s; | |
| } | |
| .lose { | |
| color: #ef4444; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); } | |
| 50% { transform: scale(1.1); } | |
| } | |
| .payout-table { | |
| margin-top: 1.5rem; | |
| background: rgba(55, 65, 81, 0.5); | |
| border-radius: 0.5rem; | |
| padding: 1rem; | |
| } | |
| .payout-table h4 { | |
| margin: 0 0 0.5rem 0; | |
| text-align: center; | |
| color: #ef4444; | |
| } | |
| .payout-row { | |
| display: flex; | |
| justify-content: space-between; | |
| font-size: 0.875rem; | |
| padding: 0.25rem 0; | |
| } | |
| </style> | |
| <div class="slot-container"> | |
| <div class="balance-display">π° Balance: $<span id="balance">1000</span></div> | |
| <div class="reels"> | |
| <div class="reel" id="reel1">π</div> | |
| <div class="reel" id="reel2">π</div> | |
| <div class="reel" id="reel3">π</div> | |
| </div> | |
| <div class="controls"> | |
| <div class="bet-controls"> | |
| <button class="bet-btn" id="decreaseBet">-</button> | |
| <span>Bet: $<span id="betAmount">10</span></span> | |
| <button class="bet-btn" id="increaseBet">+</button> | |
| </div> | |
| <button class="spin-btn" id="spinBtn">SPIN</button> | |
| </div> | |
| <div class="message" id="message"></div> | |
| <div class="payout-table"> | |
| <h4>Payouts (x bet)</h4> | |
| <div class="payout-row"><span>π 3x</span><span>2x</span></div> | |
| <div class="payout-row"><span>π 3x</span><span>3x</span></div> | |
| <div class="payout-row"><span>π 3x</span><span>4x</span></div> | |
| <div class="payout-row"><span>π 3x</span><span>5x</span></div> | |
| <div class="payout-row"><span>β 3x</span><span>10x</span></div> | |
| <div class="payout-row"><span>π 3x</span><span>20x</span></div> | |
| <div class="payout-row"><span>7οΈβ£ 3x</span><span>50x JACKPOT!</span></div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| setupEventListeners() { | |
| this.shadowRoot.getElementById('spinBtn').addEventListener('click', () => this.spin()); | |
| this.shadowRoot.getElementById('increaseBet').addEventListener('click', () => this.changeBet(5)); | |
| this.shadowRoot.getElementById('decreaseBet').addEventListener('click', () => this.changeBet(-5)); | |
| } | |
| changeBet(amount) { | |
| if (this.isSpinning) return; | |
| this.bet = Math.max(5, Math.min(100, this.bet + amount)); | |
| this.updateDisplay(); | |
| } | |
| async spin() { | |
| if (this.isSpinning || this.balance < this.bet) { | |
| if (this.balance < this.bet) { | |
| this.showMessage('β Insufficient balance!', 'lose'); | |
| } | |
| return; | |
| } | |
| this.isSpinning = true; | |
| this.balance -= this.bet; | |
| this.updateDisplay(); | |
| const reel1 = this.shadowRoot.getElementById('reel1'); | |
| const reel2 = this.shadowRoot.getElementById('reel2'); | |
| const reel3 = this.shadowRoot.getElementById('reel3'); | |
| const spinBtn = this.shadowRoot.getElementById('spinBtn'); | |
| spinBtn.textContent = 'SPINNING...'; | |
| spinBtn.disabled = true; | |
| reel1.classList.add('spinning'); | |
| reel2.classList.add('spinning'); | |
| reel3.classList.add('spinning'); | |
| // Simulate spinning | |
| const spinDuration = 2000; | |
| const spinInterval = 100; | |
| const startTime = Date.now(); | |
| const spinReels = setInterval(() => { | |
| reel1.textContent = this.symbols[Math.floor(Math.random() * this.symbols.length)]; | |
| reel2.textContent = this.symbols[Math.floor(Math.random() * this.symbols.length)]; | |
| reel3.textContent = this.symbols[Math.floor(Math.random() * this.symbols.length)]; | |
| if (Date.now() - startTime > spinDuration) { | |
| clearInterval(spinReels); | |
| this.stopSpin(); | |
| } | |
| }, spinInterval); | |
| } | |
| stopSpin() { | |
| const reel1 = this.shadowRoot.getElementById('reel1'); | |
| const reel2 = this.shadowRoot.getElementById('reel2'); | |
| const reel3 = this.shadowRoot.getElementById('reel3'); | |
| const spinBtn = this.shadowRoot.getElementById('spinBtn'); | |
| reel1.classList.remove('spinning'); | |
| reel2.classList.remove('spinning'); | |
| reel3.classList.remove('spinning'); | |
| // Final results | |
| const result1 = this.symbols[Math.floor(Math.random() * this.symbols.length)]; | |
| const result2 = this.symbols[Math.floor(Math.random() * this.symbols.length)]; | |
| const result3 = this.symbols[Math.floor(Math.random() * this.symbols.length)]; | |
| reel1.textContent = result1; | |
| reel2.textContent = result2; | |
| reel3.textContent = result3; | |
| this.calculateWinnings(result1, result2, result3); | |
| spinBtn.textContent = 'SPIN'; | |
| spinBtn.disabled = false; | |
| this.isSpinning = false; | |
| } | |
| calculateWinnings(r1, r2, r3) { | |
| if (r1 === r2 && r2 === r3) { | |
| const multiplier = this.symbolValues[r1]; | |
| const winnings = this.bet * multiplier; | |
| this.balance += winnings; | |
| this.showMessage(`π JACKPOT! You won $${winnings}!`, 'win'); | |
| // Generate redemption code for big wins | |
| if (winnings >= 100) { | |
| setTimeout(() => { | |
| alert(`π CONGRATULATIONS! You've earned a redemption code: WIN-${Math.random().toString(36).substr(2, 9).toUpperCase()}`); | |
| }, 1000); | |
| } | |
| } else if (r1 === r2 || r2 === r3 || r1 === r3) { | |
| const smallWin = this.bet * 0.5; | |
| this.balance += smallWin; | |
| this.showMessage(`π° Small win! $${smallWin}`, 'win'); | |
| } else { | |
| this.showMessage('π Try again!', 'lose'); | |
| } | |
| this.updateDisplay(); | |
| } | |
| showMessage(text, type) { | |
| const messageEl = this.shadowRoot.getElementById('message'); | |
| messageEl.textContent = text; | |
| messageEl.className = `message ${type}`; | |
| } | |
| updateDisplay() { | |
| this.shadowRoot.getElementById('balance').textContent = this.balance; | |
| this.shadowRoot.getElementById('betAmount').textContent = this.bet; |