├── sfx_die.wav
├── sfx_hit.wav
├── sfx_wing.wav
├── toppipe.png
├── bgm_mario.mp3
├── bottompipe.png
├── flappybird.gif
├── flappybird.png
├── flappybird0.png
├── flappybird1.png
├── flappybird2.png
├── flappybird3.png
├── sfx_point.wav
├── flappybirdbg.png
├── sfx_swooshing.wav
├── flappybird.css
├── index.html
├── README.md
└── flappybird.js
/sfx_die.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/sfx_die.wav
--------------------------------------------------------------------------------
/sfx_hit.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/sfx_hit.wav
--------------------------------------------------------------------------------
/sfx_wing.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/sfx_wing.wav
--------------------------------------------------------------------------------
/toppipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/toppipe.png
--------------------------------------------------------------------------------
/bgm_mario.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/bgm_mario.mp3
--------------------------------------------------------------------------------
/bottompipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/bottompipe.png
--------------------------------------------------------------------------------
/flappybird.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/flappybird.gif
--------------------------------------------------------------------------------
/flappybird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/flappybird.png
--------------------------------------------------------------------------------
/flappybird0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/flappybird0.png
--------------------------------------------------------------------------------
/flappybird1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/flappybird1.png
--------------------------------------------------------------------------------
/flappybird2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/flappybird2.png
--------------------------------------------------------------------------------
/flappybird3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/flappybird3.png
--------------------------------------------------------------------------------
/sfx_point.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/sfx_point.wav
--------------------------------------------------------------------------------
/flappybirdbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/flappybirdbg.png
--------------------------------------------------------------------------------
/sfx_swooshing.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImKennyYip/flappy-bird/HEAD/sfx_swooshing.wav
--------------------------------------------------------------------------------
/flappybird.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family:'Courier New', Courier, monospace;
3 | text-align: center;
4 | }
5 |
6 | #board {
7 | /* background-color: skyblue; */
8 | background-image: url("./flappybirdbg.png");
9 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Flappy Bird
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Flappy Bird](https://youtu.be/jj5ADM2uywg)
2 | - Coding Tutorial: https://youtu.be/jj5ADM2uywg
3 | - Demo: https://imkennyyip.github.io/flappy-bird/
4 | - Learn how to add music/sounds: https://youtu.be/UQA5jG-yh78
5 | - Learn how to add animations: https://youtu.be/94Vw8teCElM
6 |
7 | In this tutorial, you will learn to create the flappy bird game with html, css, and javascript. Specifically, you will learn how to code the game using html5 canvas.
8 |
9 | Throughout the tutorial, you will learn how to create the game loop, add images onto the canvas, add click handlers to make the flappy bird jump, randomly generate pipes and move them across the screen, detect collisions between the flappy bird and each pipe, and add a running score.
10 |
11 | 
12 |
--------------------------------------------------------------------------------
/flappybird.js:
--------------------------------------------------------------------------------
1 |
2 | //board
3 | let board;
4 | let boardWidth = 360;
5 | let boardHeight = 640;
6 | let context;
7 |
8 | //bird
9 | let birdWidth = 34; //width/height ratio = 408/228 = 17/12
10 | let birdHeight = 24;
11 | let birdX = boardWidth/8;
12 | let birdY = boardHeight/2;
13 | let birdImg;
14 |
15 | let bird = {
16 | x : birdX,
17 | y : birdY,
18 | width : birdWidth,
19 | height : birdHeight
20 | }
21 |
22 | //pipes
23 | let pipeArray = [];
24 | let pipeWidth = 64; //width/height ratio = 384/3072 = 1/8
25 | let pipeHeight = 512;
26 | let pipeX = boardWidth;
27 | let pipeY = 0;
28 |
29 | let topPipeImg;
30 | let bottomPipeImg;
31 |
32 | //physics
33 | let velocityX = -2; //pipes moving left speed
34 | let velocityY = 0; //bird jump speed
35 | let gravity = 0.4;
36 |
37 | let gameOver = false;
38 | let score = 0;
39 |
40 | window.onload = function() {
41 | board = document.getElementById("board");
42 | board.height = boardHeight;
43 | board.width = boardWidth;
44 | context = board.getContext("2d"); //used for drawing on the board
45 |
46 | //draw flappy bird
47 | // context.fillStyle = "green";
48 | // context.fillRect(bird.x, bird.y, bird.width, bird.height);
49 |
50 | //load images
51 | birdImg = new Image();
52 | birdImg.src = "./flappybird.png";
53 | birdImg.onload = function() {
54 | context.drawImage(birdImg, bird.x, bird.y, bird.width, bird.height);
55 | }
56 |
57 | topPipeImg = new Image();
58 | topPipeImg.src = "./toppipe.png";
59 |
60 | bottomPipeImg = new Image();
61 | bottomPipeImg.src = "./bottompipe.png";
62 |
63 | requestAnimationFrame(update);
64 | setInterval(placePipes, 1500); //every 1.5 seconds
65 | document.addEventListener("keydown", moveBird);
66 | }
67 |
68 | function update() {
69 | requestAnimationFrame(update);
70 | if (gameOver) {
71 | return;
72 | }
73 | context.clearRect(0, 0, board.width, board.height);
74 |
75 | //bird
76 | velocityY += gravity;
77 | // bird.y += velocityY;
78 | bird.y = Math.max(bird.y + velocityY, 0); //apply gravity to current bird.y, limit the bird.y to top of the canvas
79 | context.drawImage(birdImg, bird.x, bird.y, bird.width, bird.height);
80 |
81 | if (bird.y > board.height) {
82 | gameOver = true;
83 | }
84 |
85 | //pipes
86 | for (let i = 0; i < pipeArray.length; i++) {
87 | let pipe = pipeArray[i];
88 | pipe.x += velocityX;
89 | context.drawImage(pipe.img, pipe.x, pipe.y, pipe.width, pipe.height);
90 |
91 | if (!pipe.passed && bird.x > pipe.x + pipe.width) {
92 | score += 0.5; //0.5 because there are 2 pipes! so 0.5*2 = 1, 1 for each set of pipes
93 | pipe.passed = true;
94 | }
95 |
96 | if (detectCollision(bird, pipe)) {
97 | gameOver = true;
98 | }
99 | }
100 |
101 | //clear pipes
102 | while (pipeArray.length > 0 && pipeArray[0].x < -pipeWidth) {
103 | pipeArray.shift(); //removes first element from the array
104 | }
105 |
106 | //score
107 | context.fillStyle = "white";
108 | context.font="45px sans-serif";
109 | context.fillText(score, 5, 45);
110 |
111 | if (gameOver) {
112 | context.fillText("GAME OVER", 5, 90);
113 | }
114 | }
115 |
116 | function placePipes() {
117 | if (gameOver) {
118 | return;
119 | }
120 |
121 | //(0-1) * pipeHeight/2.
122 | // 0 -> -128 (pipeHeight/4)
123 | // 1 -> -128 - 256 (pipeHeight/4 - pipeHeight/2) = -3/4 pipeHeight
124 | let randomPipeY = pipeY - pipeHeight/4 - Math.random()*(pipeHeight/2);
125 | let openingSpace = board.height/4;
126 |
127 | let topPipe = {
128 | img : topPipeImg,
129 | x : pipeX,
130 | y : randomPipeY,
131 | width : pipeWidth,
132 | height : pipeHeight,
133 | passed : false
134 | }
135 | pipeArray.push(topPipe);
136 |
137 | let bottomPipe = {
138 | img : bottomPipeImg,
139 | x : pipeX,
140 | y : randomPipeY + pipeHeight + openingSpace,
141 | width : pipeWidth,
142 | height : pipeHeight,
143 | passed : false
144 | }
145 | pipeArray.push(bottomPipe);
146 | }
147 |
148 | function moveBird(e) {
149 | if (e.code == "Space" || e.code == "ArrowUp" || e.code == "KeyX") {
150 | //jump
151 | velocityY = -6;
152 |
153 | //reset game
154 | if (gameOver) {
155 | bird.y = birdY;
156 | pipeArray = [];
157 | score = 0;
158 | gameOver = false;
159 | }
160 | }
161 | }
162 |
163 | function detectCollision(a, b) {
164 | return a.x < b.x + b.width && //a's top left corner doesn't reach b's top right corner
165 | a.x + a.width > b.x && //a's top right corner passes b's top left corner
166 | a.y < b.y + b.height && //a's top left corner doesn't reach b's bottom left corner
167 | a.y + a.height > b.y; //a's bottom left corner passes b's top left corner
168 | }
--------------------------------------------------------------------------------