Spaces:
Running
Running
| const player = document.getElementById('player'); | |
| const scoreDisplay = document.getElementById('score'); | |
| const gameArea = document.getElementById('game-area'); | |
| const gameOverDisplay = document.getElementById('game-over'); | |
| const pauseButton = document.getElementById('pause-button'); | |
| const pauseMenu = document.getElementById('pause-menu'); | |
| const resumeButton = document.getElementById('resume-button'); | |
| let score = 0; | |
| let gameOver = false; | |
| let isPaused = false; | |
| let orbSpeed = 2; | |
| let bonusSpeed = 4; | |
| let intervalId; | |
| let orbs = []; | |
| let bonuses = []; | |
| // Player movement (mouse control) | |
| document.addEventListener('mousemove', (e) => { | |
| if (isPaused || gameOver) return; | |
| const gameAreaRect = gameArea.getBoundingClientRect(); | |
| let mouseX = e.clientX - gameAreaRect.left; | |
| if (mouseX < 0) mouseX = 0; | |
| if (mouseX > gameArea.offsetWidth - player.offsetWidth) mouseX = gameArea.offsetWidth - player.offsetWidth; | |
| player.style.left = `${mouseX}px`; | |
| }); | |
| // Player movement (touch control) | |
| gameArea.addEventListener('touchstart', (e) => { | |
| touchStartX = e.touches[0].clientX; | |
| touchCurrentX = touchStartX; | |
| }); | |
| gameArea.addEventListener('touchmove', (e) => { | |
| touchCurrentX = e.touches[0].clientX; | |
| if (!isPaused && !gameOver) { | |
| const gameAreaRect = gameArea.getBoundingClientRect(); | |
| let playerLeft = touchCurrentX - gameAreaRect.left - player.offsetWidth / 2; | |
| playerLeft = Math.max(0, Math.min(playerLeft, gameArea.offsetWidth - player.offsetWidth)); | |
| player.style.left = `${playerLeft}px`; | |
| } | |
| }, { passive: true }); | |
| // Pause on Esc key | |
| document.addEventListener('keydown', (e) => { | |
| if (e.key === 'Escape') { | |
| togglePause(); | |
| } | |
| }); | |
| // Pause on window blur | |
| window.addEventListener('blur', () => { | |
| if (!gameOver && !isPaused) { | |
| togglePause(); | |
| } | |
| }); | |
| // Pause button for mobile devices | |
| pauseButton.addEventListener('click', () => { | |
| togglePause(); | |
| }); | |
| // Resume button | |
| resumeButton.addEventListener('click', () => { | |
| togglePause(); | |
| }); | |
| // Create orb | |
| function createOrb() { | |
| if (isPaused || gameOver) return; | |
| const orb = document.createElement('div'); | |
| orb.classList.add('orb'); | |
| orb.style.backgroundColor = `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255})`; | |
| orb.style.left = `${Math.random() * (gameArea.offsetWidth - 30)}px`; | |
| orb.style.top = `${Math.random() * -50}px`; // Start above the top | |
| gameArea.appendChild(orb); | |
| // Create trail | |
| const trail = document.createElement('div'); | |
| trail.classList.add('trail'); | |
| trail.style.background = orb.style.background; | |
| trail.style.left = orb.style.left; | |
| trail.style.top = orb.style.top; | |
| gameArea.appendChild(trail); | |
| let orbInterval = setInterval(() => { | |
| if (isPaused || gameOver) { | |
| clearInterval(orbInterval); | |
| return; | |
| } | |
| let orbTop = parseFloat(getComputedStyle(orb).getPropertyValue('top')); | |
| orb.style.top = `${orbTop + orbSpeed}px`; | |
| trail.style.top = `${orbTop + orbSpeed}px`; | |
| if (orbTop > gameArea.offsetHeight) { | |
| clearInterval(orbInterval); | |
| gameArea.removeChild(orb); | |
| gameArea.removeChild(trail); | |
| orbs = orbs.filter(o => o !== orb); | |
| } | |
| // Collision detection | |
| if (checkCollision(orb, player)) { | |
| clearInterval(orbInterval); | |
| gameArea.removeChild(orb); | |
| gameArea.removeChild(trail); | |
| score += 10; | |
| scoreDisplay.textContent = score; | |
| increaseDifficulty(); | |
| } | |
| }, 16); | |
| orbs.push({ element: orb, interval: orbInterval }); | |
| } | |
| // Create bonus | |
| function createBonus() { | |
| if (isPaused || gameOver) return; | |
| const bonus = document.createElement('div'); | |
| bonus.classList.add('bonus'); | |
| bonus.style.left = `${Math.random() * (gameArea.offsetWidth - 30)}px`; | |
| bonus.style.top = `${Math.random() * -50}px`; // Start above the top | |
| gameArea.appendChild(bonus); | |
| // Create trail | |
| const trail = document.createElement('div'); | |
| trail.classList.add('trail'); | |
| trail.style.background = bonus.style.background; | |
| trail.style.left = bonus.style.left; | |
| trail.style.top = bonus.style.top; | |
| gameArea.appendChild(trail); | |
| let bonusInterval = setInterval(() => { | |
| if (isPaused || gameOver) { | |
| clearInterval(bonusInterval); | |
| return; | |
| } | |
| let bonusTop = parseFloat(getComputedStyle(bonus).getPropertyValue('top')); | |
| bonus.style.top = `${bonusTop + bonusSpeed}px`; | |
| trail.style.top = `${bonusTop + bonusSpeed}px`; | |
| if (bonusTop > gameArea.offsetHeight) { | |
| clearInterval(bonusInterval); | |
| gameArea.removeChild(bonus); | |
| gameArea.removeChild(trail); | |
| bonuses = bonuses.filter(b => b !== bonus); | |
| } | |
| // Collision detection | |
| if (checkCollision(bonus, player)) { | |
| clearInterval(bonusInterval); | |
| gameArea.removeChild(bonus); | |
| gameArea.removeChild(trail); | |
| score += 50; // Bonus gives 50 points | |
| scoreDisplay.textContent = score; | |
| } | |
| }, 16); | |
| bonuses.push({ element: bonus, interval: bonusInterval }); | |
| } | |
| // Collision detection | |
| function checkCollision(a, b) { | |
| const aRect = a.getBoundingClientRect(); | |
| const bRect = b.getBoundingClientRect(); | |
| return !( | |
| aRect.bottom < bRect.top || | |
| aRect.top > bRect.bottom || | |
| aRect.right < bRect.left || | |
| aRect.left > bRect.right | |
| ); | |
| } | |
| // Increase difficulty | |
| function increaseDifficulty() { | |
| orbSpeed += 0.1; | |
| bonusSpeed += 0.05; | |
| } | |
| // Toggle pause | |
| function togglePause() { | |
| if (gameOver) return; | |
| isPaused = !isPaused; | |
| if (isPaused) { | |
| clearInterval(intervalId); | |
| pauseButton.textContent = "Pause"; | |
| pauseMenu.style.display = "block"; | |
| pauseButton.style.display = "none"; | |
| // Stop all orb intervals | |
| orbs.forEach(o => clearInterval(o.interval)); | |
| bonuses.forEach(b => clearInterval(b.interval)); | |
| } else { | |
| intervalId = setInterval(() => { | |
| createOrb(); | |
| if (Math.random() < 0.1) { // 10% chance to create a bonus | |
| createBonus(); | |
| } | |
| }, 500); | |
| pauseMenu.style.display = "none"; | |
| pauseButton.style.display = "block"; | |
| // Resume all orb intervals | |
| orbs.forEach(o => { | |
| d.interval = setInterval(o.orbInterval, 16); | |
| }); | |
| bonuses.forEach(b => { | |
| b.interval = setInterval(b.bonusInterval, 16); | |
| }); | |
| } | |
| } | |
| // Game over | |
| function endGame() { | |
| clearInterval(intervalId); | |
| orbs.forEach(o => clearInterval(o.interval)); | |
| bonuses.forEach(b => clearInterval(b.interval)); | |
| gameOver = true; | |
| gameOverDisplay.style.display = "block"; | |
| isPaused = true; | |
| pauseButton.style.display = "none"; | |
| pauseMenu.style.display = "none"; | |
| } | |
| // Start game | |
| function startGame() { | |
| score = 0; | |
| scoreDisplay.textContent = score; | |
| orbSpeed = 2; | |
| bonusSpeed = 4; | |
| gameOverDisplay.style.display = "none"; | |
| gameOver = false; | |
| isPaused = false; | |
| pauseButton.style.display = "none"; | |
| pauseMenu.style.display = "none"; | |
| orbs = []; | |
| bonuses = []; | |
| intervalId = setInterval(() => { | |
| createOrb(); | |
| if (Math.random() < 0.1) { // 10% chance to create a bonus | |
| createBonus(); | |
| } | |
| }, 500); | |
| // Show pause button on mobile devices | |
| if (window.innerWidth <= 600) { | |
| pauseButton.style.display = "block"; | |
| } | |
| } | |
| // Start the game | |
| startGame(); | |