( ′∀`)σ≡σ☆))Д′)レ(゚∀゚;)ヘ=З=З=Зε≡(ノ´_ゝ`)ノ
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Flappy Bird HTML5</title>
<style>
/* Center canvas on page */
body {
margin: 0;
background: #70c5ce;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, sans-serif;
user-select: none;
}
canvas {
background: #fff;
border: 2px solid #333;
display: block;
}
/* Game over text */
#gameOverText {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 48px;
color: #e74c3c;
text-align: center;
display: none;
pointer-events: none;
}
#restartText {
font-size: 24px;
color: #333;
margin-top: 10px;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="600"></canvas>
<div id="gameOverText">
Game Over
<div id="restartText">Press Space to Restart</div>
</div>
<script>
(() => {
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const gameOverText = document.getElementById('gameOverText');
// Constants
const GRAVITY = 0.5;
const JUMP = -8;
const PIPE_WIDTH = 60;
const PIPE_GAP = 150;
const PIPE_SPEED = 2;
const BIRD_SIZE = 30;
// Game variables
let birdY = canvas.height / 2;
let birdX = 80;
let birdVelocity = 0;
let pipes = [];
let score = 0;
let gameOver = false;
function resetGame() {
birdY = canvas.height / 2;
birdVelocity = 0;
pipes = [];
score = 0;
gameOver = false;
gameOverText.style.display = 'none';
// Start with one pipe
addPipe();
loop();
}
function addPipe() {
// Random top pipe height between 50 and canvas.height - PIPE_GAP - 50
const topHeight = Math.floor(Math.random() * (canvas.height - PIPE_GAP - 100)) + 50;
pipes.push({
x: canvas.width,
top: topHeight,
passed: false,
});
}
function drawBird() {
ctx.fillStyle = '#f1c40f';
ctx.beginPath();
ctx.arc(birdX, birdY, BIRD_SIZE / 2, 0, Math.PI * 2);
ctx.fill();
// Optional: draw eye
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(birdX + 5, birdY - 5, 4, 0, Math.PI * 2);
ctx.fill();
}
function drawPipes() {
ctx.fillStyle = '#2ecc40';
pipes.forEach(pipe => {
// Top pipe
ctx.fillRect(pipe.x, 0, PIPE_WIDTH, pipe.top);
// Bottom pipe
ctx.fillRect(pipe.x, pipe.top + PIPE_GAP, PIPE_WIDTH, canvas.height - pipe.top - PIPE_GAP);
});
}
function drawScore() {
ctx.fillStyle = '#333';
ctx.font = '32px Arial';
ctx.fillText(`Score: ${score}`, 10, 50);
}
function updatePipes() {
// Add new pipe if last pipe is far enough
if (pipes.length === 0 || pipes[pipes.length - 1].x < canvas.width - 200) {
addPipe();
}
pipes.forEach(pipe => {
pipe.x -= PIPE_SPEED;
// Check if pipe passed bird for scoring
if (!pipe.passed && pipe.x + PIPE_WIDTH < birdX) {
score++;
pipe.passed = true;
}
});
// Remove pipes that are off-screen
if (pipes.length && pipes[0].x + PIPE_WIDTH < 0) {
pipes.shift();
}
}
function checkCollision() {
// Check collision with pipes
for (let pipe of pipes) {
if (
birdX + BIRD_SIZE / 2 > pipe.x &&
birdX - BIRD_SIZE / 2 < pipe.x + PIPE_WIDTH
) {
if (
birdY - BIRD_SIZE / 2 < pipe.top ||
birdY + BIRD_SIZE / 2 > pipe.top + PIPE_GAP
) {
return true;
}
}
}
// Check collision with floor or ceiling
if (birdY + BIRD_SIZE / 2 > canvas.height || birdY - BIRD_SIZE / 2 < 0) {
return true;
}
return false;
}
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw
drawPipes();
drawBird();
drawScore();
if (!gameOver) {
// Physics
birdVelocity += GRAVITY;
birdY += birdVelocity;
updatePipes();
if (checkCollision()) {
gameOver = true;
gameOverText.style.display = 'block';
} else {
requestAnimationFrame(loop);
}
}
}
// Controls
window.addEventListener('keydown', e => {
if (e.code === 'Space') {
e.preventDefault();
if (!gameOver) {
birdVelocity = JUMP;
} else {
resetGame();
}
}
});
// Start the game
resetGame();
})();
</script>
</body>
</html>