Flash Tutorial Links:
Play Games: HTML5 Tutorials:

How To Make Flappy Bird

Tap tap tap and help Jovia the flappy bird navigate past all the pipes!

History of Flappy Bird

A 1 hit wonder by a Vietnamese creator, Dong Ngyuen, this addictively simple-to-play, but difficult game has taken the world by storm in 2014. As controversial as it first begun, it was swiftly taken down by its creator, citing personal reasons.

Download the Game Files

The files you need to create this game can be downloaded from here.

Part 1

package {
	import flash.display.*;
	import flash.events.*;
	import flash.ui.*;
	public class FlappyBird extends MovieClip
		private var score:Number;
		private var speed:Number;
		private var pipes:Array;
		private var gotoWin, gotoLose, playerClicked:Boolean;
		public function FlappyBird()

The 3 standard packages are imported. You will almost always need display and events. As for ui, it'll be useful to import it in too.

The following variables will be used for the game. score keeps track of how many pipes the player has managed to pass through, and pipes is an array that will be used store all the names of the obstacles.

speed indicates the bird's vertical velocity. A value of 1 means the bird will be moving downwards, and -1 means the bird will be moving upwards.

gotoWin and gotoLose are standard boolean variables you'll see throughout the tutorials. Once they are set to true, the game jumps to the respective Win or Lose frames.

playerClicked is just a boolean indicator to note whether the player has clicked on the game, and if so, to move the bird upwards.

Part 2

    //All Start Functions
    public function startMenu()
        btnStartGame.addEventListener(MouseEvent.CLICK, gotoStartGame);
        btnHowToPlay.addEventListener(MouseEvent.CLICK, gotoHowToPlay);
    public function startHowToPlay()
        btnBack.addEventListener(MouseEvent.CLICK, gotoMenu);
    public function startWin()
        btnBack.addEventListener(MouseEvent.CLICK, gotoMenu);
    public function startLose()
        btnBack.addEventListener(MouseEvent.CLICK, gotoMenu);

Take a look at the ActionScript embedded in the different frames in the FLA file. You will see that in the menu labelled frame, it has a single function call to startMenu. Likewise, the win labelled frame will call startWin.

All the functions here handle those calls. We often refrain from writing codes in the FLA file so that everything can be seen in the AS file, and it helps tremendously in debugging your codes.

Basically, the function calls here only set up the codes for the buttons in that frame to make them function.

Part 3

    public function startGame()
        score = 0;
        speed = 0;
        gotoWin = false;
        gotoLose = false;
        playerClicked = false;
        pipes = new Array(	"pipe1a","pipe1b","pipe2a","pipe2b","pipe3a","pipe3b",
        stage.focus = this;

startGame is called in the frame labelled game.

This will be the heaviest start-kind-of-function as you can see. Basically, the role of this function is to kick start all the necessary variables and states in the game. At the start of the game, we call the player movieclip to play the "right" frames, which will show an animation of the bird flapping its wings. This Jovia (name of the bird) movie clip was obtained in tutorial 1, so there are some redundant frames here.

score is reset to 0 right at the start. speed is set to 0 too, and the bird will stay stationary at the start for a while before gravity pulls it down.

There is a call to setupGame, which we'll examine later.

pipes will store all the names of the pipe movieclips we have dragged onto the stage. If you want to create new pipes, do remember to amend this pipes array as well.

The game loop is created in the game by adding an event listener that listens to the ENTER_FRAME event. So, if you set the fps of the game to 30, this update function will run 30 times a second (assuming the computer is able to handle the complexity of each game loop).

We also add event listeners to listen to the key down event, which will be triggered when you click anywhere on the stage.

What "stage.focus = this" does is to set the focus back into the game. When you clicked on a button to get from the Menu frame into the game, the focus is actually given to the button. Hence, if the game is played using the keys on the keyboard, they will not work unless you click on the game screen again to give it focus. You can try commenting this off to see what I mean.

Part 4

//All Goto Functions
private function gotoStartGame(evt:MouseEvent)
    btnStartGame.removeEventListener(MouseEvent.CLICK, gotoStartGame);
    btnHowToPlay.removeEventListener(MouseEvent.CLICK, gotoHowToPlay);

private function gotoHowToPlay(evt:MouseEvent)
    btnStartGame.removeEventListener(MouseEvent.CLICK, gotoStartGame);
    btnHowToPlay.removeEventListener(MouseEvent.CLICK, gotoHowToPlay);

private function gotoMenu(evt:MouseEvent)
    btnBack.removeEventListener(MouseEvent.CLICK, gotoMenu);

These functions handle the interaction when the player clicks on the buttons in the menu, how to play section, etc.

Before it jumps to the right frame, it removes the event listener from the button first. This is just good programming practice.

Part 5

private function clicked(evt:MouseEvent)
        playerClicked = true;

The only input to the game is through a tap, simulated here with a mouse click. When that happens, we just set playerClicked to be true, and the actual game logic will be handled later.

Part 6

public function update(evt:Event)
    if (gotoWin)
    else if (gotoLose)

This is how the game loop will look like. I've further broken down what the game loop should be doing by creating 3 other functions.

handleUserInput will take care of the player's inputs, be it mouse, or keyboard.

handleGameLogic will almost always be the biggest function. It handles everything from updating the player's movements, bullets' movements if any, to even more fanciful stuff like calculating advanced enemy AI.

handleDraw does little, but it is important in presenting the game states to the player by updating the UI. For example, if the player gains score, the Score textfield will be updated here to reflect the correct score.

After these 3 functions have executed, the gotoWin and gotoLose variables are checked to see if they are true. If so, the respective functions will be called, and the game will end thereafter.

Part 7

    private function handleUserInput()
        //Handle player 1 position
        if (playerClicked)
            speed = -16;	
            playerClicked = false;	

playerClicked will be set to true when the player clicks his mouse anywhere on the game stage. In that case, we set speed to be -16. Note that a negative value here makes the bird moves up. Feel free to experiment with numbers beside 16.

We also need to set playerClicked back to false after we have acted on it.

Part 8

private function handleGameLogic()
    //Update the bird position
    mcPlayer.y += speed;
    //Impose gravity
    speed += 1.4;
    //Check for collisions
    //Top and bottom walls
    if (mcPlayer.y <= 0)
        gotoLose = true;
    else if (mcPlayer.y >= 600)
        gotoLose = true;

At the start, we update the position of the bird ("mcPlayer") by adding the speed to its y position. If the speed is negative, the y position decreases, hence going up.

Then we implement a gravity to make the speed go in the positive (downwards) direction. Again, feel free to implement a different value here.

In the actual Flappy Bird, the bird will not die when it flies up into the top of the game screen. Here, for simplicity sake, I'm just going to make the bird die when it hits either the top of bottom of the game screen. The codes will then check for the player's position, either lesser than 0, or higher than 600 (which is the bottom-most pixel) and if so, setting gotoLose to be true.

Part 9

//update pipes
for (var i in pipes)
    var currPipeName = pipes[i];
    var currPipe = this[currPipeName];
    //Move the pipes
    currPipe.x -= 8;
    //Check collision with bird
    if (currPipe.hitTestPoint(mcPlayer.x, mcPlayer.y))
        gotoLose = true;
    //Add score
    if (currPipe.visible && currPipe.x <= 0)
        currPipe.visible = false;

We will then loop through the pipes array which contains all the names of the pipes (See startgame). currPipeName will store the name, and when we do var currPipe = this[currPipeName], we get the actual reference to the respective pipe movieclip.

Then, we move each of the pipes to the left. We are using a speed of -8 here; feel free to experiment with it but just ensure it is negative so that it moves to the left.

We then check the collision of the pipe with the bird by using hitTestPoint. The advantage of this is that it makes the game a little easier, as even if the edges of the bird touches the pipes, the bird will still survive. If there is a hit, again, we set gotoLose to be true, and the game will eventually end.

Otherwise, once the currPipe passes by the bird, we set it to invisible, and add a 0.5 score to the game. The reason why 0.5 is that there is always a pair of pipes, so giving 0.5 to each makes clearing each pipe obstacle worth 1 point.

Part 10

//Check for win
if (score >= 8)
    gotoWin = true;

I have only created 8 sets of pipe obstacles, so once that is cleared, the player is deemed to have won. Once you start experimenting with the codes, feel free to add more sets of pipe obstacles if you wish.


Part 11

private function handleDraw()
    //Handle display
   txtScore.text = String(score);

Typically, we use the handleDraw function to update the UI displays. In this case, we update the text field that shows the time (txtTime) and the text field that shows the lives that the player has left (txtLife).

Part 12

private function triggerGoToWin()
   removeEventListener(Event.ENTER_FRAME, update);

private function triggerGoToLose()
    removeEventListener(Event.ENTER_FRAME, update);

}//end class

The two functions triggerGoToWin and triggerGoToLose are called whenever the respective win or lose states happen. Before we jump to the win or lose frame, we must remove the game loop so the game doesn't continue running, before we jump to the correct frame.

Download the Game Files

The files you need to create this game can be downloaded from here.

The Game

Now, let's tap tap tap the bird to victory!

How To Play

Objective: Naivgate Jovia the bird past the pipes by not colliding into any of them.

Controls: Click to move Jovia the bird up

Content on this page requires a newer version of Adobe Flash Player.

Get Adobe Flash player

Flash Resources
Preloader FPS Display Sounds & Music
Keycodes Name Generator
Game Development Resources
Sprite Sheets