| | <!DOCTYPE html> |
| | <html lang="en"> |
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title>Flappy Bird: Hyper Edition</title> |
| | <script src="https://cdn.tailwindcss.com"></script> |
| | <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script> |
| | <style> |
| | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap'); |
| | |
| | body { |
| | font-family: 'Poppins', sans-serif; |
| | overflow: hidden; |
| | touch-action: manipulation; |
| | background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%); |
| | margin: 0; |
| | padding: 0; |
| | } |
| | |
| | .game-container { |
| | position: relative; |
| | width: 100vw; |
| | height: 100vh; |
| | overflow: hidden; |
| | } |
| | |
| | canvas { |
| | display: block; |
| | background-color: #87CEEB; |
| | } |
| | |
| | .bird { |
| | transition: all 0.3s ease; |
| | position: relative; |
| | } |
| | |
| | .bird::after { |
| | content: ''; |
| | position: absolute; |
| | top: 0; |
| | left: 0; |
| | right: 0; |
| | bottom: 0; |
| | background: rgba(255, 255, 255, 0.1); |
| | border-radius: 50%; |
| | transform: scale(0.9); |
| | opacity: 0; |
| | transition: all 0.3s ease; |
| | } |
| | |
| | .bird:hover::after { |
| | opacity: 1; |
| | transform: scale(1.1); |
| | } |
| | |
| | .pipe { |
| | transition: transform 0.1s linear; |
| | } |
| | |
| | .score-display { |
| | text-shadow: 0 0 10px rgba(255, 255, 255, 0.8); |
| | animation: pulse 1.5s infinite alternate; |
| | } |
| | |
| | @keyframes pulse { |
| | from { transform: scale(1); } |
| | to { transform: scale(1.1); } |
| | } |
| | |
| | .game-over { |
| | animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both; |
| | } |
| | |
| | @keyframes shake { |
| | 10%, 90% { transform: translate3d(-1px, 0, 0); } |
| | 20%, 80% { transform: translate3d(2px, 0, 0); } |
| | 30%, 50%, 70% { transform: translate3d(-4px, 0, 0); } |
| | 40%, 60% { transform: translate3d(4px, 0, 0); } |
| | } |
| | |
| | .bird-option { |
| | transition: all 0.3s ease; |
| | transform-style: preserve-3d; |
| | } |
| | |
| | .bird-option:hover { |
| | transform: translateY(-10px) scale(1.1) rotateY(15deg); |
| | } |
| | |
| | .bird-option.selected { |
| | box-shadow: 0 0 20px rgba(255, 215, 0, 0.7); |
| | transform: translateY(-15px) scale(1.15) rotateY(0deg); |
| | animation: float 3s ease-in-out infinite; |
| | } |
| | |
| | @keyframes float { |
| | 0%, 100% { transform: translateY(-15px) scale(1.15); } |
| | 50% { transform: translateY(-25px) scale(1.15); } |
| | } |
| | |
| | .flap-particle { |
| | position: absolute; |
| | background-color: rgba(255, 255, 255, 0.7); |
| | border-radius: 50%; |
| | pointer-events: none; |
| | } |
| | |
| | .parallax-layer { |
| | position: absolute; |
| | width: 300%; |
| | height: 100%; |
| | background-repeat: repeat-x; |
| | will-change: transform; |
| | } |
| | |
| | .bird-eye { |
| | position: absolute; |
| | background: white; |
| | border-radius: 50%; |
| | animation: blink 5s infinite; |
| | } |
| | |
| | @keyframes blink { |
| | 0%, 95%, 100% { transform: scaleY(1); } |
| | 97.5% { transform: scaleY(0.1); } |
| | } |
| | |
| | .bird-beak { |
| | position: absolute; |
| | background: #FF9800; |
| | clip-path: polygon(0 0, 100% 50%, 0 100%); |
| | } |
| | |
| | .bird-wing { |
| | position: absolute; |
| | background: currentColor; |
| | border-radius: 50%; |
| | animation: flap 0.3s infinite alternate; |
| | } |
| | |
| | @keyframes flap { |
| | 0% { transform: rotate(0deg); } |
| | 100% { transform: rotate(20deg); } |
| | } |
| | |
| | .feather { |
| | position: absolute; |
| | background: currentColor; |
| | clip-path: polygon(50% 0%, 0% 100%, 100% 100%); |
| | } |
| | </style> |
| | </head> |
| | <body class="flex items-center justify-center min-h-screen"> |
| | <div class="game-container relative"> |
| | |
| | <canvas id="gameCanvas" class="absolute top-0 left-0 w-full h-full"></canvas> |
| | |
| | |
| | <div id="parallaxContainer" class="absolute top-0 left-0 w-full h-full overflow-hidden"> |
| | <div class="parallax-layer bg-blue-400 opacity-20" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjEiIGQ9Ik0wLDEwMCBMNTAsMCBMMTAwLDEwMCBMMCwxMDAgWiIvPjwvc3ZnPg=='); background-size: 100px 100px;"></div> |
| | <div class="parallax-layer bg-blue-500 opacity-15" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIyIi8+PC9zdmc+'); background-size: 150px 150px;"></div> |
| | <div class="parallax-layer bg-blue-600 opacity-10" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHJlY3Qgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9zdmc+'); background-size: 200px 200px;"></div> |
| | </div> |
| | |
| | |
| | <div id="startScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-50 transition-opacity duration-500"> |
| | <h1 class="text-6xl font-bold text-white mb-8">Flappy Bird: Hyper Edition</h1> |
| | |
| | <div class="mb-12 text-center"> |
| | <h2 class="text-2xl text-white mb-4">Choose Your Bird</h2> |
| | <div class="flex space-x-8"> |
| | <div class="bird-option cursor-pointer" data-color="yellow"> |
| | <div class="w-20 h-20 bg-yellow-400 rounded-full flex items-center justify-center shadow-lg relative"> |
| | <div class="bird-eye w-4 h-4 absolute top-1/3 left-1/2 transform -translate-x-1/2 -translate-y-1/2"> |
| | <div class="w-2 h-2 bg-black rounded-full absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"></div> |
| | </div> |
| | <div class="bird-beak w-6 h-4 absolute top-1/2 left-3/4"></div> |
| | <div class="bird-wing w-12 h-8 absolute top-3/4 left-1/4"></div> |
| | </div> |
| | <p class="text-white text-center mt-2">Classic</p> |
| | </div> |
| | <div class="bird-option cursor-pointer" data-color="red"> |
| | <div class="w-20 h-20 bg-red-500 rounded-full flex items-center justify-center shadow-lg relative"> |
| | <div class="bird-eye w-4 h-4 absolute top-1/3 left-1/2 transform -translate-x-1/2 -translate-y-1/2"> |
| | <div class="w-2 h-2 bg-black rounded-full absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"></div> |
| | </div> |
| | <div class="bird-beak w-6 h-4 absolute top-1/2 left-3/4"></div> |
| | <div class="bird-wing w-12 h-8 absolute top-3/4 left-1/4"></div> |
| | </div> |
| | <p class="text-white text-center mt-2">Red</p> |
| | </div> |
| | <div class="bird-option cursor-pointer" data-color="blue"> |
| | <div class="w-20 h-20 bg-blue-500 rounded-full flex items-center justify-center shadow-lg relative"> |
| | <div class="bird-eye w-4 h-4 absolute top-1/3 left-1/2 transform -translate-x-1/2 -translate-y-1/2"> |
| | <div class="w-2 h-2 bg-black rounded-full absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"></div> |
| | </div> |
| | <div class="bird-beak w-6 h-4 absolute top-1/2 left-3/4"></div> |
| | <div class="bird-wing w-12 h-8 absolute top-3/4 left-1/4"></div> |
| | </div> |
| | <p class="text-white text-center mt-2">Blue</p> |
| | </div> |
| | <div class="bird-option cursor-pointer" data-color="green"> |
| | <div class="w-20 h-20 bg-green-500 rounded-full flex items-center justify-center shadow-lg relative"> |
| | <div class="bird-eye w-4 h-4 absolute top-1/3 left-1/2 transform -translate-x-1/2 -translate-y-1/2"> |
| | <div class="w-2 h-2 bg-black rounded-full absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"></div> |
| | </div> |
| | <div class="bird-beak w-6 h-4 absolute top-1/2 left-3/4"></div> |
| | <div class="bird-wing w-12 h-8 absolute top-3/4 left-1/4"></div> |
| | </div> |
| | <p class="text-white text-center mt-2">Green</p> |
| | </div> |
| | </div> |
| | </div> |
| | |
| | <button id="startButton" class="px-12 py-4 bg-yellow-400 hover:bg-yellow-300 text-black font-bold rounded-full text-xl transition-all transform hover:scale-105 shadow-lg hover:shadow-yellow-300/50"> |
| | Start Game |
| | </button> |
| | |
| | <div class="mt-8 text-white"> |
| | <p>Press SPACE or click/tap to flap</p> |
| | </div> |
| | </div> |
| | |
| | |
| | <div id="scoreDisplay" class="absolute top-8 left-0 right-0 text-center text-6xl font-bold text-white score-display opacity-0 transition-opacity duration-300"> |
| | 0 |
| | </div> |
| | |
| | |
| | <div id="gameOverScreen" class="absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-70 opacity-0 transition-opacity duration-500 pointer-events-none"> |
| | <div class="bg-gray-800 rounded-xl p-8 max-w-md w-full text-center game-over"> |
| | <h2 class="text-4xl font-bold text-white mb-4">Game Over</h2> |
| | <p class="text-2xl text-white mb-2">Your Score: <span id="finalScore" class="text-yellow-400">0</span></p> |
| | <p class="text-xl text-white mb-6">High Score: <span id="highScore" class="text-green-400">0</span></p> |
| | |
| | <div class="flex space-x-4 justify-center"> |
| | <button id="restartButton" class="px-8 py-3 bg-yellow-400 hover:bg-yellow-300 text-black font-bold rounded-full transition-all transform hover:scale-105"> |
| | Play Again |
| | </button> |
| | <button id="menuButton" class="px-8 py-3 bg-gray-600 hover:bg-gray-500 text-white font-bold rounded-full transition-all transform hover:scale-105"> |
| | Main Menu |
| | </button> |
| | </div> |
| | </div> |
| | </div> |
| | </div> |
| |
|
| | <script> |
| | |
| | const GRAVITY = 0.5; |
| | const JUMP_FORCE = -10; |
| | const PIPE_WIDTH = 80; |
| | const PIPE_GAP = 200; |
| | const PIPE_SPEED = 3; |
| | const BIRD_WIDTH = 40; |
| | const BIRD_HEIGHT = 30; |
| | const GROUND_HEIGHT = 100; |
| | |
| | |
| | let canvas, ctx; |
| | let gameWidth, gameHeight; |
| | let bird = { |
| | x: 100, |
| | y: 250, |
| | width: BIRD_WIDTH, |
| | height: BIRD_HEIGHT, |
| | velocity: 0, |
| | rotation: 0, |
| | color: 'yellow', |
| | wingAngle: 0, |
| | eyeScale: 1 |
| | }; |
| | let pipes = []; |
| | let score = 0; |
| | let highScore = localStorage.getItem('flappyHighScore') || 0; |
| | let gameStarted = false; |
| | let gameOver = false; |
| | let animationFrameId; |
| | let lastPipeTime = 0; |
| | let parallaxOffset = 0; |
| | let flapParticles = []; |
| | let lastFlapTime = 0; |
| | let gameTime = 0; |
| | |
| | |
| | const startScreen = document.getElementById('startScreen'); |
| | const gameOverScreen = document.getElementById('gameOverScreen'); |
| | const scoreDisplay = document.getElementById('scoreDisplay'); |
| | const finalScore = document.getElementById('finalScore'); |
| | const highScoreElement = document.getElementById('highScore'); |
| | const startButton = document.getElementById('startButton'); |
| | const restartButton = document.getElementById('restartButton'); |
| | const menuButton = document.getElementById('menuButton'); |
| | const birdOptions = document.querySelectorAll('.bird-option'); |
| | const parallaxLayers = document.querySelectorAll('.parallax-layer'); |
| | |
| | |
| | function init() { |
| | canvas = document.getElementById('gameCanvas'); |
| | ctx = canvas.getContext('2d'); |
| | |
| | resizeCanvas(); |
| | window.addEventListener('resize', resizeCanvas); |
| | |
| | |
| | startButton.addEventListener('click', startGame); |
| | restartButton.addEventListener('click', restartGame); |
| | menuButton.addEventListener('click', showMenu); |
| | |
| | document.addEventListener('keydown', (e) => { |
| | if (e.code === 'Space') { |
| | e.preventDefault(); |
| | if (!gameStarted) startGame(); |
| | else if (!gameOver) flap(); |
| | } |
| | }); |
| | |
| | canvas.addEventListener('click', () => { |
| | if (!gameStarted) startGame(); |
| | else if (!gameOver) flap(); |
| | }); |
| | |
| | |
| | canvas.addEventListener('touchstart', (e) => { |
| | e.preventDefault(); |
| | if (!gameStarted) startGame(); |
| | else if (!gameOver) flap(); |
| | }); |
| | |
| | |
| | birdOptions.forEach(option => { |
| | option.addEventListener('click', () => { |
| | birdOptions.forEach(opt => opt.classList.remove('selected')); |
| | option.classList.add('selected'); |
| | bird.color = option.dataset.color; |
| | }); |
| | }); |
| | |
| | |
| | birdOptions[0].classList.add('selected'); |
| | |
| | |
| | render(); |
| | } |
| | |
| | |
| | function resizeCanvas() { |
| | gameWidth = window.innerWidth; |
| | gameHeight = window.innerHeight; |
| | canvas.width = gameWidth; |
| | canvas.height = gameHeight; |
| | } |
| | |
| | |
| | function startGame() { |
| | |
| | bird.y = gameHeight / 2; |
| | bird.velocity = 0; |
| | bird.rotation = 0; |
| | bird.wingAngle = 0; |
| | bird.eyeScale = 1; |
| | pipes = []; |
| | score = 0; |
| | gameStarted = true; |
| | gameOver = false; |
| | lastPipeTime = 0; |
| | parallaxOffset = 0; |
| | flapParticles = []; |
| | gameTime = 0; |
| | |
| | |
| | startScreen.style.opacity = '0'; |
| | startScreen.style.pointerEvents = 'none'; |
| | |
| | scoreDisplay.textContent = '0'; |
| | scoreDisplay.style.opacity = '1'; |
| | gameOverScreen.style.opacity = '0'; |
| | gameOverScreen.style.pointerEvents = 'none'; |
| | |
| | |
| | if (animationFrameId) { |
| | cancelAnimationFrame(animationFrameId); |
| | } |
| | gameLoop(); |
| | } |
| | |
| | |
| | function gameLoop(timestamp) { |
| | update(timestamp); |
| | render(); |
| | |
| | if (!gameOver) { |
| | animationFrameId = requestAnimationFrame(gameLoop); |
| | } |
| | } |
| | |
| | |
| | function update(timestamp) { |
| | if (!gameStarted || gameOver) return; |
| | |
| | gameTime += 16; |
| | |
| | |
| | bird.velocity += GRAVITY; |
| | bird.y += bird.velocity; |
| | |
| | |
| | bird.rotation = Math.min(Math.max(bird.velocity * 3, -30), 90); |
| | |
| | |
| | bird.wingAngle = Math.sin(gameTime * 0.02) * 20; |
| | |
| | |
| | if (Math.random() < 0.002) { |
| | bird.eyeScale = 0.1; |
| | setTimeout(() => { |
| | bird.eyeScale = 1; |
| | }, 100); |
| | } |
| | |
| | |
| | if (timestamp - lastPipeTime > 2000) { |
| | createPipe(); |
| | lastPipeTime = timestamp; |
| | } |
| | |
| | |
| | for (let i = pipes.length - 1; i >= 0; i--) { |
| | pipes[i].x -= PIPE_SPEED; |
| | |
| | |
| | if (!pipes[i].passed && bird.x > pipes[i].x + PIPE_WIDTH) { |
| | pipes[i].passed = true; |
| | score++; |
| | scoreDisplay.textContent = score; |
| | |
| | |
| | gsap.to(scoreDisplay, { |
| | scale: 1.3, |
| | duration: 0.1, |
| | yoyo: true, |
| | repeat: 1, |
| | ease: "power1.inOut" |
| | }); |
| | } |
| | |
| | |
| | if (pipes[i].x + PIPE_WIDTH < 0) { |
| | pipes.splice(i, 1); |
| | } |
| | } |
| | |
| | |
| | parallaxOffset += 0.5; |
| | updateParallax(); |
| | |
| | |
| | updateParticles(); |
| | |
| | |
| | checkCollisions(); |
| | } |
| | |
| | |
| | function render() { |
| | |
| | ctx.clearRect(0, 0, gameWidth, gameHeight); |
| | |
| | |
| | const skyGradient = ctx.createLinearGradient(0, 0, 0, gameHeight); |
| | skyGradient.addColorStop(0, '#87CEEB'); |
| | skyGradient.addColorStop(1, '#1E90FF'); |
| | ctx.fillStyle = skyGradient; |
| | ctx.fillRect(0, 0, gameWidth, gameHeight); |
| | |
| | |
| | ctx.fillStyle = '#5C3317'; |
| | ctx.fillRect(0, gameHeight - GROUND_HEIGHT, gameWidth, GROUND_HEIGHT); |
| | |
| | |
| | ctx.fillStyle = '#4CAF50'; |
| | ctx.beginPath(); |
| | for (let x = 0; x < gameWidth; x += 20) { |
| | const height = 20 + Math.sin(x * 0.1) * 10; |
| | ctx.moveTo(x, gameHeight - GROUND_HEIGHT); |
| | ctx.lineTo(x + 10, gameHeight - GROUND_HEIGHT - height); |
| | ctx.lineTo(x + 20, gameHeight - GROUND_HEIGHT); |
| | } |
| | ctx.fill(); |
| | |
| | |
| | pipes.forEach(pipe => { |
| | |
| | ctx.fillStyle = '#4CAF50'; |
| | ctx.fillRect(pipe.x, 0, PIPE_WIDTH, pipe.topHeight); |
| | |
| | |
| | ctx.fillStyle = '#388E3C'; |
| | ctx.fillRect(pipe.x - 5, pipe.topHeight - 20, PIPE_WIDTH + 10, 20); |
| | |
| | |
| | ctx.fillStyle = '#4CAF50'; |
| | ctx.fillRect(pipe.x, pipe.bottomY, PIPE_WIDTH, gameHeight - pipe.bottomY); |
| | |
| | |
| | ctx.fillStyle = '#388E3C'; |
| | ctx.fillRect(pipe.x - 5, pipe.bottomY, PIPE_WIDTH + 10, 20); |
| | }); |
| | |
| | |
| | flapParticles.forEach(particle => { |
| | ctx.fillStyle = particle.color; |
| | ctx.globalAlpha = particle.opacity; |
| | ctx.beginPath(); |
| | ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2); |
| | ctx.fill(); |
| | ctx.globalAlpha = 1; |
| | }); |
| | |
| | |
| | ctx.save(); |
| | ctx.translate(bird.x + bird.width / 2, bird.y + bird.height / 2); |
| | ctx.rotate(bird.rotation * Math.PI / 180); |
| | |
| | |
| | ctx.fillStyle = getBirdColor(); |
| | ctx.beginPath(); |
| | ctx.ellipse(0, 0, bird.width / 2, bird.height / 2, 0, 0, Math.PI * 2); |
| | ctx.fill(); |
| | |
| | |
| | ctx.fillStyle = getBirdColor(true); |
| | for (let i = 0; i < 5; i++) { |
| | ctx.beginPath(); |
| | ctx.moveTo(-bird.width / 4 + i * 3, 0); |
| | ctx.lineTo(-bird.width / 4 + i * 3 - 5, -5); |
| | ctx.lineTo(-bird.width / 4 + i * 3 - 2, -2); |
| | ctx.closePath(); |
| | ctx.fill(); |
| | } |
| | |
| | |
| | ctx.save(); |
| | ctx.translate(-bird.width / 4, bird.height / 4); |
| | ctx.rotate(bird.wingAngle * Math.PI / 180); |
| | |
| | ctx.fillStyle = getBirdColor(true); |
| | ctx.beginPath(); |
| | ctx.ellipse(0, 0, bird.width / 2, bird.height / 3, 0, 0, Math.PI * 2); |
| | ctx.fill(); |
| | |
| | |
| | ctx.fillStyle = getBirdColor(); |
| | for (let i = 0; i < 3; i++) { |
| | ctx.beginPath(); |
| | ctx.moveTo(0, -bird.height / 3 + i * 10); |
| | ctx.lineTo(-bird.width / 3, -bird.height / 3 + i * 10 + 5); |
| | ctx.lineTo(-bird.width / 6, -bird.height / 3 + i * 10); |
| | ctx.closePath(); |
| | ctx.fill(); |
| | } |
| | ctx.restore(); |
| | |
| | |
| | ctx.fillStyle = 'white'; |
| | ctx.beginPath(); |
| | ctx.arc(bird.width / 4, -bird.height / 4, bird.height / 4 * bird.eyeScale, 0, Math.PI * 2); |
| | ctx.fill(); |
| | |
| | ctx.fillStyle = 'black'; |
| | ctx.beginPath(); |
| | ctx.arc(bird.width / 4 + 2, -bird.height / 4, bird.height / 8 * bird.eyeScale, 0, Math.PI * 2); |
| | ctx.fill(); |
| | |
| | |
| | ctx.fillStyle = '#FF9800'; |
| | ctx.beginPath(); |
| | ctx.moveTo(bird.width / 2, 0); |
| | ctx.lineTo(bird.width / 2 + bird.width / 3, -bird.height / 6); |
| | ctx.lineTo(bird.width / 2 + bird.width / 3, bird.height / 6); |
| | ctx.closePath(); |
| | ctx.fill(); |
| | |
| | |
| | ctx.fillStyle = '#FFC107'; |
| | ctx.beginPath(); |
| | ctx.moveTo(bird.width / 2 + 5, -2); |
| | ctx.lineTo(bird.width / 2 + bird.width / 3 - 5, -bird.height / 6 + 2); |
| | ctx.lineTo(bird.width / 2 + bird.width / 3 - 5, 0); |
| | ctx.closePath(); |
| | ctx.fill(); |
| | |
| | ctx.restore(); |
| | } |
| | |
| | |
| | function createPipe() { |
| | const minHeight = 80; |
| | const maxHeight = gameHeight - GROUND_HEIGHT - PIPE_GAP - minHeight; |
| | const topHeight = minHeight + Math.random() * (maxHeight - minHeight); |
| | |
| | pipes.push({ |
| | x: gameWidth, |
| | topHeight: topHeight, |
| | bottomY: topHeight + PIPE_GAP, |
| | passed: false |
| | }); |
| | } |
| | |
| | |
| | function flap() { |
| | if (Date.now() - lastFlapTime < 100) return; |
| | lastFlapTime = Date.now(); |
| | |
| | bird.velocity = JUMP_FORCE; |
| | |
| | |
| | createFlapParticles(); |
| | |
| | |
| | gsap.to(bird, { |
| | rotation: -20, |
| | duration: 0.2, |
| | ease: "power1.out" |
| | }); |
| | |
| | |
| | bird.eyeScale = 0.1; |
| | setTimeout(() => { |
| | bird.eyeScale = 1; |
| | }, 50); |
| | } |
| | |
| | |
| | function createFlapParticles() { |
| | for (let i = 0; i < 10; i++) { |
| | flapParticles.push({ |
| | x: bird.x - bird.width / 2, |
| | y: bird.y + bird.height / 2, |
| | size: 2 + Math.random() * 4, |
| | velocityX: -3 + Math.random() * 6, |
| | velocityY: -5 + Math.random() * 3, |
| | opacity: 0.7 + Math.random() * 0.3, |
| | color: `rgba(255, 255, 255, ${0.5 + Math.random() * 0.5})`, |
| | life: 30 + Math.random() * 20 |
| | }); |
| | } |
| | } |
| | |
| | |
| | function updateParticles() { |
| | for (let i = flapParticles.length - 1; i >= 0; i--) { |
| | const p = flapParticles[i]; |
| | p.x += p.velocityX; |
| | p.y += p.velocityY; |
| | p.life--; |
| | p.opacity = p.life / 50; |
| | |
| | if (p.life <= 0) { |
| | flapParticles.splice(i, 1); |
| | } |
| | } |
| | } |
| | |
| | |
| | function updateParallax() { |
| | parallaxLayers.forEach((layer, index) => { |
| | const speed = (index + 1) * 0.2; |
| | const x = -((parallaxOffset * speed) % layer.offsetWidth); |
| | layer.style.transform = `translateX(${x}px)`; |
| | }); |
| | } |
| | |
| | |
| | function checkCollisions() { |
| | |
| | if (bird.y + bird.height > gameHeight - GROUND_HEIGHT) { |
| | bird.y = gameHeight - GROUND_HEIGHT - bird.height; |
| | endGame(); |
| | return; |
| | } |
| | |
| | |
| | if (bird.y < 0) { |
| | bird.y = 0; |
| | endGame(); |
| | return; |
| | } |
| | |
| | |
| | for (const pipe of pipes) { |
| | if ( |
| | bird.x + bird.width > pipe.x && |
| | bird.x < pipe.x + PIPE_WIDTH && |
| | (bird.y < pipe.topHeight || bird.y + bird.height > pipe.bottomY) |
| | ) { |
| | endGame(); |
| | return; |
| | } |
| | } |
| | } |
| | |
| | |
| | function endGame() { |
| | if (gameOver) return; |
| | |
| | gameOver = true; |
| | |
| | |
| | if (score > highScore) { |
| | highScore = score; |
| | localStorage.setItem('flappyHighScore', highScore); |
| | } |
| | |
| | |
| | finalScore.textContent = score; |
| | highScoreElement.textContent = highScore; |
| | |
| | |
| | gameOverScreen.style.opacity = '1'; |
| | gameOverScreen.style.pointerEvents = 'auto'; |
| | |
| | |
| | gsap.to(bird, { |
| | rotation: 90, |
| | duration: 0.5, |
| | ease: "power1.in" |
| | }); |
| | |
| | |
| | gsap.to(canvas, { |
| | x: 10, |
| | y: 10, |
| | duration: 0.05, |
| | repeat: 5, |
| | yoyo: true, |
| | ease: "power1.inOut", |
| | onComplete: () => { |
| | gsap.to(canvas, { x: 0, y: 0, duration: 0.1 }); |
| | } |
| | }); |
| | |
| | |
| | for (let i = 0; i < 20; i++) { |
| | flapParticles.push({ |
| | x: bird.x + bird.width / 2, |
| | y: bird.y + bird.height / 2, |
| | size: 3 + Math.random() * 5, |
| | velocityX: -10 + Math.random() * 20, |
| | velocityY: -10 + Math.random() * 20, |
| | opacity: 1, |
| | color: getBirdColor(Math.random() > 0.5), |
| | life: 50 + Math.random() * 50 |
| | }); |
| | } |
| | } |
| | |
| | |
| | function restartGame() { |
| | gameOverScreen.style.opacity = '0'; |
| | gameOverScreen.style.pointerEvents = 'none'; |
| | startGame(); |
| | } |
| | |
| | |
| | function showMenu() { |
| | gameOverScreen.style.opacity = '0'; |
| | gameOverScreen.style.pointerEvents = 'none'; |
| | scoreDisplay.style.opacity = '0'; |
| | |
| | startScreen.style.opacity = '1'; |
| | startScreen.style.pointerEvents = 'auto'; |
| | |
| | |
| | gameStarted = false; |
| | gameOver = false; |
| | } |
| | |
| | |
| | function getBirdColor(isWing = false) { |
| | switch(bird.color) { |
| | case 'yellow': |
| | return isWing ? '#FFD700' : '#FFEB3B'; |
| | case 'red': |
| | return isWing ? '#D32F2F' : '#F44336'; |
| | case 'blue': |
| | return isWing ? '#1976D2' : '#2196F3'; |
| | case 'green': |
| | return isWing ? '#388E3C' : '#4CAF50'; |
| | default: |
| | return '#FFEB3B'; |
| | } |
| | } |
| | |
| | |
| | window.addEventListener('load', init); |
| | </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 Prince <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="Prince" 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=91prince/flappy-bird-hyper-motion" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| | </html> |