forks

Creation chat

ClarkZhang
make me a cool Roulette wheel with sound effect.
02-28 00:47

登录 后可以评论

Assistant
# Roulette Wheel Game with Sound Effects I'll create a visually appealing roulette wheel game with realistic physics and sound effects. The game will include a spinning wheel, betting interface, and win/loss tracking. (HTML code has been generated and updated; see above for the current version.) ## Features of this Roulette Wheel Game: 1. **Realistic Wheel Physics**: Smooth spinning animation with easing for a realistic feel 2. **Sound Effects**: - Spinning sound effect - Win/loss notifications - Chip placement sounds 3. **Betting System**: - Multiple bet types (red/black, even/odd, number ranges, etc.) - Different chip denominations (5, 10, 25, 50, 100) 4. **Visual Design**: - Dark theme with vibrant colors for the wheel - Responsive layout that works on mobile and desktop - Animated elements for better feedback 5. **Game Mechanics**: - Balance tracking - Win/loss calculation with appropriate payouts - Visual feedback for bets and wins 6. **User Experience**: - Clear instructions - Visual feedback for interactions - Responsive design for all screen sizes The game is ready to play! Simply place your bets, spin the wheel, and see if you win. The sound effects enhance the experience and make it more engaging.
▼ Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Roulette Wheel Game</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script>tailwind.config = { darkMode: 'class' }</script>
    <style>
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .wheel-container {
            transition: transform 4s cubic-bezier(0.2, 0.8, 0.3, 1);
        }
        
        .wheel-pointer {
            position: absolute;
            top: -20px;
            left: 50%;
            transform: translateX(-50%);
            width: 30px;
            height: 30px;
            background: #ef4444;
            clip-path: polygon(50% 100%, 0 0, 100% 0);
            z-index: 10;
        }
        
        .chip {
            transition: all 0.3s ease;
        }
        
        .bet-placed {
            transform: scale(1.2);
            box-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
        }
        
        .win-animation {
            animation: winPulse 1s infinite;
        }
        
        @keyframes winPulse {
            0% { box-shadow: 0 0 5px rgba(72, 187, 120, 0.5); }
            50% { box-shadow: 0 0 20px rgba(72, 187, 120, 0.9); }
            100% { box-shadow: 0 0 5px rgba(72, 187, 120, 0.5); }
        }
    </style>
</head>
<body class="min-h-screen bg-gradient-to-br from-slate-900 to-slate-800 text-slate-100 flex flex-col items-center justify-center p-4">
    <!-- Theme toggle button -->
    <button id="theme-toggle-btn" class="fixed top-4 right-4 z-10 p-2 rounded-md hover:bg-gray-200 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors flex items-center justify-center" aria-label="Toggle theme" onclick="toggleTheme()">
        <svg id="icon-moon" class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998z"/></svg>
        <svg id="icon-sun" class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24" aria-hidden="true" style="display:none"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"></path></svg>
    </button>
    
    <script>
        function toggleTheme(){ 
            var el=document.documentElement; 
            var isDark=!el.classList.contains('dark'); 
            el.classList.toggle('dark',isDark); 
            localStorage.setItem('theme',isDark?'dark':'light'); 
            applyTheme(isDark); 
        }
        function applyTheme(isDark){ 
            document.getElementById('icon-moon').style.display=isDark?'none':'block'; 
            document.getElementById('icon-sun').style.display=isDark?'block':'none'; 
        }
        document.addEventListener('DOMContentLoaded',function(){ 
            var saved=localStorage.getItem('theme'); 
            var isDark=saved==='dark'||(!saved&&window.matchMedia('(prefers-color-scheme: dark)').matches); 
            document.documentElement.classList.toggle('dark',isDark); 
            applyTheme(isDark); 
        });
    </script>
    
    <div class="max-w-4xl w-full text-center">
        <h1 class="text-4xl md:text-5xl font-bold mb-2 text-amber-400">Roulette Wheel</h1>
        <p class="text-lg mb-8 text-slate-300">Place your bets and spin the wheel!</p>
        
        <div class="bg-slate-800/50 backdrop-blur-sm rounded-2xl p-6 mb-8 border border-slate-700 shadow-xl">
            <div class="flex flex-col md:flex-row items-center justify-between gap-6 mb-8">
                <div class="bg-slate-900 rounded-xl p-4 flex-1">
                    <h2 class="text-xl font-semibold mb-2 text-amber-300">Your Balance</h2>
                    <div class="text-3xl font-bold text-green-400">$<span id="balance">1000</span></div>
                </div>
                
                <div class="bg-slate-900 rounded-xl p-4 flex-1">
                    <h2 class="text-xl font-semibold mb-2 text-amber-300">Last Result</h2>
                    <div id="last-result" class="text-3xl font-bold">-</div>
                </div>
            </div>
            
            <div class="relative mb-10">
                <div class="wheel-pointer"></div>
                <div id="wheel" class="wheel-container relative w-64 h-64 md:w-80 md:h-80 mx-auto rounded-full overflow-hidden border-8 border-amber-600 shadow-2xl">
                    <canvas id="wheel-canvas" width="320" height="320" class="w-full h-full"></canvas>
                </div>
            </div>
            
            <div class="flex justify-center mb-8">
                <button id="spin-btn" class="px-8 py-4 bg-gradient-to-r from-amber-500 to-amber-600 hover:from-amber-600 hover:to-amber-700 text-white font-bold rounded-full shadow-lg transform transition hover:scale-105 focus:outline-none focus:ring-4 focus:ring-amber-500/50 text-xl">
                    SPIN THE WHEEL
                </button>
            </div>
        </div>
        
        <div class="bg-slate-800/50 backdrop-blur-sm rounded-2xl p-6 border border-slate-700 shadow-xl">
            <h2 class="text-2xl font-bold mb-4 text-amber-300">Place Your Bets</h2>
            
            <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
                <div class="bg-red-600 rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="red">
                    <div class="font-bold">Red</div>
                    <div class="text-sm">1:1</div>
                </div>
                <div class="bg-black rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="black">
                    <div class="font-bold text-white">Black</div>
                    <div class="text-sm text-white">1:1</div>
                </div>
                <div class="bg-green-600 rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="green">
                    <div class="font-bold">Green</div>
                    <div class="text-sm">14:1</div>
                </div>
                <div class="bg-blue-600 rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="even">
                    <div class="font-bold">Even</div>
                    <div class="text-sm">1:1</div>
                </div>
                <div class="bg-purple-600 rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="odd">
                    <div class="font-bold">Odd</div>
                    <div class="text-sm">1:1</div>
                </div>
                <div class="bg-yellow-500 rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="1-18">
                    <div class="font-bold">1-18</div>
                    <div class="text-sm">1:1</div>
                </div>
                <div class="bg-indigo-600 rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="19-36">
                    <div class="font-bold">19-36</div>
                    <div class="text-sm">1:1</div>
                </div>
                <div class="bg-pink-600 rounded-xl p-4 cursor-pointer chip hover:opacity-90" data-value="0">
                    <div class="font-bold">0</div>
                    <div class="text-sm">14:1</div>
                </div>
            </div>
            
            <div class="flex flex-wrap justify-center gap-4 mb-6">
                <button class="px-6 py-3 bg-slate-700 hover:bg-slate-600 rounded-lg font-bold chip" data-chip="5">5</button>
                <button class="px-6 py-3 bg-slate-700 hover:bg-slate-600 rounded-lg font-bold chip" data-chip="10">10</button>
                <button class="px-6 py-3 bg-slate-700 hover:bg-slate-600 rounded-lg font-bold chip" data-chip="25">25</button>
                <button class="px-6 py-3 bg-slate-700 hover:bg-slate-600 rounded-lg font-bold chip" data-chip="50">50</button>
                <button class="px-6 py-3 bg-slate-700 hover:bg-slate-600 rounded-lg font-bold chip" data-chip="100">100</button>
                <button class="px-6 py-3 bg-red-600 hover:bg-red-700 rounded-lg font-bold" id="clear-bets">Clear Bets</button>
            </div>
            
            <div class="flex justify-center gap-4">
                <div class="bg-slate-900 rounded-xl p-4">
                    <h3 class="font-semibold mb-2">Current Bet</h3>
                    <div class="text-2xl font-bold text-amber-400">$<span id="current-bet">0</span></div>
                </div>
                <div class="bg-slate-900 rounded-xl p-4">
                    <h3 class="font-semibold mb-2">Potential Win</h3>
                    <div class="text-2xl font-bold text-green-400">$<span id="potential-win">0</span></div>
                </div>
            </div>
        </div>
    </div>
    
    <!-- Audio elements for sound effects -->
    <audio id="spin-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-arcade-retro-changing-tab-206.mp3" preload="auto"></audio>
    <audio id="win-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-winning-chimes-2015.mp3" preload="auto"></audio>
    <audio id="lose-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-game-show-losing-the-bonus-497.mp3" preload="auto"></audio>
    <audio id="chip-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-coins-handling-193.mp3" preload="auto"></audio>
    
    <script>
        // Game state
        const gameState = {
            balance: 1000,
            currentBet: 0,
            selectedChip: 5,
            bets: {},
            spinning: false,
            wheelSegments: [
                { number: 0, color: 'green' },
                { number: 32, color: 'red' },
                { number: 15, color: 'black' },
                { number: 19, color: 'red' },
                { number: 4, color: 'black' },
                { number: 21, color: 'red' },
                { number: 2, color: 'black' },
                { number: 25, color: 'red' },
                { number: 17, color: 'black' },
                { number: 34, color: 'red' },
                { number: 6, color: 'black' },
                { number: 27, color: 'red' },
                { number: 13, color: 'black' },
                { number: 36, color: 'red' },
                { number: 11, color: 'black' },
                { number: 30, color: 'red' },
                { number: 8, color: 'black' },
                { number: 23, color: 'red' },
                { number: 10, color: 'black' },
                { number: 5, color: 'red' },
                { number: 24, color: 'black' },
                { number: 16, color: 'red' },
                { number: 33, color: 'black' },
                { number: 1, color: 'red' },
                { number: 20, color: 'black' },
                { number: 14, color: 'red' },
                { number: 31, color: 'black' },
                { number: 9, color: 'red' },
                { number: 22, color: 'black' },
                { number: 18, color: 'red' },
                { number: 29, color: 'black' },
                { number: 7, color: 'red' },
                { number: 28, color: 'black' },
                { number: 12, color: 'red' },
                { number: 35, color: 'black' },
                { number: 3, color: 'red' },
                { number: 26, color: 'black' }
            ]
        };
        
        // DOM Elements
        const balanceEl = document.getElementById('balance');
        const currentBetEl = document.getElementById('current-bet');
        const potentialWinEl = document.getElementById('potential-win');
        const lastResultEl = document.getElementById('last-result');
        const spinBtn = document.getElementById('spin-btn');
        const clearBetsBtn = document.getElementById('clear-bets');
        const chipButtons = document.querySelectorAll('.chip[data-chip]');
        const betButtons = document.querySelectorAll('.chip[data-value]');
        const wheelCanvas = document.getElementById('wheel-canvas');
        const wheelCtx = wheelCanvas.getContext('2d');
        
        // Audio elements
        const spinSound = document.getElementById('spin-sound');
        const winSound = document.getElementById('win-sound');
        const loseSound = document.getElementById('lose-sound');
        const chipSound = document.getElementById('chip-sound');
        
        // Initialize the wheel
        function drawWheel(rotation = 0) {
            const centerX = wheelCanvas.width / 2;
            const centerY = wheelCanvas.height / 2;
            const radius = Math.min(centerX, centerY) - 10;
            
            // Clear canvas
            wheelCtx.clearRect(0, 0, wheelCanvas.width, wheelCanvas.height);
            
            // Draw segments
            const segmentAngle = (2 * Math.PI) / gameState.wheelSegments.length;
            
            for (let i = 0; i < gameState.wheelSegments.length; i++) {
                const startAngle = i * segmentAngle + rotation;
                const endAngle = (i + 1) * segmentAngle + rotation;
                
                // Draw segment
                wheelCtx.beginPath();
                wheelCtx.moveTo(centerX, centerY);
                wheelCtx.arc(centerX, centerY, radius, startAngle, endAngle);
                wheelCtx.closePath();
                
                // Fill with appropriate color
                const color = gameState.wheelSegments[i].color;
                if (color === 'red') {
                    wheelCtx.fillStyle = '#dc2626';
                } else if (color === 'black') {
                    wheelCtx.fillStyle = '#1f2937';
                } else {
                    wheelCtx.fillStyle = '#16a34a';
                }
                wheelCtx.fill();
                
                // Draw border
                wheelCtx.strokeStyle = '#f3f4f6';
                wheelCtx.lineWidth = 1;
                wheelCtx.stroke();
                
                // Draw number
                const textAngle = startAngle + segmentAngle / 2;
                const textRadius = radius * 0.7;
                const textX = centerX + Math.cos(textAngle) * textRadius;
                const textY = centerY + Math.sin(textAngle) * textRadius;
                
                wheelCtx.fillStyle = '#f3f4f6';
                wheelCtx.font = 'bold 14px Arial';
                wheelCtx.textAlign = 'center';
                wheelCtx.textBaseline = 'middle';
                wheelCtx.fillText(gameState.wheelSegments[i].number.toString(), textX, textY);
            }
            
            // Draw center circle
            wheelCtx.beginPath();
            wheelCtx.arc(centerX, centerY, radius * 0.1, 0, 2 * Math.PI);
            wheelCtx.fillStyle = '#9ca3af';
            wheelCtx.fill();
            wheelCtx.strokeStyle = '#f3f4f6';
            wheelCtx.lineWidth = 2;
            wheelCtx.stroke();
        }
        
        // Initialize the game
        function initGame() {
            drawWheel();
            updateUI();
            
            // Set up event listeners
            spinBtn.addEventListener('click', spinWheel);
            clearBetsBtn.addEventListener('click', clearBets);
            
            chipButtons.forEach(button => {
                button.addEventListener('click', () => {
                    gameState.selectedChip = parseInt(button.dataset.chip);
                    chipSound.currentTime = 0;
                    chipSound.play().catch(e => console.log("Audio play prevented by browser:", e));
                    updateChipSelection();
                });
            });
            
            betButtons.forEach(button => {
                button.addEventListener('click', () => {
                    if (gameState.spinning) return;
                    
                    const betType = button.dataset.value;
                    placeBet(betType);
                });
            });
            
            updateChipSelection();
        }
        
        // Update chip selection UI
        function updateChipSelection() {
            chipButtons.forEach(button => {
                const chipValue = parseInt(button.dataset.chip);
                if (chipValue === gameState.selectedChip) {
                    button.classList.add('ring-4', 'ring-amber-400');
                } else {
                    button.classList.remove('ring-4', 'ring-amber-400');
                }
            });
        }
        
        // Place a bet
        function placeBet(betType) {
            if (gameState.balance < gameState.selectedChip) {
                alert('Not enough balance!');
                return;
            }
            
            // Add to existing bet or create new
            if (gameState.bets[betType]) {
                gameState.bets[betType] += gameState.selectedChip;
            } else {
                gameState.bets[betType] = gameState.selectedChip;
            }
            
            gameState.balance -= gameState.selectedChip;
            gameState.currentBet += gameState.selectedChip;
            
            // Visual feedback
            const betButton = document.querySelector(`.chip[data-value="${betType}"]`);
            betButton.classList.add('bet-placed');
            setTimeout(() => {
                betButton.classList.remove('bet-placed');
            }, 300);
            
            chipSound.currentTime = 0;
            chipSound.play().catch(e => console.log("Audio play prevented by browser:", e));
            updateUI();
        }
        
        // Clear all bets
        function clearBets() {
            if (gameState.spinning) return;
            
            // Return bet amount to balance
            gameState.balance += gameState.currentBet;
            
            // Reset bets
            gameState.bets = {};
            gameState.currentBet = 0;
            
            updateUI();
        }
        
        // Spin the wheel
        function spinWheel() {
            if (gameState.spinning) return;
            if (gameState.currentBet <= 0) {
                alert('Place a bet first!');
                return;
            }
            
            gameState.spinning = true;
            spinBtn.disabled = true;
            spinBtn.textContent = 'SPINNING...';
            
            // Play spin sound
            spinSound.currentTime = 0;
            spinSound.play().catch(e => console.log("Audio play prevented by browser:", e));
            
            // Calculate random result
            const spinDegrees = 1800 + Math.floor(Math.random() * 360);
            const segmentAngle = 360 / gameState.wheelSegments.length;
            const winningIndex = Math.floor((spinDegrees % 360) / segmentAngle);
            const winningSegment = gameState.wheelSegments[winningIndex];
            
            // Animate wheel
            const wheelEl = document.getElementById('wheel');
            wheelEl.style.transform = `rotate(${spinDegrees}deg)`;
            
            // Draw spinning wheel animation
            let rotation = 0;
            const spinAnimation = setInterval(() => {
                rotation += 10;
                drawWheel(rotation * Math.PI / 180);
            }, 30);
            
            // Stop animation after delay
            setTimeout(() => {
                clearInterval(spinAnimation);
                drawWheel(spinDegrees * Math.PI / 180);
                
                // Determine win/loss
                const result = checkWin(winningSegment);
                lastResultEl.textContent = `${winningSegment.number} ${winningSegment.color}`;
                lastResultEl.className = `text-3xl font-bold ${winningSegment.color === 'red' ? 'text-red-500' : winningSegment.color === 'black' ? 'text-gray-800' : 'text-green-500'}`;
                
                if (result.win) {
                    gameState.balance += result.payout;
                    lastResultEl.classList.add('win-animation');
                    winSound.currentTime = 0;
                    winSound.play().catch(e => console.log("Audio play prevented by browser:", e));
                } else {
                    loseSound.currentTime = 0;
                    loseSound.play().catch(e => console.log("Audio play prevented by browser:", e));
                }
                
                // Reset for next spin
                setTimeout(() => {
                    gameState.spinning = false;
                    spinBtn.disabled = false;
                    spinBtn.textContent = 'SPIN THE WHEEL';
                    gameState.bets = {};
                    gameState.currentBet = 0;
                    updateUI();
                }, 2000);
                
            }, 4000);
        }
        
        // Check if player won
        function checkWin(winningSegment) {
            let totalWin = 0;
            
            // Check all bets
            for (const betType in gameState.bets) {
                const betAmount = gameState.bets[betType];
                let win = false;
                let payoutMultiplier = 1;
                
                switch (betType) {
                    case 'red':
                        if (winningSegment.color === 'red') win = true;
                        break;
                    case 'black':
                        if (winningSegment.color === 'black') win = true;
                        break;
                    case 'green':
                        if (winningSegment.color === 'green') {
                            win = true;
                            payoutMultiplier = 14;
                        }
                        break;
                    case 'even':
                        if (winningSegment.number !== 0 && winningSegment.number % 2 === 0) win = true;
                        break;
                    case 'odd':
                        if (winningSegment.number !== 0 && winningSegment.number % 2 === 1) win = true;
                        break;
                    case '1-18':
                        if (winningSegment.number >= 1 && winningSegment.number <= 18) win = true;
                        break;
                    case '19-36':
                        if (winningSegment.number >= 19 && winningSegment.number <= 36) win = true;
                        break;
                    case '0':
                        if (winningSegment.number === 0) {
                            win = true;
                            payoutMultiplier = 14;
                        }
                        break;
                }
                
                if (win) {
                    totalWin += betAmount * payoutMultiplier;
                }
            }
            
            return {
                win: totalWin > 0,
                payout: totalWin
            };
        }
        
        // Update UI elements
        function updateUI() {
            balanceEl.textContent = gameState.balance;
            currentBetEl.textContent = gameState.currentBet;
            
            // Calculate potential win
            let potentialWin = 0;
            for (const betType in gameState.bets) {
                const betAmount = gameState.bets[betType];
                let multiplier = 1;
                
                if (betType === 'green' || betType === '0') {
                    multiplier = 14;
                }
                
                potentialWin += betAmount * multiplier;
            }
            
            potentialWinEl.textContent = potentialWin;
        }
        
        // Initialize the game when page loads
        window.addEventListener('load', initGame);
    </script>
</body>
</html>
02-28 00:51

登录 后可以评论

Comments

登录 后可以评论