Flappy Bird Game | A Game Similar to Flappy Bird
How to Save and Play the Flappy Bird HTML Game
The game is contained in a single HTML file, so no installation is required.
Step 1: Copy the Code
Copy the entire HTML code provided on this page. (below)
Step 2: Create a New File
Open a text editor such as Notepad (Windows) or TextEdit (Mac).
Step 3: Paste the Code
Paste the HTML code into the empty document.
Step 4: Save as an HTML File
Save the file with the name:
FlappyBird.html
Make sure the file extension is .html and not .txt.
Step 5: Open the Game
Locate the saved file and double-click it.
The game will open instantly in your web browser and be ready to play.
Sharing the Game
You can share the HTML file with friends by:
• Email
• Google Drive
• Dropbox
• OneDrive
• Discord
• Telegram
• USB drive
Anyone can play the game by downloading the file and opening it in a modern web browser.
No installation, account, or internet connection is required after downloading the file.
Below is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Flappy Bird Variants</title>
<style>
html, body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: #70c5ce;
font-family: Arial, Helvetica, sans-serif;
touch-action: manipulation;
}
canvas {
display: block;
width: 100vw;
height: 100vh;
}
.hud {
position: fixed;
inset: 0;
pointer-events: none;
user-select: none;
color: #fff;
text-shadow: 0 2px 6px rgba(0,0,0,.35);
}
.score {
position: absolute;
top: 18px;
left: 0;
width: 100%;
text-align: center;
font-size: clamp(28px, 4vw, 44px);
font-weight: 800;
letter-spacing: 1px;
}
.birdName {
position: absolute;
top: 18px;
left: 18px;
font-size: 14px;
font-weight: 700;
opacity: .92;
background: rgba(0,0,0,.16);
padding: 8px 10px;
border-radius: 999px;
backdrop-filter: blur(4px);
}
.centerPanel {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
box-sizing: border-box;
}
.card {
max-width: 420px;
width: 100%;
text-align: center;
background: rgba(0,0,0,.22);
border: 1px solid rgba(255,255,255,.18);
border-radius: 20px;
padding: 18px 18px 16px;
backdrop-filter: blur(6px);
}
.title {
font-size: 34px;
font-weight: 900;
margin: 4px 0 8px;
}
.sub {
font-size: 15px;
line-height: 1.45;
opacity: .95;
margin: 6px 0;
}
.hidden {
display: none;
}
.hint {
margin-top: 12px;
font-size: 13px;
opacity: .88;
}
</style>
</head>
<body>
<canvas id="game"></canvas>
<div class="hud">
<div class="birdName" id="birdName">Bird: ...</div>
<div class="score" id="score">0</div>
<div class="centerPanel" id="startPanel">
<div class="card">
<div class="title">Flappy Birds</div>
<div class="sub">A random bird is chosen every time you open the game.</div>
<div class="sub">Tap, click, or press Space to start.</div>
<div class="hint">Hard mode: the pipes are tuned close to the original Flappy Bird feel.</div>
</div>
</div>
<div class="centerPanel hidden" id="overPanel">
<div class="card">
<div class="title">Game Over</div>
<div class="sub" id="finalScore">Score: 0</div>
<div class="sub" id="bestScore">Best: 0</div>
<div class="hint">Tap, click, or press Space to play again.</div>
</div>
</div>
</div>
<script>
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
const scoreEl = document.getElementById("score");
const birdNameEl = document.getElementById("birdName");
const startPanel = document.getElementById("startPanel");
const overPanel = document.getElementById("overPanel");
const finalScoreEl = document.getElementById("finalScore");
const bestScoreEl = document.getElementById("bestScore");
let W = 0, H = 0, dpr = 1;
const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
const rand = (min, max) => Math.random() * (max - min) + min;
function resize() {
dpr = Math.max(1, window.devicePixelRatio || 1);
W = window.innerWidth;
H = window.innerHeight;
canvas.width = Math.floor(W * dpr);
canvas.height = Math.floor(H * dpr);
canvas.style.width = W + "px";
canvas.style.height = H + "px";
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
bird.x = W * 0.26;
groundH = clamp(Math.round(H * 0.16), 78, 120);
pipeGap = clamp(Math.round(H * 0.26), 136, 160);
pipeSpacing = clamp(Math.round(W * 0.41), 170, 230);
pipeSpeed = clamp(W / 300, 2.8, 3.2);
if (bird.y === 0) bird.y = H * 0.45;
}
function makeBirdStyle(i, name) {
const hue = (i * 12 + 18) % 360;
const wingHue = (hue + 18) % 360;
const bellyHue = (hue + 8) % 360;
const beakHue = (hue + 42) % 360;
return {
name,
body: `hsl(${hue} 88% 60%)`,
wing: `hsl(${wingHue} 80% 45%)`,
belly: `hsl(${bellyHue} 100% 82%)`,
beak: `hsl(${beakHue} 95% 58%)`,
eye: "#1c1c1c",
accent: `hsl(${(hue + 180) % 360} 92% 66%)`,
pattern: ["none", "stripe", "cheek", "speckle", "crown"][i % 5]
};
}
const birdNames = [
"Sun Sparrow","Berry Finch","Sky Canary","Mint Robin","Coral Wren",
"Lemon Lark","Aqua Swift","Rose Sparrow","Olive Thrush","Violet Tit",
"Amber Finch","Ice Warbler","Mango Robin","Plum Sparrow","Teal Finch",
"Ruby Wren","Peach Canary","Cobalt Swift","Honey Lark","Lilac Thrush",
"Pine Robin","Cherry Finch","Saffron Sparrow","Cloud Warbler","Neon Tit",
"Peacock Swift","Grape Finch","Frost Lark","Tiger Wren","Flame Canary"
];
const birdStyles = birdNames.map((name, i) => makeBirdStyle(i, name));
const birdSkin = birdStyles[Math.floor(Math.random() * birdStyles.length)];
birdNameEl.textContent = `Bird: ${birdSkin.name}`;
const bird = {
x: 0,
y: 0,
vy: 0,
r: 14,
gravity: 0.42,
flap: -7.6,
maxFall: 10.5
};
let groundH = 96;
let pipeGap = 150;
let pipeSpacing = 190;
let pipeSpeed = 2.9;
let pipes = [];
let started = false;
let gameOver = false;
let score = 0;
let bestScore = Number(localStorage.getItem("flappyBest") || 0);
function resetGame() {
score = 0;
pipes = [];
bird.y = H * 0.45;
bird.vy = 0;
started = true;
gameOver = false;
scoreEl.textContent = "0";
startPanel.classList.add("hidden");
overPanel.classList.add("hidden");
const firstX = W + 140;
pipes.push(makePipe(firstX));
pipes.push(makePipe(firstX + pipeSpacing));
pipes.push(makePipe(firstX + pipeSpacing * 2));
}
function makePipe(x) {
const topMin = 50;
const topMax = Math.max(topMin + 40, H - groundH - pipeGap - 70);
const top = rand(topMin, topMax);
return {
x,
top,
bottom: top + pipeGap,
scored: false
};
}
function flap() {
if (!started || gameOver) {
resetGame();
}
bird.vy = bird.flap;
}
function collideCircleRect(cx, cy, r, rx, ry, rw, rh) {
const testX = clamp(cx, rx, rx + rw);
const testY = clamp(cy, ry, ry + rh);
const dx = cx - testX;
const dy = cy - testY;
return dx * dx + dy * dy <= r * r;
}
function drawBackground() {
const sky = ctx.createLinearGradient(0, 0, 0, H);
sky.addColorStop(0, "#70c5ce");
sky.addColorStop(1, "#d9f5ff");
ctx.fillStyle = sky;
ctx.fillRect(0, 0, W, H);
// soft clouds
ctx.globalAlpha = 0.16;
ctx.fillStyle = "#fff";
for (let i = 0; i < 5; i++) {
const x = (i * 260 + (performance.now() * 0.01)) % (W + 300) - 150;
const y = 70 + i * 38;
ctx.beginPath();
ctx.ellipse(x, y, 42, 20, 0, 0, Math.PI * 2);
ctx.ellipse(x + 30, y + 4, 34, 16, 0, 0, Math.PI * 2);
ctx.ellipse(x - 24, y + 6, 28, 14, 0, 0, Math.PI * 2);
ctx.fill();
}
ctx.globalAlpha = 1;
// ground
ctx.fillStyle = "#8ccf6d";
ctx.fillRect(0, H - groundH, W, groundH);
ctx.fillStyle = "#63b24c";
for (let x = -30; x < W + 30; x += 76) {
ctx.beginPath();
ctx.ellipse(x + 30, H - groundH + 14, 34, 12, 0, 0, Math.PI * 2);
ctx.fill();
}
}
function drawPipe(pipe) {
const pipeW = 78;
const bodyGrad = ctx.createLinearGradient(pipe.x, 0, pipe.x + pipeW, 0);
bodyGrad.addColorStop(0, "#2d8f2d");
bodyGrad.addColorStop(0.5, "#48bb48");
bodyGrad.addColorStop(1, "#1f6f1f");
const capColor = "#43c763";
ctx.fillStyle = bodyGrad;
ctx.fillRect(pipe.x, 0, pipeW, pipe.top);
ctx.fillRect(pipe.x, pipe.bottom, pipeW, H - groundH - pipe.bottom);
ctx.fillStyle = capColor;
ctx.fillRect(pipe.x - 6, pipe.top - 24, pipeW + 12, 24);
ctx.fillRect(pipe.x - 6, pipe.bottom, pipeW + 12, 24);
ctx.strokeStyle = "rgba(0,0,0,.18)";
ctx.lineWidth = 2;
ctx.strokeRect(pipe.x, 0, pipeW, pipe.top);
ctx.strokeRect(pipe.x, pipe.bottom, pipeW, H - groundH - pipe.bottom);
}
function drawBird() {
const s = birdSkin;
ctx.save();
ctx.translate(bird.x, bird.y);
const tilt = clamp(bird.vy * 0.06, -0.55, 1.0);
ctx.rotate(tilt);
// shadow
ctx.globalAlpha = 0.14;
ctx.fillStyle = "#000";
ctx.beginPath();
ctx.ellipse(2, 11, 15, 8, 0, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1;
// body
const bodyGrad = ctx.createRadialGradient(-4, -4, 4, 0, 0, 18);
bodyGrad.addColorStop(0, s.body);
bodyGrad.addColorStop(1, s.wing);
ctx.fillStyle = bodyGrad;
ctx.beginPath();
ctx.ellipse(0, 0, 15.5, 13.5, -0.08, 0, Math.PI * 2);
ctx.fill();
// belly
ctx.fillStyle = s.belly;
ctx.beginPath();
ctx.ellipse(-2, 3, 9.5, 7.2, -0.12, 0, Math.PI * 2);
ctx.fill();
// wing
ctx.fillStyle = s.wing;
ctx.beginPath();
ctx.ellipse(-2, 3, 9, 6.5, -0.7, 0, Math.PI * 2);
ctx.fill();
// pattern overlays
ctx.fillStyle = s.accent;
if (s.pattern === "stripe") {
ctx.globalAlpha = 0.55;
ctx.fillRect(-10, -2, 20, 2.5);
ctx.fillRect(-10, 2, 20, 2.5);
ctx.globalAlpha = 1;
} else if (s.pattern === "cheek") {
ctx.globalAlpha = 0.55;
ctx.beginPath();
ctx.arc(8, 4, 3.2, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1;
} else if (s.pattern === "speckle") {
ctx.globalAlpha = 0.62;
for (let i = 0; i < 5; i++) {
ctx.beginPath();
ctx.arc(-6 + i * 3, -2 + (i % 2) * 3, 1.1, 0, Math.PI * 2);
ctx.fill();
}
ctx.globalAlpha = 1;
} else if (s.pattern === "crown") {
ctx.globalAlpha = 0.75;
ctx.beginPath();
ctx.moveTo(-5, -13);
ctx.lineTo(-1, -19);
ctx.lineTo(3, -13);
ctx.lineTo(7, -18);
ctx.lineTo(11, -12);
ctx.closePath();
ctx.fill();
ctx.globalAlpha = 1;
}
// eye
ctx.fillStyle = "#fff";
ctx.beginPath();
ctx.arc(6.2, -4.8, 4.6, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = s.eye;
ctx.beginPath();
ctx.arc(7.4, -4.4, 1.8, 0, Math.PI * 2);
ctx.fill();
// beak
ctx.fillStyle = s.beak;
ctx.beginPath();
ctx.moveTo(14, -1);
ctx.lineTo(25, 3);
ctx.lineTo(14, 7);
ctx.closePath();
ctx.fill();
// tiny highlight
ctx.globalAlpha = 0.25;
ctx.fillStyle = "#fff";
ctx.beginPath();
ctx.arc(-5, -6, 3.3, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
function drawHUD() {
ctx.fillStyle = "#fff";
ctx.font = "800 32px Arial";
ctx.textAlign = "center";
ctx.shadowColor = "rgba(0,0,0,.35)";
ctx.shadowBlur = 4;
ctx.fillText(score, W / 2, 58);
ctx.shadowBlur = 0;
}
function endGame() {
gameOver = true;
started = true;
finalScoreEl.textContent = `Score: ${score}`;
bestScoreEl.textContent = `Best: ${bestScore}`;
overPanel.classList.remove("hidden");
localStorage.setItem("flappyBest", String(bestScore));
}
function update() {
requestAnimationFrame(update);
if (!started) {
drawScene();
return;
}
if (!gameOver) {
bird.vy = Math.min(bird.vy + bird.gravity, bird.maxFall);
bird.y += bird.vy;
if (pipes.length === 0 || pipes[pipes.length - 1].x < W - pipeSpacing) {
pipes.push(makePipe(W + 60));
}
for (let i = 0; i < pipes.length; i++) {
const p = pipes[i];
p.x -= pipeSpeed;
if (!p.scored && p.x + 78 < bird.x) {
p.scored = true;
score++;
scoreEl.textContent = String(score);
if (score > bestScore) bestScore = score;
}
const hitTop = collideCircleRect(bird.x, bird.y, bird.r, p.x, 0, 78, p.top);
const hitBottom = collideCircleRect(bird.x, bird.y, bird.r, p.x, p.bottom, 78, H - groundH - p.bottom);
if (hitTop || hitBottom) {
endGame();
}
}
while (pipes.length && pipes[0].x < -100) pipes.shift();
if (bird.y - bird.r < 0 || bird.y + bird.r > H - groundH) {
endGame();
}
}
drawScene();
}
function drawScene() {
drawBackground();
pipes.forEach(drawPipe);
drawBird();
drawHUD();
if (!started) {
ctx.fillStyle = "rgba(0,0,0,.10)";
ctx.fillRect(0, 0, W, H);
}
}
function handleInput(e) {
if (e && e.code === "Space") e.preventDefault();
if (!started || gameOver) {
resetGame();
}
bird.vy = bird.flap;
}
document.addEventListener("keydown", (e) => {
if (e.code === "Space") handleInput(e);
});
document.addEventListener("pointerdown", handleInput);
document.addEventListener("touchstart", (e) => {
e.preventDefault();
handleInput(e);
}, { passive: false });
window.addEventListener("resize", resize);
resize();
bird.y = H * 0.45;
scoreEl.textContent = "0";
bestScoreEl.textContent = `Best: ${bestScore}`;
birdNameEl.textContent = `Bird: ${birdSkin.name}`;
update();
</script>
</body>
</html>

Comments
Post a Comment