Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>USA Block Breaker</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| #gameCanvas { | |
| background: linear-gradient(to bottom, #0a3161, #003366); | |
| border-radius: 10px; | |
| box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); | |
| } | |
| .flag-stripe { | |
| height: 20px; | |
| width: 100%; | |
| } | |
| .stripe-red { | |
| background-color: #B22234; | |
| } | |
| .stripe-white { | |
| background-color: white; | |
| } | |
| .stars { | |
| background-color: #0a3161; | |
| color: white; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| font-size: 14px; | |
| } | |
| .explosion { | |
| position: absolute; | |
| width: 40px; | |
| height: 40px; | |
| background: radial-gradient(circle, #ff0, #f80, #f00); | |
| border-radius: 50%; | |
| pointer-events: none; | |
| transform: scale(0); | |
| animation: explode 0.5s forwards; | |
| } | |
| @keyframes explode { | |
| 0% { transform: scale(0); opacity: 1; } | |
| 100% { transform: scale(3); opacity: 0; } | |
| } | |
| .firework { | |
| position: absolute; | |
| width: 4px; | |
| height: 4px; | |
| border-radius: 50%; | |
| box-shadow: 0 0 10px 2px; | |
| animation: firework 1s forwards; | |
| } | |
| @keyframes firework { | |
| 0% { transform: translate(0, 0); opacity: 1; } | |
| 100% { transform: translate(var(--tx), var(--ty)); opacity: 0; } | |
| } | |
| .confetti { | |
| position: absolute; | |
| width: 10px; | |
| height: 10px; | |
| opacity: 0; | |
| animation: confetti-fall 3s linear forwards; | |
| } | |
| @keyframes confetti-fall { | |
| 0% { transform: translateY(-100px) rotate(0deg); opacity: 1; } | |
| 100% { transform: translateY(1000px) rotate(360deg); opacity: 0; } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen flex flex-col items-center py-8"> | |
| <div class="w-full max-w-4xl mx-auto px-4"> | |
| <!-- USA Flag Header --> | |
| <div class="usa-flag mb-8 overflow-hidden rounded-lg shadow-lg"> | |
| <div class="flex"> | |
| <div class="w-2/5 stars h-40 flex flex-col justify-center"> | |
| <div class="text-center"> | |
| <div class="text-2xl font-bold mb-2">USA BLOCK BREAKER</div> | |
| <div class="text-sm">Destroy the blocks to reveal the flag!</div> | |
| </div> | |
| </div> | |
| <div class="w-3/5"> | |
| <div class="flag-stripe stripe-red"></div> | |
| <div class="flag-stripe stripe-white"></div> | |
| <div class="flag-stripe stripe-red"></div> | |
| <div class="flag-stripe stripe-white"></div> | |
| <div class="flag-stripe stripe-red"></div> | |
| <div class="flag-stripe stripe-white"></div> | |
| <div class="flag-stripe stripe-red"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Game Info --> | |
| <div class="flex justify-between items-center mb-6"> | |
| <div class="bg-white p-4 rounded-lg shadow-md flex items-center"> | |
| <i class="fas fa-star-sparkle text-yellow-400 text-xl mr-2"></i> | |
| <span class="font-bold">Score: <span id="score">0</span></span> | |
| </div> | |
| <div class="bg-white p-4 rounded-lg shadow-md flex items-center"> | |
| <i class="fas fa-heart text-red-500 text-xl mr-2"></i> | |
| <span class="font-bold">Lives: <span id="lives">3</span></span> | |
| </div> | |
| <div class="bg-white p-4 rounded-lg shadow-md flex items-center"> | |
| <i class="fas fa-layer-group text-blue-500 text-xl mr-2"></i> | |
| <span class="font-bold">Level: <span id="level">1</span></span> | |
| </div> | |
| </div> | |
| <!-- Game Canvas --> | |
| <div class="relative"> | |
| <canvas id="gameCanvas" width="800" height="500" class="w-full border-4 border-white"></canvas> | |
| <div id="gameOver" class="hidden absolute inset-0 bg-black bg-opacity-70 flex flex-col justify-center items-center text-white rounded-lg"> | |
| <h2 class="text-4xl font-bold mb-4">GAME OVER</h2> | |
| <p class="text-xl mb-6">Final Score: <span id="finalScore">0</span></p> | |
| <button id="restartBtn" class="bg-red-600 hover:bg-red-700 text-white font-bold py-3 px-6 rounded-full text-lg transition-all transform hover:scale-105"> | |
| <i class="fas fa-flag-usa mr-2"></i> Play Again | |
| </button> | |
| </div> | |
| <div id="levelComplete" class="hidden absolute inset-0 bg-black bg-opacity-70 flex flex-col justify-center items-center text-white rounded-lg"> | |
| <h2 class="text-4xl font-bold mb-4">LEVEL COMPLETE!</h2> | |
| <p class="text-xl mb-6">Score: <span id="levelScore">0</span></p> | |
| <button id="nextLevelBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-full text-lg transition-all transform hover:scale-105"> | |
| <i class="fas fa-arrow-right mr-2"></i> Next Level | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Controls --> | |
| <div class="mt-6 flex justify-center space-x-4"> | |
| <button id="pauseBtn" class="bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-2 px-4 rounded"> | |
| <i class="fas fa-pause mr-2"></i> Pause | |
| </button> | |
| <button id="soundBtn" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded"> | |
| <i class="fas fa-volume-up mr-2"></i> Sound On | |
| </button> | |
| </div> | |
| </div> | |
| <audio id="bounceSound" src="https://assets.mixkit.co/sfx/preview/mixkit-arcade-game-jump-coin-216.mp3" preload="auto"></audio> | |
| <audio id="breakSound" src="https://assets.mixkit.co/sfx/preview/mixkit-unlock-game-notification-253.mp3" preload="auto"></audio> | |
| <audio id="gameOverSound" src="https://assets.mixkit.co/sfx/preview/mixkit-retro-arcade-lose-2027.mp3" preload="auto"></audio> | |
| <audio id="levelCompleteSound" src="https://assets.mixkit.co/sfx/preview/mixkit-winning-chimes-2015.mp3" preload="auto"></audio> | |
| <audio id="backgroundMusic" loop src="https://assets.mixkit.co/music/preview/mixkit-patriotic-spirit-668.mp3" preload="auto"></audio> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Game elements | |
| const canvas = document.getElementById('gameCanvas'); | |
| const ctx = canvas.getContext('2d'); | |
| const scoreElement = document.getElementById('score'); | |
| const livesElement = document.getElementById('lives'); | |
| const levelElement = document.getElementById('level'); | |
| const gameOverElement = document.getElementById('gameOver'); | |
| const finalScoreElement = document.getElementById('finalScore'); | |
| const restartBtn = document.getElementById('restartBtn'); | |
| const levelCompleteElement = document.getElementById('levelComplete'); | |
| const levelScoreElement = document.getElementById('levelScore'); | |
| const nextLevelBtn = document.getElementById('nextLevelBtn'); | |
| const pauseBtn = document.getElementById('pauseBtn'); | |
| const soundBtn = document.getElementById('soundBtn'); | |
| // Audio elements | |
| const bounceSound = document.getElementById('bounceSound'); | |
| const breakSound = document.getElementById('breakSound'); | |
| const gameOverSound = document.getElementById('gameOverSound'); | |
| const levelCompleteSound = document.getElementById('levelCompleteSound'); | |
| const backgroundMusic = document.getElementById('backgroundMusic'); | |
| // Game variables | |
| let score = 0; | |
| let lives = 3; | |
| let level = 1; | |
| let isPaused = false; | |
| let soundOn = true; | |
| let gameRunning = false; | |
| // Paddle | |
| const paddleWidth = 100; | |
| const paddleHeight = 15; | |
| let paddleX = (canvas.width - paddleWidth) / 2; | |
| // Ball | |
| const ballRadius = 10; | |
| let ballX = canvas.width / 2; | |
| let ballY = canvas.height - 30; | |
| let ballSpeedX = 5; | |
| let ballSpeedY = -5; | |
| // Blocks | |
| const blockRowCount = 5; | |
| const blockColumnCount = 10; | |
| const blockWidth = 75; | |
| const blockHeight = 20; | |
| const blockPadding = 10; | |
| const blockOffsetTop = 60; | |
| const blockOffsetLeft = 30; | |
| let blocks = []; | |
| // Initialize blocks | |
| function initBlocks() { | |
| blocks = []; | |
| for (let c = 0; c < blockColumnCount; c++) { | |
| blocks[c] = []; | |
| for (let r = 0; r < blockRowCount; r++) { | |
| // Create blocks with different colors and point values | |
| let blockPoints = 0; | |
| let blockColor = ''; | |
| if (r === 0) { | |
| blockColor = '#B22234'; // Red | |
| blockPoints = 7; | |
| } else if (r === 1) { | |
| blockColor = '#FFFFFF'; // White | |
| blockPoints = 5; | |
| } else if (r === 2) { | |
| blockColor = '#B22234'; // Red | |
| blockPoints = 7; | |
| } else if (r === 3) { | |
| blockColor = '#FFFFFF'; // White | |
| blockPoints = 5; | |
| } else { | |
| blockColor = '#0a3161'; // Blue | |
| blockPoints = 10; | |
| } | |
| blocks[c][r] = { | |
| x: 0, | |
| y: 0, | |
| status: 1, | |
| color: blockColor, | |
| points: blockPoints * level // Increase points with level | |
| }; | |
| } | |
| } | |
| } | |
| // Draw paddle | |
| function drawPaddle() { | |
| ctx.beginPath(); | |
| ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight); | |
| ctx.fillStyle = '#0a3161'; | |
| ctx.fill(); | |
| ctx.strokeStyle = '#B22234'; | |
| ctx.lineWidth = 2; | |
| ctx.stroke(); | |
| ctx.closePath(); | |
| // Add stars to paddle | |
| const starCount = Math.floor(paddleWidth / 20); | |
| for (let i = 0; i < starCount; i++) { | |
| const starX = paddleX + 10 + (i * (paddleWidth / starCount)); | |
| const starY = canvas.height - paddleHeight / 2; | |
| ctx.beginPath(); | |
| ctx.moveTo(starX, starY - 5); | |
| for (let j = 0; j < 5; j++) { | |
| const angle = (Math.PI * 2 / 5) * j - Math.PI / 2; | |
| const x = starX + Math.cos(angle) * 5; | |
| const y = starY + Math.sin(angle) * 5; | |
| ctx.lineTo(x, y); | |
| const innerAngle = angle + Math.PI / 5; | |
| const innerX = starX + Math.cos(innerAngle) * 2; | |
| const innerY = starY + Math.sin(innerAngle) * 2; | |
| ctx.lineTo(innerX, innerY); | |
| } | |
| ctx.closePath(); | |
| ctx.fillStyle = '#FFFFFF'; | |
| ctx.fill(); | |
| } | |
| } | |
| // Draw ball | |
| function drawBall() { | |
| ctx.beginPath(); | |
| ctx.arc(ballX, ballY, ballRadius, 0, Math.PI * 2); | |
| ctx.fillStyle = '#FFFFFF'; | |
| ctx.fill(); | |
| ctx.strokeStyle = '#B22234'; | |
| ctx.lineWidth = 2; | |
| ctx.stroke(); | |
| ctx.closePath(); | |
| // Add star pattern to ball | |
| ctx.beginPath(); | |
| ctx.moveTo(ballX, ballY - 3); | |
| for (let j = 0; j < 5; j++) { | |
| const angle = (Math.PI * 2 / 5) * j - Math.PI / 2; | |
| const x = ballX + Math.cos(angle) * 3; | |
| const y = ballY + Math.sin(angle) * 3; | |
| ctx.lineTo(x, y); | |
| const innerAngle = angle + Math.PI / 5; | |
| const innerX = ballX + Math.cos(innerAngle) * 1; | |
| const innerY = ballY + Math.sin(innerAngle) * 1; | |
| ctx.lineTo(innerX, innerY); | |
| } | |
| ctx.closePath(); | |
| ctx.fillStyle = '#0a3161'; | |
| ctx.fill(); | |
| } | |
| // Draw blocks | |
| function drawBlocks() { | |
| for (let c = 0; c < blockColumnCount; c++) { | |
| for (let r = 0; r < blockRowCount; r++) { | |
| if (blocks[c][r].status === 1) { | |
| const blockX = c * (blockWidth + blockPadding) + blockOffsetLeft; | |
| const blockY = r * (blockHeight + blockPadding) + blockOffsetTop; | |
| blocks[c][r].x = blockX; | |
| blocks[c][r].y = blockY; | |
| ctx.beginPath(); | |
| ctx.rect(blockX, blockY, blockWidth, blockHeight); | |
| ctx.fillStyle = blocks[c][r].color; | |
| ctx.fill(); | |
| ctx.strokeStyle = '#000000'; | |
| ctx.lineWidth = 1; | |
| ctx.stroke(); | |
| ctx.closePath(); | |
| // Add block points text | |
| ctx.font = 'bold 12px Arial'; | |
| ctx.fillStyle = '#000000'; | |
| ctx.textAlign = 'center'; | |
| ctx.fillText(blocks[c][r].points, blockX + blockWidth / 2, blockY + blockHeight / 2 + 4); | |
| } | |
| } | |
| } | |
| } | |
| // Collision detection | |
| function collisionDetection() { | |
| for (let c = 0; c < blockColumnCount; c++) { | |
| for (let r = 0; r < blockRowCount; r++) { | |
| const block = blocks[c][r]; | |
| if (block.status === 1) { | |
| if ( | |
| ballX > block.x && | |
| ballX < block.x + blockWidth && | |
| ballY > block.y && | |
| ballY < block.y + blockHeight | |
| ) { | |
| ballSpeedY = -ballSpeedY; | |
| block.status = 0; | |
| score += block.points; | |
| scoreElement.textContent = score; | |
| // Play break sound | |
| if (soundOn) { | |
| breakSound.currentTime = 0; | |
| breakSound.play(); | |
| } | |
| // Create explosion effect | |
| createExplosion(block.x + blockWidth/2, block.y + blockHeight/2, block.color); | |
| // Check if all blocks are destroyed | |
| if (checkLevelComplete()) { | |
| levelComplete(); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // Check if level is complete | |
| function checkLevelComplete() { | |
| for (let c = 0; c < blockColumnCount; c++) { | |
| for (let r = 0; r < blockRowCount; r++) { | |
| if (blocks[c][r].status === 1) { | |
| return false; | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| // Level complete | |
| function levelComplete() { | |
| if (soundOn) { | |
| levelCompleteSound.currentTime = 0; | |
| levelCompleteSound.play(); | |
| } | |
| gameRunning = false; | |
| levelScoreElement.textContent = score; | |
| levelCompleteElement.classList.remove('hidden'); | |
| // Create fireworks | |
| createFireworks(); | |
| } | |
| // Next level | |
| function nextLevel() { | |
| level++; | |
| levelElement.textContent = level; | |
| levelCompleteElement.classList.add('hidden'); | |
| // Reset ball and paddle | |
| ballX = canvas.width / 2; | |
| ballY = canvas.height - 30; | |
| paddleX = (canvas.width - paddleWidth) / 2; | |
| // Increase ball speed slightly | |
| ballSpeedX *= 1.1; | |
| ballSpeedY *= 1.1; | |
| // Initialize new blocks | |
| initBlocks(); | |
| gameRunning = true; | |
| requestAnimationFrame(draw); | |
| } | |
| // Create explosion effect | |
| function createExplosion(x, y, color) { | |
| const explosion = document.createElement('div'); | |
| explosion.className = 'explosion'; | |
| explosion.style.left = `${x - 20}px`; | |
| explosion.style.top = `${y - 20}px`; | |
| explosion.style.backgroundColor = color; | |
| document.body.appendChild(explosion); | |
| setTimeout(() => { | |
| explosion.remove(); | |
| }, 500); | |
| } | |
| // Create fireworks for level complete | |
| function createFireworks() { | |
| for (let i = 0; i < 20; i++) { | |
| setTimeout(() => { | |
| const x = Math.random() * canvas.width; | |
| const y = Math.random() * canvas.height / 2; | |
| // Create central explosion | |
| const explosion = document.createElement('div'); | |
| explosion.className = 'explosion'; | |
| explosion.style.left = `${x - 20}px`; | |
| explosion.style.top = `${y - 20}px`; | |
| explosion.style.backgroundColor = i % 2 === 0 ? '#B22234' : '#FFFFFF'; | |
| document.body.appendChild(explosion); | |
| // Create particles | |
| for (let j = 0; j < 20; j++) { | |
| const angle = Math.random() * Math.PI * 2; | |
| const distance = 5 + Math.random() * 50; | |
| const tx = Math.cos(angle) * distance; | |
| const ty = Math.sin(angle) * distance; | |
| const particle = document.createElement('div'); | |
| particle.className = 'firework'; | |
| particle.style.left = `${x}px`; | |
| particle.style.top = `${y}px`; | |
| particle.style.setProperty('--tx', `${tx}px`); | |
| particle.style.setProperty('--ty', `${ty}px`); | |
| particle.style.color = i % 2 === 0 ? '#B22234' : '#FFFFFF'; | |
| document.body.appendChild(particle); | |
| setTimeout(() => { | |
| particle.remove(); | |
| }, 1000); | |
| } | |
| setTimeout(() => { | |
| explosion.remove(); | |
| }, 500); | |
| }, i * 200); | |
| } | |
| // Create confetti | |
| for (let i = 0; i < 100; i++) { | |
| const confetti = document.createElement('div'); | |
| confetti.className = 'confetti'; | |
| confetti.style.left = `${Math.random() * canvas.width}px`; | |
| confetti.style.backgroundColor = i % 3 === 0 ? '#B22234' : (i % 3 === 1 ? '#FFFFFF' : '#0a3161'); | |
| confetti.style.animationDelay = `${Math.random() * 2}s`; | |
| document.body.appendChild(confetti); | |
| setTimeout(() => { | |
| confetti.remove(); | |
| }, 3000); | |
| } | |
| } | |
| // Game over | |
| function gameOver() { | |
| if (soundOn) { | |
| gameOverSound.currentTime = 0; | |
| gameOverSound.play(); | |
| backgroundMusic.pause(); | |
| } | |
| gameRunning = false; | |
| finalScoreElement.textContent = score; | |
| gameOverElement.classList.remove('hidden'); | |
| } | |
| // Restart game | |
| function restartGame() { | |
| score = 0; | |
| lives = 3; | |
| level = 1; | |
| scoreElement.textContent = score; | |
| livesElement.textContent = lives; | |
| levelElement.textContent = level; | |
| // Reset ball and paddle | |
| ballX = canvas.width / 2; | |
| ballY = canvas.height - 30; | |
| paddleX = (canvas.width - paddleWidth) / 2; | |
| ballSpeedX = 5; | |
| ballSpeedY = -5; | |
| // Initialize blocks | |
| initBlocks(); | |
| gameOverElement.classList.add('hidden'); | |
| gameRunning = true; | |
| if (soundOn) { | |
| backgroundMusic.currentTime = 0; | |
| backgroundMusic.play(); | |
| } | |
| requestAnimationFrame(draw); | |
| } | |
| // Main draw function | |
| function draw() { | |
| if (!gameRunning || isPaused) return; | |
| // Clear canvas | |
| ctx.clearRect(0, 0, canvas.width, canvas.height); | |
| // Draw elements | |
| drawBlocks(); | |
| drawPaddle(); | |
| drawBall(); | |
| // Collision detection | |
| collisionDetection(); | |
| // Ball movement | |
| ballX += ballSpeedX; | |
| ballY += ballSpeedY; | |
| // Wall collision (left/right) | |
| if (ballX + ballSpeedX > canvas.width - ballRadius || ballX + ballSpeedX < ballRadius) { | |
| ballSpeedX = -ballSpeedX; | |
| if (soundOn) { | |
| bounceSound.currentTime = 0; | |
| bounceSound.play(); | |
| } | |
| } | |
| // Wall collision (top) | |
| if (ballY + ballSpeedY < ballRadius) { | |
| ballSpeedY = -ballSpeedY; | |
| if (soundOn) { | |
| bounceSound.currentTime = 0; | |
| bounceSound.play(); | |
| } | |
| } | |
| // Paddle collision | |
| if ( | |
| ballY + ballSpeedY > canvas.height - paddleHeight - ballRadius && | |
| ballX > paddleX && | |
| ballX < paddleX + paddleWidth | |
| ) { | |
| // Calculate bounce angle based on where ball hits paddle | |
| const hitPosition = (ballX - paddleX) / paddleWidth; | |
| const bounceAngle = hitPosition * Math.PI - Math.PI/2; | |
| // Adjust ball speed based on bounce angle | |
| const speed = Math.sqrt(ballSpeedX * ballSpeedX + ballSpeedY * ballSpeedY); | |
| ballSpeedX = speed * Math.cos(bounceAngle) * 1.1; | |
| ballSpeedY = -Math.abs(speed * Math.sin(bounceAngle)) * 1.1; | |
| if (soundOn) { | |
| bounceSound.currentTime = 0; | |
| bounceSound.play(); | |
| } | |
| } | |
| // Bottom wall collision (lose life) | |
| if (ballY + ballSpeedY > canvas.height - ballRadius) { | |
| lives--; | |
| livesElement.textContent = lives; | |
| if (lives <= 0) { | |
| gameOver(); | |
| } else { | |
| // Reset ball and paddle | |
| ballX = canvas.width / 2; | |
| ballY = canvas.height - 30; | |
| paddleX = (canvas.width - paddleWidth) / 2; | |
| ballSpeedX = 5; | |
| ballSpeedY = -5; | |
| } | |
| } | |
| requestAnimationFrame(draw); | |
| } | |
| // Mouse movement handler | |
| function mouseMoveHandler(e) { | |
| if (!gameRunning || isPaused) return; | |
| const relativeX = e.clientX - canvas.offsetLeft; | |
| if (relativeX > paddleWidth / 2 && relativeX < canvas.width - paddleWidth / 2) { | |
| paddleX = relativeX - paddleWidth / 2; | |
| } | |
| } | |
| // Touch movement handler | |
| function touchMoveHandler(e) { | |
| if (!gameRunning || isPaused) return; | |
| e.preventDefault(); | |
| const touch = e.touches[0] || e.changedTouches[0]; | |
| const relativeX = touch.clientX - canvas.offsetLeft; | |
| if (relativeX > paddleWidth / 2 && relativeX < canvas.width - paddleWidth / 2) { | |
| paddleX = relativeX - paddleWidth / 2; | |
| } | |
| } | |
| // Pause game | |
| function togglePause() { | |
| isPaused = !isPaused; | |
| pauseBtn.innerHTML = isPaused ? | |
| '<i class="fas fa-play mr-2"></i> Resume' : | |
| '<i class="fas fa-pause mr-2"></i> Pause'; | |
| if (!isPaused && gameRunning) { | |
| requestAnimationFrame(draw); | |
| } | |
| if (soundOn) { | |
| if (isPaused) { | |
| backgroundMusic.pause(); | |
| } else { | |
| backgroundMusic.play(); | |
| } | |
| } | |
| } | |
| // Toggle sound | |
| function toggleSound() { | |
| soundOn = !soundOn; | |
| soundBtn.innerHTML = soundOn ? | |
| '<i class="fas fa-volume-up mr-2"></i> Sound On' : | |
| '<i class="fas fa-volume-mute mr-2"></i> Sound Off'; | |
| if (soundOn) { | |
| backgroundMusic.play(); | |
| } else { | |
| backgroundMusic.pause(); | |
| } | |
| } | |
| // Event listeners | |
| canvas.addEventListener('mousemove', mouseMoveHandler); | |
| canvas.addEventListener('touchmove', touchMoveHandler, {passive: false}); | |
| restartBtn.addEventListener('click', restartGame); | |
| nextLevelBtn.addEventListener('click', nextLevel); | |
| pauseBtn.addEventListener('click', togglePause); | |
| soundBtn.addEventListener('click', toggleSound); | |
| // Start the game | |
| initBlocks(); | |
| gameRunning = true; | |
| if (soundOn) { | |
| backgroundMusic.play(); | |
| } | |
| draw(); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=amirpoorazima/down-with-usa" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |