“Mass Attack” HTML5 game made with Phaser 3 – code optimized by Richard Davey

Read all posts about "" game
When I showed you the Phaser 3.0 prototype of Mass Attack I wasn’t able to write optimized code due to a lack of documentation so I had to make some workaround to make things work. A few minutes after I published the game, Richard Davey rewrote my prototype in a more optimized way, and since he’s the brain behind Phaser, it’s an invaluable contribution, we can say we have an official blueprint for Phaser 3 games.
Click-touch and hold to create a sphere, release to drop the sphere, watch it bounce on the balance and move it accordingly. Here is the source code, for you to study:
var MassAttack = new Phaser.Class({

    Extends: Phaser.Scene,

    initialize:

    function MassAttack (config)
    {
        Phaser.Scene.call(this, config)

        this.gameOptions = {
            maxDiameter: 1,
            ballGrowingSpeed: 0.015,
            balanceFriction: 400
        };

        this.growBall = false;
        this.canPlay = true;
        this.ball = null;
        this.balance = [];
    },

    preload: function ()
    {
        this.load.setPath('assets/');
        this.load.image('ball', 'ball.png');
        this.load.image('balance', 'balance.png');
    },

    create: function ()
    {
        for (var i = 0; i < 2; i++)
        {
            var group = this.add.group();

            group.weight = 0;
            group.saveYPosition = 0;

            var sprite = group.create(this.game.config.width / 2 * i, 240, 'balance');

            sprite.setOrigin(0, 0.5);

            this.balance.push(group);
        }

        this.input.events.on('POINTER_DOWN_EVENT', this.placeBall.bind(this));
        this.input.events.on('POINTER_UP_EVENT', this.dropBall.bind(this));
    },

    placeBall: function (event)
    {
        if (!this.growBall && this.canPlay)
        {
            var side = Math.floor(event.x / (this.game.config.width / 2));

            this.ball = this.balance[side].create(event.x, 30, 'ball');
            this.ball.setScale(0.1);
            this.ball.balance = side;

            this.growBall = true;
        }
    },

    dropBall: function ()
    {
        if (this.growBall)
        {
            this.growBall = false;
            this.canPlay = false;

            var group = this.balance[this.ball.balance];

            var ballDestination = this.game.config.height / 2 + group.saveYPosition - group.children.entries[0].height / 2 - this.ball.height * this.ball.scaleY / 2;

            this.balance[this.ball.balance].weight += (4 / 3) * Math.PI * Math.pow((this.ball.width * this.ball.scaleX / 2), 3);

            this.tweens.add({
                targets: this.ball,
                y: ballDestination,
                duration: 2000,
                ease: 'Bounce',
                onComplete: this.adjustBalances,
                onCompleteScope: this
            });
        }
    },

    adjustBalances: function ()
    {
        var weightDifference = (this.balance[0].weight - this.balance[1].weight) / this.gameOptions.balanceFriction;
        var maxDifference = this.game.config.height / 3;

        if (weightDifference > maxDifference)
        {
            weightDifference = maxDifference;
        }

        if (weightDifference < -maxDifference)
        {
            weightDifference = -maxDifference;
        }

        for (var i = 0; i < 2; i++)
        {
            var difference = -this.balance[i].saveYPosition + weightDifference - (2 * i * weightDifference);

            this.balance[i].saveYPosition += difference;

            this.tweens.add({
                targets: this.balance[i].getChildren(),
                y: '+=' + difference.toString(),
                duration: 2000,
                ease: 'Quad',
                onComplete: function ()
                {
                    this.canPlay = true;
                },
                onCompleteScope: this
            });
        }
    },

    update: function ()
    {
        if (this.growBall && this.ball.scaleX < this.gameOptions.maxDiameter)
        {
            this.ball.setScale(this.ball.scaleX + this.gameOptions.ballGrowingSpeed);
        }
    }

});

var config = {
    type: Phaser.AUTO,
    width: 320,
    height: 480,
    backgroundColor: '#222222',
    parent: 'phaser-example',
    scene: MassAttack
};

var game = new Phaser.Game(config);
While you download the source code, I would like to say “thank you” to Richard for spending his time fixing my code. Next time I will create something better.

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