├── 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 | ![flappy-bird-sample](https://user-images.githubusercontent.com/78777681/219966636-72584cb3-d471-41c0-872f-62c230dccc47.png) 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 | } --------------------------------------------------------------------------------