Creation of a match 3 game like Farm Heroes Saga using any language – Step 3: adding tiles to stage

Read all posts about "" game

Here we are with the 3rd step of the Farm Heroes Saga creation using any language. A brief recap:

In step 1 I showed you the variable and constants to use to create the game field, while in step 2 we discussed about the functions to use in order to populate the game field.

Now it’s time to see some action, and we are going to draw the game field using two popular HTML5 game frameworks, Phaser and Panda.

We are doing this with mobile development in mind, so we will create a 320×480 game which scales to fit the browser area.

Here it is what we are going to do:

Phaser 320×480 game scaled to 360×540 Panda 320×480 game scaled to 360×540

Since all game logic functions have already been defined, let’s jump straight to source code and see the interesting lines of both versions. Just keep in mind we will need three more constants:

TILESIZE: size of the tile, in pixels. We assume tiles have their registration point in the upper left corner

OFFSETX: horizontal distance from the upper left corner to the upper left corner of the first tile, in pixels

OFFSETY: vertical distance from the upper left corner to the upper left corner of the first tile, in pixels

We aare using the offsets to place our tiles anywhere on the game field. You may say I could create a layer and just position the layer with all tiles inside, but working with single offsets should assure more cross-language compatibility.

Source codes now:

PHASER

Phaser version uses a single file for everything:

<!doctype html>
<html>
	<head>
    		<script src="phaser.min.js"></script>
    		<style>
    			body{margin:0}
    		</style>
    		<script type="text/javascript">
    		
			window.onload = function() {
			
				function rowNumber(i){
			     	return Math.floor(i/FIELDSIZE);
				}
				 
				function colNumber(i){
				     return i%FIELDSIZE;
				}
				 
				function isHorizontalMatch(i){
				     return colNumber(i)>=2 && gameArray[i]==gameArray[i-1] && gameArray[i] == gameArray[i-2] && rowNumber(i)==rowNumber(i-2);
				}
				 
				function isVerticalMatch(i){
				     return rowNumber(i)>=2 && gameArray[i]==gameArray[i-FIELDSIZE] && gameArray[i] == gameArray[i-2*FIELDSIZE];
				}
				
				function createLevel(){
					for(i=0;i<FIELDSIZE*FIELDSIZE;i++){
					     do{
					          gameArray[i]=Math.ceil(Math.random()*TILETYPES);
					     }while (isHorizontalMatch(i) || isVerticalMatch(i));
					} 
				}
				
				function drawLevel(){
					for(i=0;i<FIELDSIZE*FIELDSIZE;i++){
						var tile = gameArray[i];
						var item = game.add.sprite(i%FIELDSIZE*TILESIZE+OFFSETX,Math.floor(i/FIELDSIZE)*TILESIZE+OFFSETY,"tile"+tile);    
					}
				}
			
				var game = new Phaser.Game(320,480,Phaser.CANVAS,"",{
					preload:onPreload,
					create:onCreate,
					update:onUpdate
				});
				
				var FIELDSIZE = 8;
				var TILETYPES = 8;
				var TILESIZE = 36;
				var OFFSETX = 16;
				var OFFSETY = 50;
				var gameArray = new Array(FIELDSIZE*FIELDSIZE);
            		
				function onPreload() {
					for(i=1;i<=TILETYPES;i++){
						game.load.image("tile"+i, "tile_"+i+".png");
					}
					createLevel();
				}
				
				function onCreate() {
					drawLevel();
					game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
					game.scale.setScreenSize();
				}
				
				function onUpdate() {
	    			}
	    		};
		</script>
    </head>
    <body>
    </body>
</html>

Lines 36-41: function drawLevel, which places items on the stage

Lines 43-47: configuring the game, setting its resolution and the functions to be called. At the moment onUpdate does not do anything, but we’ll find it useful next time

Lines 57-59: loading graphic assets

Lines 65-66: setting game scale mode

PANDA

Panda needs to edit both config and game files.

config.js

pandaConfig = {
    system: {
        rotateImg: "rotate.png",
        bgColor: "#000000",
        orientation: "portrait",
        width: 320,
        height: 480,
        scaleToFit:true
    },
    loader: {
        logo: "data:image/png;base64,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",
        logoTween: true
    }
};

Lines 5-8: defining game resolution and scaling

main.js

game.module(
     "game.main"
)
.body(function() {

     function rowNumber(i){
     	return Math.floor(i/FIELDSIZE);
     }
      
     function colNumber(i){
          return i%FIELDSIZE;
     }
      
     function isHorizontalMatch(i){
          return colNumber(i)>=2 && gameArray[i]==gameArray[i-1] && gameArray[i] == gameArray[i-2] && rowNumber(i)==rowNumber(i-2);
     }
      
     function isVerticalMatch(i){
          return rowNumber(i)>=2 && gameArray[i]==gameArray[i-FIELDSIZE] && gameArray[i] == gameArray[i-2*FIELDSIZE];
     }
     
     function createLevel(){
     	for(i=0;i<FIELDSIZE*FIELDSIZE;i++){
     	     do{
     	          gameArray[i]=Math.ceil(Math.random()*TILETYPES);
     	     }while (isHorizontalMatch(i) || isVerticalMatch(i));
     	} 
     }
     
     function drawLevel(){
     	for(i=0;i<FIELDSIZE*FIELDSIZE;i++){
     		var tile = gameArray[i];
     		var item = new game.Sprite("tile"+tile);
               item.position.set(i%FIELDSIZE*TILESIZE+OFFSETX,Math.floor(i/FIELDSIZE)*TILESIZE+OFFSETY);
               game.scene.stage.addChild(item);                        
     	}                                  
     }

     var FIELDSIZE = 8;
     var TILETYPES = 8;
     var TILESIZE = 36;
     var OFFSETX = 16;
     var OFFSETY = 50;
     var gameArray = new Array(FIELDSIZE*FIELDSIZE);

     for(i=1;i<=TILETYPES;i++){
     	game.addAsset("tile_"+i+".png","tile"+i);
     }

     createLevel();

     SceneGame = game.Scene.extend({
          backgroundColor: 0x000000,
          init: function() {
               console.log(gameArray);
               drawLevel();
          }
     });
     game.start();
});

Lines 30-37: function drawLevel, which places items on the stage

Lines 46-48: loading graphic assets

The rest of both scripts are just plain JavaSCript functions I explained in step 2. Things will get interesting when we’ll start to add user interaction, selecting items to swap, but we’ll see it next time, 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