Flappy Bird Game | A Game Similar to Flappy Bird

 

flappy bird game, games 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

Popular posts from this blog

Loan & EMI Calculator | Plan Your Repayments with Confidence

The Hidden Cost of Avoiding Hard Decisions

The Gold Mine in Every Conversation