Create the HTML5 engine behind iOS hit Memdot with Phaser

Read all posts about "" game
Did you play Memdot by Appsolute Games, the same team behind Dashy Panda game I already explained? It’s a tiny free iOSgame which has been featured on the app store. Some colored circles enter the stage in a fancy way. The the stage fades out to a random color and circles disappear. You have to touch all circles with the same color as stage color. Easier to play than to explain, as usual. memdot This game is also perfect to start a new tutorial series, we will see how to create the engine which manages circles entering the stage, background color fading in, and you selecting the circle (or the circles) matching background color. Again, it’s way simpler playing than explaining, to test it you may need to reload the game and focus the canvas:
Once the circles disappear, touch the circles with the same color of the background to make them disappear, if you fail you will see the actual color of the circle. I used a lot of ArrayUtils methods to populate arrays with circles positions and colors then randomly draw and remove them from the array. You will find ArrayUtils very useful, as you can see the full commented source code:
// the game
var game;

// size of each tile, in pixels
var gridSize = 40;

// colors to be used in game
var colorsInGame = [0xff0000, 0xff8800, 0x00ff00, 0x0000ff, 0xff00ff, 0x555555];

// how many circles in game?
var circlesInGame = 3;

// creation of the game
window.onload = function() {	
	game = new Phaser.Game(320, 480);
     game.state.add("PlayGame", playGame);
     game.state.start("PlayGame");
}


var playGame = function(game){}

playGame.prototype = {
     preload: function(){
          
          // preloading the assets
          game.load.spritesheet("circles", "circles.png", gridSize, gridSize);
          game.load.image("background", "background.png");          
     },
     create: function(){
          
          // set background color to white                                                                                     
          game.stage.backgroundColor = "#ffffff";
          
          // adding a group containing all circles
          this.circleGroup = game.add.group();
          
          // possibleColors will contain the same items as colorsInGame array,
          // just repeated (circlesInGame - 1) times.
          // we want to have more circles with the same color, but not ALL circle with the same color
           this.possibleColors = [];
          for(var i = 0; i < colorsInGame.length; i++){
               for(var j = 0; j < circlesInGame - 1; j++){
                    this.possibleColors.push(colorsInGame[i])     
               } 
          }
          
          // boardWidth and boardHeight will determine the width and height of the game board,
          // according to game size and grid size.
          // we subtract 2 from both boardWidth and boardHeight because we don't want
          // tiles to be at the very edge of the canvas
          var boardWidth = game.width / gridSize - 2;
          var boardHeight = game.height / gridSize - 2;
          
          // creation of an array with all possible grid positions
          this.positionsArray = [];
          for(var i = 0; i < (boardWidth) * (boardHeight); i++){
               this.positionsArray.push(i);     
          }
          
          // pickedColors is the array which will contain all colors actually used in this game
          this.pickedColors = [];
          
          // repeating this loop circlesInGame times
          for(var i = 0; i < circlesInGame; i++){
               
               // choosing a random position for the circle.
               // this position won't be available anymore as we remove it from positionsArray 
               var randomPosition = Phaser.ArrayUtils.removeRandomItem(this.positionsArray);              
               
               // determining circle x and y position in pixels
               var posX = (1 + randomPosition % (boardWidth)) * gridSize;
               var posY = (1 + Math.floor(randomPosition / boardWidth)) * gridSize;
               
               // creating the circle as a button which calls circleSelected function
               var circle = game.add.button(posX, posY, "circles", this.circleSelected, this);
               
               // adding the circle to circleGroup group 
               this.circleGroup.add(circle);
               
               // tinting the circle with a possible color and removing the color
               // from the array of possible colors.
               // we also save its tint color in a property called tintColor
               circle.tintColor = Phaser.ArrayUtils.removeRandomItem(this.possibleColors)
               circle.tint = circle.tintColor;
               
               // adding the tint color to pickedColors array, if not already in the array
               if(this.pickedColors.indexOf(circle.tint) == -1){
                    this.pickedColors.push(circle.tint);     
               }
               
               // choosima a random direction: 1 = left, 2 = up, 3 = right, 4 = down
               var randomDirection = game.rnd.integerInRange(1, 4);
               
               // a temporary object which will be used to handle circle tween
               var tweenObject = {};
               
               // according to random direction...
               switch(randomDirection){
                    case 1:
                         // left: circle is placed just outside left border and the tween
                         // will bring it to its initial x position
                         circle.x = - gridSize;
                         tweenObject.x = posX;
                         break;
                    case 2:
                         // up: circle is placed just outside upper border and the tween
                         // will bring it to its initial y position
                         circle.y = - gridSize;
                         tweenObject.y = posY;
                         break;
                    case 3:
                         // left: circle is placed just outside right border and the tween
                         // will bring it to its initial x position
                         circle.x = game.width + gridSize;
                         tweenObject.x = posX;
                         break;
                    case 4:
                         // left: circle is placed just outside bottom border and the tween
                         // will bring it to its initial y position
                         circle.y = game.height + gridSize;
                         tweenObject.y = posY;
                         break;
               }
               
               // adding the tween to circle. This will create the "enter in the stage" effect
               game.add.tween(circle).to(tweenObject, 500, Phaser.Easing.Cubic.Out, true);     
          }
          
          // after two seconds, let's cover the screen
          game.time.events.add(Phaser.Timer.SECOND * 2, this.fadeOut, this);
          
            
     },
     
     // this function will cover the screen with a random color
     fadeOut: function(){
     
          // filling the entire canvas with a tile sprite
          this.cover = game.add.tileSprite(0, 0, game.width, game.height, "background");
          
          // giving the cover a tint color picked among circle colors 
          this.cover.tint = Phaser.ArrayUtils.getRandomItem(this.pickedColors);
          
          // setting the cover to transparent
          this.cover.alpha = 0;
          
          // tweening the cover to fully opaque
          var coverTween = game.add.tween(this.cover).to({
               alpha: 1
          }, 200, Phaser.Easing.Linear.None, true);   
          
          // once the cover is fully opaque...
          coverTween.onComplete.add(function(){
          
               // bring to top circleGroup as it was hidden by the cover
               game.world.bringToTop(this.circleGroup);
               
               // for each circle in circleGroup group...
               this.circleGroup.forEach(function(item){
               
                    // tinting it white
                    item.tint = 0xffffff;
                    
                    // setting it to frame 1 to show just a white ring
                    item.frame = 1;
               })
          }, this)       
     },
     
     // this function will be called each time a circle is touched
     // b is the circle
     circleSelected: function(b){
     
          // if the screen is already fully covered...
          if(this.cover != undefined &amp;&amp; this.cover.alpha == 1){
               
               // if the circle has the same tint color of the cover...
               // (we use tintColor property we previously saved, because circle tint color now is white)
               if(b.tintColor == this.cover.tint){
                    // then destrot it
                    b.destroy();
               }
               else{
                    // if not, show the actual color of the circle
                    b.tint = b.tintColor
                    b.frame = 0;
               }
          }
     }
}
Next time I will show you how to create a full working game, meanwhile download the source code and obviously play the original game.

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

214 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
// 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