HTML5 “Flappy Bird” prototype updated to Phaser 2.10.1 with more room for customization

Read all posts about "" game

While Phaser 3 is becoming more and more stable, there’s still a lot to do and learn with Phaser 2, especially if you have games developed with Phaser 2 and want to keep them up to date or port to Phaser 3.

I made a Flappy Bird prototype about three years ago and it’s time to update it to the latest Phaser 2 version before showing you how to port to Phaser 3 line by line.

Also, I added some more room for customization and I not destroy any sprite during the game, I only recycle them saving memory and improving performance.

Have a look at the prototype:

Use the mouse to flap.

Now, let me show you the source code, still uncommented but rather easy to read, with a lot of customizable options:

var game;

var gameOptions = {

    // bird gravity, will make bird fall if you don't flap
    birdGravity: 800,

    // horizontal bird speed
    birdSpeed: 125,

    // flap thrust
    birdFlapPower: 300,

    // minimum pipe height, in pixels. Affects hole position
    minPipeHeight: 50,

    // distance range from next pipe, in pixels
    pipeDistance: [220, 280],

    // hole range between pipes, in pixels
    pipeHole: [100, 130],

    // local storage object name
    localStorageName: "bestFlappyScore"
}

window.onload = function() {
    game = new Phaser.Game(320, 480, Phaser.CANVAS);
    game.state.add("Play", play, true);
}

var play = function(){}
play.prototype = {
    preload:function(){
        game.load.image("bird", "bird.png");
        game.load.image("pipe", "pipe.png");
    },
    create:function(){
        game.stage.backgroundColor = "#87CEEB";
        game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
        game.scale.pageAlignHorizontally = true;
        game.scale.pageAlignVertically = true;
        game.stage.disableVisibilityChange = true;
        game.physics.startSystem(Phaser.Physics.ARCADE);
        this.pipeGroup = game.add.group();
        this.score = 0;
        this.topScore = localStorage.getItem(gameOptions.localStorageName) == null ? 0 : localStorage.getItem(gameOptions.localStorageName);
        this.scoreText = game.add.text(10, 10, "-", {
            font:"bold 16px Arial"
        });
        this.updateScore(0);
        this.bird = game.add.sprite(80, 240, "bird");
        this.bird.anchor.set(0.5);
        game.physics.arcade.enable(this.bird);
        this.bird.body.gravity.y = gameOptions.birdGravity;
        game.input.onDown.add(this.flap, this);
        var pipePosition = game.width
        do{
            this.addPipe(pipePosition);
            pipePosition += game.rnd.between(gameOptions.pipeDistance[0], gameOptions.pipeDistance[1]);
        } while(pipePosition < game.width * 4);
    },
    update:function(){
        game.physics.arcade.collide(this.bird, this.pipeGroup, this.die, null, this);
        if(this.bird.y > game.height || this.bird.y < 0){
            this.die();
        }
    },
    updateScore: function(inc){
        this.score += inc;
        this.scoreText.text = "Score: " + this.score + "\nBest: " + this.topScore;
    },
    flap: function(){
        this.bird.body.velocity.y = -gameOptions.birdFlapPower;
    },
    die: function(){
        localStorage.setItem(gameOptions.localStorageName, Math.max(this.score, this.topScore));
        game.state.start("Play");
	},
    addPipe: function(posX){
        var pipeHoleHeight = game.rnd.between(gameOptions.pipeHole[0], gameOptions.pipeHole[1]);
        var pipeHolePosition = game.rnd.between(gameOptions.minPipeHeight + pipeHoleHeight / 2, game.height - gameOptions.minPipeHeight - pipeHoleHeight / 2);
        var upperPipe = new Pipe(game, posX, pipeHolePosition - pipeHoleHeight / 2, -gameOptions.birdSpeed);
        game.add.existing(upperPipe);
        upperPipe.anchor.set(0.5, 1);
        this.pipeGroup.add(upperPipe);
        var lowerPipe = new Pipe(game, posX, pipeHolePosition + pipeHoleHeight / 2, -gameOptions.birdSpeed);
        game.add.existing(lowerPipe);
        lowerPipe.anchor.set(0.5, 0);
        this.pipeGroup.add(lowerPipe);
    }
}

Pipe = function (game, x, y, speed) {
    Phaser.Sprite.call(this, game, x, y, "pipe");
    game.physics.enable(this, Phaser.Physics.ARCADE);
    this.body.velocity.x = speed;
    this.giveScore = true;
};

Pipe.prototype = Object.create(Phaser.Sprite.prototype);
Pipe.prototype.constructor = Pipe;

Pipe.prototype.update = function() {
    if(this.x + this.width < game.state.states[game.state.current].bird.x && this.giveScore){
        game.state.states[game.state.current].updateScore(0.5);
        this.giveScore = false;
    }
    if(this.x < -this.width){
        this.giveScore = true;
        game.state.states[game.state.current].pipeGroup.sort("x", Phaser.Group.SORT_DESCENDING);
        if(game.state.states[game.state.current].pipeGroup.getChildAt(0).x == game.state.states[game.state.current].pipeGroup.getChildAt(1).x){
            this.x = game.state.states[game.state.current].pipeGroup.getChildAt(0).x + game.rnd.between(gameOptions.pipeDistance[0], gameOptions.pipeDistance[1]);
        }
        else{
            this.x = game.state.states[game.state.current].pipeGroup.getChildAt(0).x;
        }
	}
};

The game is managed by ARCADE physics, and during next days you will see it improved and ported to Phaser3, meanwhile download the source code.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers