Create a new folder on your system. You can name it anything, for example:
bird-game
index.htmlInside the folder, create a file named:
index.html Now copy the complete bird game code (given below) and paste it into index.html.
Make sure you paste the entire code, including <html>, <style>, and <script> sections.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Simple Bird Game</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(#4facfe, #00f2fe);
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.game-wrapper {
background: #222;
padding: 8px;
border-radius: 16px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
}
#gameCanvas {
display: block;
background: linear-gradient(#87ceeb, #e0f7ff);
border-radius: 12px;
}
.info {
text-align: center;
margin-top: 8px;
color: #f5f5f5;
font-size: 14px;
}
.info span.key {
padding: 2px 6px;
border-radius: 4px;
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.2);
font-size: 12px;
}
</style>
</head>
<body>
<div class="game-wrapper">
<canvas id="gameCanvas" width="420" height="600"></canvas>
<div class="info">
Press <span class="key">SPACE</span> / <span class="key">↑</span> or click / tap to jump
</div>
</div>
<script>
(function () {
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
// Bird properties
const bird = {
x: WIDTH * 0.25,
y: HEIGHT / 2,
radius: 14,
vy: 0,
gravity: 0.5,
jumpStrength: -8,
};
// Pipes
const pipes = [];
const PIPE_WIDTH = 70;
const PIPE_GAP = 140;
const PIPE_SPEED = 2.5;
const PIPE_INTERVAL = 180; // frames between pipes
let frameCount = 0;
let score = 0;
let bestScore = 0;
let gameState = "start"; // "start", "play", "gameover"
function resetGame() {
bird.y = HEIGHT / 2;
bird.vy = 0;
pipes.length = 0;
frameCount = 0;
score = 0;
gameState = "start";
}
function spawnPipe() {
const minGapY = 80;
const maxGapY = HEIGHT - 80;
const gapY = Math.random() * (maxGapY - minGapY) + minGapY;
pipes.push({
x: WIDTH + PIPE_WIDTH,
gapY: gapY,
passed: false,
});
}
function updateBird() {
bird.vy += bird.gravity;
bird.y += bird.vy;
// Limit fall speed
if (bird.vy > 12) bird.vy = 12;
// Prevent going off top
if (bird.y - bird.radius < 0) {
bird.y = bird.radius;
bird.vy = 0;
}
// Hit ground
if (bird.y + bird.radius > HEIGHT) {
bird.y = HEIGHT - bird.radius;
gameOver();
}
}
function updatePipes() {
for (let i = pipes.length - 1; i >= 0; i--) {
const p = pipes[i];
p.x -= PIPE_SPEED;
// Passed the bird (score)
if (!p.passed && p.x + PIPE_WIDTH < bird.x) {
p.passed = true;
score++;
if (score > bestScore) bestScore = score;
}
// Remove offscreen pipes
if (p.x + PIPE_WIDTH < 0) {
pipes.splice(i, 1);
}
}
// Spawn new pipes
if (frameCount % PIPE_INTERVAL === 0) {
spawnPipe();
}
}
function checkCollisions() {
for (const p of pipes) {
const inXRange = bird.x + bird.radius > p.x && bird.x - bird.radius < p.x + PIPE_WIDTH;
if (!inXRange) continue;
const topPipeBottom = p.gapY - PIPE_GAP / 2;
const bottomPipeTop = p.gapY + PIPE_GAP / 2;
if (bird.y - bird.radius < topPipeBottom || bird.y + bird.radius > bottomPipeTop) {
gameOver();
return;
}
}
}
function jump() {
if (gameState === "start") {
gameState = "play";
}
if (gameState === "play") {
bird.vy = bird.jumpStrength;
} else if (gameState === "gameover") {
resetGame();
}
}
function gameOver() {
if (gameState !== "gameover") {
gameState = "gameover";
}
}
function drawBackground() {
// Sky is already gradient via canvas background.
// Draw ground
const groundHeight = 80;
ctx.fillStyle = "#5c913b";
ctx.fillRect(0, HEIGHT - groundHeight, WIDTH, groundHeight);
// Ground detail
ctx.fillStyle = "#4a7a30";
for (let i = 0; i < WIDTH; i += 24) {
ctx.fillRect(i, HEIGHT - groundHeight + 40, 16, 40);
}
}
function drawPipes() {
for (const p of pipes) {
const topPipeBottom = p.gapY - PIPE_GAP / 2;
const bottomPipeTop = p.gapY + PIPE_GAP / 2;
// Pipe body
ctx.fillStyle = "#2ecc71";
// Top pipe
ctx.fillRect(p.x, 0, PIPE_WIDTH, topPipeBottom);
// Bottom pipe
ctx.fillRect(p.x, bottomPipeTop, PIPE_WIDTH, HEIGHT - bottomPipeTop);
// Pipe edges
ctx.fillStyle = "rgba(0,0,0,0.15)";
ctx.fillRect(p.x, topPipeBottom - 12, PIPE_WIDTH, 12); // top lip
ctx.fillRect(p.x, bottomPipeTop, PIPE_WIDTH, 12); // bottom lip
}
}
function drawBird() {
// Bird body
ctx.beginPath();
ctx.arc(bird.x, bird.y, bird.radius, 0, Math.PI * 2);
ctx.fillStyle = "#f1c40f";
ctx.fill();
ctx.closePath();
// Eye
ctx.beginPath();
ctx.arc(bird.x + 6, bird.y - 4, 4, 0, Math.PI * 2);
ctx.fillStyle = "#fff";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.arc(bird.x + 7, bird.y - 4, 2, 0, Math.PI * 2);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
// Beak
ctx.beginPath();
ctx.moveTo(bird.x + bird.radius, bird.y);
ctx.lineTo(bird.x + bird.radius + 10, bird.y - 4);
ctx.lineTo(bird.x + bird.radius + 10, bird.y + 4);
ctx.closePath();
ctx.fillStyle = "#e67e22";
ctx.fill();
// Wing
ctx.beginPath();
ctx.ellipse(bird.x - 4, bird.y + 2, 8, 6, 0, 0, Math.PI * 2);
ctx.fillStyle = "#f39c12";
ctx.fill();
}
function drawText() {
ctx.textAlign = "center";
// Score top center
ctx.fillStyle = "rgba(0,0,0,0.3)";
ctx.font = "bold 32px system-ui, sans-serif";
ctx.fillText(score, WIDTH / 2 + 2, 52 + 2);
ctx.fillStyle = "#ffffff";
ctx.fillText(score, WIDTH / 2, 52);
if (gameState === "start") {
ctx.font = "bold 28px system-ui, sans-serif";
ctx.fillStyle = "#ffffff";
ctx.fillText("Tap or Press SPACE to Start", WIDTH / 2, HEIGHT / 2 - 20);
ctx.font = "16px system-ui, sans-serif";
ctx.fillText("Avoid the pipes and stay in the air!", WIDTH / 2, HEIGHT / 2 + 10);
} else if (gameState === "gameover") {
// Overlay
ctx.fillStyle = "rgba(0,0,0,0.45)";
ctx.fillRect(0, 0, WIDTH, HEIGHT);
ctx.fillStyle = "#ffffff";
ctx.font = "bold 36px system-ui, sans-serif";
ctx.fillText("Game Over", WIDTH / 2, HEIGHT / 2 - 30);
ctx.font = "20px system-ui, sans-serif";
ctx.fillText("Score: " + score, WIDTH / 2, HEIGHT / 2 + 5);
ctx.fillText("Best: " + bestScore, WIDTH / 2, HEIGHT / 2 + 32);
ctx.font = "16px system-ui, sans-serif";
ctx.fillText("Click / Tap / Press SPACE to restart", WIDTH / 2, HEIGHT / 2 + 65);
}
}
function loop() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
drawBackground();
if (gameState === "play") {
frameCount++;
updateBird();
updatePipes();
checkCollisions();
}
drawPipes();
drawBird();
drawText();
requestAnimationFrame(loop);
}
// Input handlers
document.addEventListener("keydown", function (e) {
if (e.code === "Space" || e.code === "ArrowUp") {
e.preventDefault();
jump();
}
});
canvas.addEventListener("mousedown", function () {
jump();
});
canvas.addEventListener("touchstart", function (e) {
e.preventDefault();
jump();
});
// Start game
resetGame();
loop();
})();
</script>
</body>
</html>To play the game in your browser:
index.htmlYour game will open in the browser
This is a great beginner project to understand:
You can later enhance it by adding:
localStorage
I'm a dedicated full-stack developer with expertise in building and managing dynamic web applications across both frontend and backend.