Spaces:
Running
Running
| <script> | |
| const gameArea = document.getElementById('gameArea'); | |
| const player = document.getElementById('player'); | |
| let score = 0; | |
| let level = 1; | |
| let isGameActive = true; | |
| let playerX = 385; | |
| let playerY = 285; | |
| let playerSpeed = 5; | |
| let enemies = []; | |
| let balls = []; | |
| let powerups = []; | |
| let hasShield = false; | |
| const keys = {}; | |
| class Enemy { | |
| constructor(type) { | |
| this.element = document.createElement('div'); | |
| this.element.className = `enemy ${type}`; | |
| this.type = type; | |
| this.x = Math.random() * 750; | |
| this.y = type === 'bouncer' ? 550 : Math.random() * 550; | |
| this.dx = (Math.random() - 0.5) * 4; | |
| this.dy = type === 'bouncer' ? -10 : (Math.random() - 0.5) * 4; | |
| gameArea.appendChild(this.element); | |
| this.startShooting(); | |
| } | |
| update() { | |
| if (this.type === 'bouncer') { | |
| this.dy += 0.5; // Gravity | |
| if (this.y > 550) this.dy = -Math.abs(this.dy) * 0.8; | |
| } | |
| this.x += this.dx; | |
| this.y += this.dy; | |
| // Bounce off walls | |
| if (this.x < 0 || this.x > 750) this.dx *= -1; | |
| if (this.y < 0) this.dy = Math.abs(this.dy); | |
| this.element.style.left = this.x + 'px'; | |
| this.element.style.top = this.y + 'px'; | |
| this.createTrail(); | |
| } | |
| startShooting() { | |
| setInterval(() => { | |
| if (!isGameActive) return; | |
| this.shoot(); | |
| }, 2000); | |
| } | |
| shoot() { | |
| const types = ['fire-ball', 'ice-ball', 'thunder-ball']; | |
| const type = types[Math.floor(Math.random() * types.length)]; | |
| const ball = this.createBall(type); | |
| this.launchBall(ball); | |
| } | |
| createBall(type) { | |
| const ball = document.createElement('div'); | |
| ball.className = `ball ${type}`; | |
| ball.style.left = this.x + 'px'; | |
| ball.style.top = this.y + 'px'; | |
| gameArea.appendChild(ball); | |
| return { element: ball, type }; | |
| } | |
| launchBall(ball) { | |
| const angle = Math.atan2(playerY - this.y, playerX - this.x); | |
| const speed = ball.type === 'ice-ball' ? 7 : | |
| ball.type === 'thunder-ball' ? 4 : 5; | |
| balls.push({ | |
| ...ball, | |
| x: this.x, | |
| y: this.y, | |
| dx: Math.cos(angle) * speed, | |
| dy: Math.sin(angle) * speed | |
| }); | |
| } | |
| createTrail() { | |
| const trail = document.createElement('div'); | |
| trail.className = 'trail'; | |
| trail.style.width = this.element.offsetWidth + 'px'; | |
| trail.style.height = this.element.offsetHeight + 'px'; | |
| trail.style.left = this.x + 'px'; | |
| trail.style.top = this.y + 'px'; | |
| trail.style.background = this.type === 'bouncer' ? | |
| 'rgba(255,0,0,0.3)' : 'rgba(255,0,255,0.3)'; | |
| gameArea.appendChild(trail); | |
| setTimeout(() => trail.remove(), 500); | |
| } | |
| } | |
| function update() { | |
| if (!isGameActive) return; | |
| updatePlayer(); | |
| updateEnemies(); | |
| updateBalls(); | |
| updatePowerups(); | |
| checkCollisions(); | |
| updateScore(); | |
| requestAnimationFrame(update); | |
| } | |
| function updatePlayer() { | |
| if (keys['ArrowLeft'] || keys['a']) playerX = Math.max(0, playerX - playerSpeed); | |
| if (keys['ArrowRight'] || keys['d']) playerX = Math.min(770, playerX + playerSpeed); | |
| if (keys['ArrowUp'] || keys['w']) playerY = Math.max(0, playerY - playerSpeed); | |
| if (keys['ArrowDown'] || keys['s']) playerY = Math.min(570, playerY + playerSpeed); | |
| player.style.left = playerX + 'px'; | |
| player.style.top = playerY + 'px'; | |
| } | |
| function updateEnemies() { | |
| enemies.forEach(enemy => enemy.update()); | |
| } | |
| function updateBalls() { | |
| balls.forEach((ball, index) => { | |
| ball.x += ball.dx; | |
| ball.y += ball.dy; | |
| ball.element.style.left = ball.x + 'px'; | |
| ball.element.style.top = ball.y + 'px'; | |
| if (ball.x < -50 || ball.x > 850 || ball.y < -50 || ball.y > 650) { | |
| ball.element.remove(); | |
| balls.splice(index, 1); | |
| } | |
| }); | |
| } | |
| function updatePowerups() { | |
| powerups.forEach(powerup => { | |
| powerup.y += 2; | |
| powerup.element.style.top = powerup.y + 'px'; | |
| if (powerup.y > 600) { | |
| powerup.element.remove(); | |
| powerups = powerups.filter(p => p !== powerup); | |
| } | |
| }); | |
| } | |
| function checkCollisions() { | |
| const playerRect = player.getBoundingClientRect(); | |
| // Check collisions with enemies and balls | |
| enemies.concat(balls).forEach(obj => { | |
| const rect = obj.element.getBoundingClientRect(); | |
| if (isColliding(playerRect, rect)) { | |
| if (hasShield) { | |
| hasShield = false; | |
| document.getElementById('shieldStatus').textContent = '❌'; | |
| } else { | |
| gameOver(); | |
| } | |
| } | |
| }); | |
| } | |
| function isColliding(rect1, rect2) { | |
| return !(rect1.right < rect2.left || | |
| rect1.left > rect2.right || | |
| rect1.bottom < rect2.top || | |
| rect1.top > rect2.bottom); | |
| } | |
| function updateScore() { | |
| score++; | |
| document.getElementById('scoreValue').textContent = score; | |
| if (score % 500 === 0) { | |
| level++; | |
| document.getElementById('levelValue').textContent = level; | |
| enemies.push(new Enemy(Math.random() < 0.5 ? 'bouncer' : 'spinner')); | |
| } | |
| } | |
| function gameOver() { | |
| isGameActive = false; | |
| document.getElementById('gameOver').style.display = 'flex'; | |
| document.getElementById('finalScore').textContent = score; | |
| } | |
| // Event Listeners | |
| document.addEventListener('keydown', e => keys[e.key] = true); | |
| document.addEventListener('keyup', e => keys[e.key] = false); | |
| // Initialize game | |
| enemies.push(new Enemy('bouncer')); | |
| enemies.push(new Enemy('spinner')); | |
| update(); | |
| </script> |