Building Games with HTML5 and JavaScript has gained a lot of popularity in recent years and many Game Engines / Frameworks (List) were created.
In this article, I will show you how to build a flappy bird clone with the free and powerful Game Framework Phaser 3 in TypeScript (will compile to plain JavaScript).
To access the source code on github, download and install git from here. You also need node.js with npm, which you get here.
Start your terminal (Windows, Mac), navigate to the desired directory and clone the flappy bird repository:
git clone https://github.com/digitsensitive/phaser3-flappy-bird.git
After cloning:
npm install
to install the node_modules andnpm run dev
to start the development server and see the game.Now everything is setup and we can dive into the source code.
The core of every phaser game is your Game class, that extends the Phaser.Game class and is given a basic configuration during creation.
|
|
We can define many important game parameters in the GameConfig (f.e. game scenes, allowed input). For the sake of simplicity we will keep it very simple and clean for now.
|
|
For our Flappy Bird game we define a width (390 px) and a height (600 px). We will only have one scene (the Game Scene), allow the user to steer the bird with the keyboard and enable Arcade Physics. Of course we have to define a positive gravity in the y-direction, so that the bird will be pulled down from the sky if no flap is done. Finally we will set pixelArt to true, so that our pixel art will be sharp without any antialiasing.
After having setup our game instance and the basic game configuration we proceed to our game scene. Usually you will have multiple scenes in your games and make transitions between them. We will keep it simple with one single scene.
Each scene calls core functions according to a predefined pattern. Independent of Phaser the constructor() of each class will be called at first. Since our GameScene extends Phaser.Scene we must call super() which will execute the constructor of the base class. For now, we can simply take notice of this.
|
|
Next, we call the init()
function which is the right place to initiate
variables. In our example we will only set a variable for the score
.
|
|
After that we call the preload()
function, where we load all our assets. We
will make use of the pack function and load all the assets via a JSON File.
|
|
In the create()
function we construct all our actual Game Objects:
Last but not least we call the update()
function. This function will be called
until the scene restarts. If the bird is alive, we will move the background,
update the bird actions and check if there is a bird-pipe overlap. If the bird
is dead, we will stop all the pipe movements and restart the scene as soon as
the bird is out of the screen.
The addRowOfPipes()
function is quite interesting and worth a look.
|
|
Have a look at the lower illustration. We will loop through 10 boxes (each with a height of 60 x 60 pixels, since we scaled the 20 x 20 pixels pipe by a factor of 3) and create a hole with a height of 3 boxes. I decided to only accept a random number between 1 and 5, so that the hole will neither be at the top nor at the bottom. Depending where the hole is, we will use other pipe graphics (= since it is a spritesheet simply other frames) above and below.
The pipe class should be self-explanatory. Finally, I would like to discuss the update function of the Bird class.
|
|
If the bird angle is less than 30 degree we add 2 degrees each time. If you look at the illustration, the bird will look down more and more.
When the the player clicks the jump button (= the bird is flapping) we will add
some velocity upwards and use a tween to change to reset the angle again to -20
degrees within 150 milliseconds. As soon as the player releases the jump button,
we will set the boolean isFlapping
back to false.
Congratulations! You have reached the end of this tutorial. Thank you for reading this. If you have any questions, feel free to contact me.
For more examples have a look at my Phaser3-Typescript Repository on Github.