In this post, we'll break down the JavaScript code from the Flappy Bird game to understand how the game works. This implementation uses HTML5 Canvas and plain JavaScript to create a simplified version of the classic Flappy Bird game.
What You Will Learn in This Tutorial
This Flappy Bird implementation uses sprites, sound effects, and smooth animations. Here's what you'll learn by studying the code:
🖼️ Asset Loading & Management
-
How to preload sprite sheets (bird, pipes, background) before the game starts.
-
Loading and playing sound effects (wing flaps, crashes, scoring).
-
Using
Image()
andAudio()
objects for smooth rendering.
🎮 Game Development Essentials
-
Sprite animation (flapping bird, scrolling background).
-
Collision detection with hitbox adjustments for pixel-perfect accuracy.
-
Game state management (start screen, gameplay, game over).
🔊 Audio Integration
-
Triggering sounds on key events (jump, collision, score).
-
Managing audio playback for a polished experience.
🔄 Game Loop Optimization
-
Smooth movement with
requestAnimationFrame()
. -
Efficient rendering to prevent lag.
1. Setting Up the Canvas
The game starts by setting up the HTML5 Canvas, where all the graphics will be rendered.
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
-
canvas
gets the game canvas element from the HTML. -
ctx
provides a 2D rendering context for drawing shapes, text, and images.
2. Game Variables Initialization
Several variables control the game state:
let birdY = 250;
let birdVelocity = 0;
let gravity = 0.5;
let pipes = [];
let score = 0;
let gameOver = false;
-
birdY
tracks the bird's vertical position. -
birdVelocity
controls how fast the bird moves up or down. -
gravity
pulls the bird downward. -
pipes
stores the positions of obstacles. -
score
keeps track of the player's points. -
gameOver
checks if the game has ended.
3. Handling User Input
The bird jumps when the player presses a key (or clicks).
document.addEventListener("keydown", () => (birdVelocity = -10));
-
When a key is pressed,
birdVelocity
is set to-10
, making the bird move upward.
4. Generating Pipes
Pipes (obstacles) are created at intervals.
function generatePipes() {
if (frames % 100 === 0) {
const gap = 150;
const pipeHeight = Math.random() * 200 + 50;
pipes.push({ x: canvas.width, topHeight: pipeHeight, gap });
}
}
-
gap
is the space between the top and bottom pipes. -
pipeHeight
randomizes the obstacle height. -
New pipes are added to the
pipes
array.
5. Updating Game State
The update()
function handles movement and collisions.
function update() {
birdVelocity += gravity;
birdY += birdVelocity;
// Check if bird hits ground or ceiling
if (birdY > canvas.height || birdY < 0) gameOver = true;
generatePipes();
// Move and check pipes
pipes.forEach((pipe, index) => {
pipe.x -= 2; // Move pipes left
// Detect collision
if (
(birdX + birdWidth > pipe.x &&
birdX < pipe.x + pipeWidth &&
(birdY < pipe.topHeight || birdY + birdHeight > pipe.topHeight + gap)) ||
birdY + birdHeight > canvas.height
) {
gameOver = true;
}
// Increase score if bird passes a pipe
if (pipe.x + pipeWidth < birdX && !pipe.passed) {
score++;
pipe.passed = true;
}
});
}
-
The bird's position updates based on velocity and gravity.
-
Pipes move left (
pipe.x -= 2
). -
Collisions are checked between the bird and pipes/ground.
-
The score increases when the bird passes a pipe.
6. Rendering the Game
The draw()
function renders the game elements.
function draw() {
ctx.fillStyle = "skyblue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw bird
ctx.fillStyle = "yellow";
ctx.fillRect(birdX, birdY, birdWidth, birdHeight);
// Draw pipes
pipes.forEach(pipe => {
ctx.fillStyle = "green";
ctx.fillRect(pipe.x, 0, pipeWidth, pipe.topHeight);
ctx.fillRect(pipe.x, pipe.topHeight + gap, pipeWidth, canvas.height);
});
// Draw score
ctx.fillStyle = "black";
ctx.font = "24px Arial";
ctx.fillText(`Score: ${score}`, 10, 30);
}
-
The background (
skyblue
) is drawn first. -
The bird (
yellow
) and pipes (green
) are rendered. -
The score is displayed in the top-left corner.
7. Game Loop
The gameLoop()
runs continuously, updating and drawing each frame.
function gameLoop() {
if (!gameOver) {
update();
draw();
requestAnimationFrame(gameLoop);
} else {
ctx.fillText("Game Over!", canvas.width / 2 - 60, canvas.height / 2);
}
}
gameLoop();
-
If the game is still running,
update()
anddraw()
are called. -
If
gameOver
istrue
, a "Game Over!" message appears.
Conclusion
This breakdown explains the core mechanics of the Flappy Bird game in JavaScript. The code uses:
-
Canvas for rendering.
-
Event listeners for player input.
-
Collision detection for game logic.
You can find the full code in the flappy-bird repository. Try modifying it, changing gravity, pipe speed, or adding new features!
Happy coding! 🚀