Create Flappy Bird Clone with Javascript (no framework)

Erdoğan Bavaş
3 min readJan 3, 2021
Flappy Bird clone made with Javascript

Creating or cloning browser-based games is a very useful practice for web development enthusiasts. This time, we will be doing the famous Flappy Bird game. You can get codes of this project from this repo.

Before diving to the code section, let’s look in to the visuals we need. There can be dozens of different images used in a game. It would be inefficient to load all of them one by one, to make separate request for each of them, to allocate space in memory. Instead, we will combine all the images and include them in our game as a single image file and use it by showing the location of the image we need. For Flappy Bird, we will use this sprite image. You can also access the image from the git repository.

Let’s start coding. As usual, we start with our index.html file. We add a canvas element to our DOM tree. All our drawings will be on this canvas with javascript. With simple CSS styles, we center our canvas and give our sprite image as a background. With background-size, we ensure that the image coincides with the appropriate part.

Our javascript part start with game.js file. We will use a modular structure with 4 different module files.

  • vars: some global variables for the game
  • Bird: contains Bird class
  • Ground: contains Ground class which bird will die if it lands on it.
  • Column: contains Column class as obstacles

In our game.js file, we first take our canvas element from our DOM tree and size it according to our screen size. Since it is a game played on portrait mode, we give a maximum height and 16/9 height as width.

As the bird falls, a force of gravity is required that pulls it to the ground. We calculated this in pixel per frame units to drop the whole screen in 5 seconds and assign it to GRAVITY variable.

We assign our sprite iamge to the sprite variable to use it in all objects. We create an instance of our bird, ground and columns variables from their respective classes. Since we need to increase the score when the columns come off the screen and come alive again, we use the increaseScore function as we need to bind an event for it.

We will draw on our canvas for each frame by using setInterval. With context.clearRect, we first clean our screen. Since we provide our background with CSS, our background image will be visible even if we do clearRect. For each of our instances, we call draw method and draw on the canvas, and draw our score with fillText. Finally, we finish the setInterval by checking whether our bird touches the ground or the columns.

Bird

Our bird image has 3-frame animation. We pass the coordinates of each step to the frames variable in the constructor. You can use the Sprite Cow to find these position values on the sprite image easily. We will keep the position of the bird on the canvas in the position object variable. Finally, to scale bird’s dimension (34 * 24) according to our canvas, we compare the canvas dimensions with the background image dimensions (288 * 512) in our sprite image.

With the draw method, we recalculate the vertical position (y) for each frame and draw it on our canvas with drawImage.
By comparing the relative position values of both objects with the isTouchingGround and isTouchingColumns methods, we return true if there is a conflict and end game.

Ground

Not much different from the Bird class. Ground image in sprite is a bit longer than background image. We’ll use this to make it seem like we’re moving forward. There is a repeating pattern on every 22px. We mark every couple pixels and add it to the frames array. Other parts of this class proceed almost the same as the Bird class.

Column

In the constructor method of this class, we assign the gap between the two columns to the gap variable (25% of the canvas height). gapTopPosition specifies the vertical position of the top column. We change this value randomly in the reviveColumn method, which is called in every time a column get off the canvas so that our gap is not always in the same position.

--

--