Making a Flash game like Plants Vs Zombies

Read all posts about "" game

As promised in fully explaining a PopCap game post, here we go with Plants Vs Zombies.

I have to say I am not a great PvZ player (shame on me), so if you notice something wrong during the series, let me know.

Defining the main structure of the game

PopCap did a great look and feel job with PvZ as defending your house from brain eater zombies has a great appeal… and all in all killing zombies is fun, as confirmed by blockbuster like Resident Evil, Left 4 Dead and Dead Rising. But this has nothing to do with the gameplay, which could be Butchers Vs Plumbers, Pigeons Vs Camels or Circles Vs Squares.

During the series, good circles will prevent evil squares to get to the base. Also, the structure of the game field can be simplified in a tile based game.

Take this situation:

And try to imagine it this way:

What we have is a plant on (2,2) ready to stop a zombie walking on row 2, another zombie approaching on row 3 and a sun falling through column 4. There can’t be another plant on (2,2), and a new zombie never appear between row 2 and 3.

Again, bow to PopCap for making you believe this was the hardest game to code.

Creation of the game field

As you can see in the above picture, the game field is a 5 rows x 9 columns matrix, so the first thing is defining an array with the same properties. I assume your fla file has a document class called Main. So this is the content of Main.as:

package {
	import flash.display.Sprite;
	public class Main extends Sprite {
		private var gameField:Array;
		public function Main():void {
			setupField();
		}
		private function setupField():void {
			gameField=new Array();
			for (var i:uint=0; i<5; i++) {
				gameField[i]=new Array();
				for (var j:uint=0; j<9; j++) {
					gameField[i][j]=0;
				}
			}
		}
	}
}

At the end of the script gameField array contains the 5x9 matrix.

Drawing the game field

This is more for a debug purpose, anyway we are going to draw the game field. I am using some rectangles drawn on the fly with drawRect method and filled with a random green.

package {
	import flash.display.Sprite;
	public class Main extends Sprite {
		private var gameField:Array;
		public function Main():void {
			setupField();
			drawField();
		}
		private function setupField():void {
			gameField=new Array();
			for (var i:uint=0; i<5; i++) {
				gameField[i]=new Array();
				for (var j:uint=0; j<9; j++) {
					gameField[i][j]=0;
				}
			}
		}
		private function drawField():void {
			var fieldSprite:Sprite=new Sprite();
			var randomGreen:Number;
			addChild(fieldSprite);
			fieldSprite.graphics.lineStyle(1,0xFFFFFF);
			for (var i:uint=0; i<5; i++) {
				for (var j:uint=0; j<9; j++) {
					randomGreen=(125+Math.floor(Math.random()*50))*256;
					fieldSprite.graphics.beginFill(randomGreen);
					fieldSprite.graphics.drawRect(25+65*j,80+75*i,65,75);
				}
			}
		}
	}
}

What drawField function does could have been done directly in setupField function, but I wanted to keep things separate for a tutorial purpose. The only interesting line is the random green color generation between #007D00 and #00AE00 at line 25.

This is our game field. If you want to draw decent tiles, let me know

Catching suns

Suns are PvZ's currency. They fall from the sky and land on a square. Picking them up, the player can buy plants.

We are using a timer event to drop a sun every five seconds. Refer to understanding AS3 Timer class if you aren't familiar with it.

At the moment suns don't fall down from the sky but just appear in a random tile. At the moment, I don't know if two suns can land on the same tile. In this example they can, but if the original game does not allow it just let me know.

When a sun is on the ground, it can be picked up by the player. A mouse event listener handles the whole process. This is the script:

package {
	import flash.display.Sprite;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.events.MouseEvent;
	public class Main extends Sprite {
		private var gameField:Array;
		private var flowersTimer:Timer=new Timer(5000);
		private var sun:sunMc;
		private var sunContainer:Sprite=new Sprite();
		public function Main():void {
			setupField();
			drawField();
			fallingSuns();
		}
		private function fallingSuns():void {
			addChild(sunContainer);
			flowersTimer.start();
			flowersTimer.addEventListener(TimerEvent.TIMER, newSun);
		}
		private function newSun(e:TimerEvent):void {
			var sunRow:uint=Math.floor(Math.random()*5);
			var sunCol:uint=Math.floor(Math.random()*9);
			sun = new sunMc();
			sunContainer.addChild(sun);
			sun.x=52+sunRow*65;
			sun.y=130+sunRow*75;
			sun.addEventListener(MouseEvent.CLICK,sunClicked);
		}
		private function sunClicked(e:MouseEvent):void {
			e.currentTarget.removeEventListener(MouseEvent.CLICK,sunClicked);
			var sunToRemove:sunMc=e.currentTarget as sunMc;
			sunContainer.removeChild(sunToRemove);
		}
		private function setupField():void {
			gameField=new Array();
			for (var i:uint=0; i<5; i++) {
				gameField[i]=new Array();
				for (var j:uint=0; j<9; j++) {
					gameField[i][j]=0;
				}
			}
		}
		private function drawField():void {
			var fieldSprite:Sprite=new Sprite();
			var randomGreen:Number;
			addChild(fieldSprite);
			fieldSprite.graphics.lineStyle(1,0xFFFFFF);
			for (var i:uint=0; i<5; i++) {
				for (var j:uint=0; j<9; j++) {
					randomGreen=(125+Math.floor(Math.random()*50))*256;
					fieldSprite.graphics.beginFill(randomGreen);
					fieldSprite.graphics.drawRect(25+65*j,80+75*i,65,75);
				}
			}
		}
	}
}

And a brief recap of the function used:

drawField: phyisically drawing the field

fallingSuns: setting up the suns to make them fall

newSun: creation of a new sun

setupField: preparing the field array

sunClicked: called when the player clicks on a sun

This is the result:

Pick up suns with the mouse.

Download the source code of the latest example. Next time, we'll add smooth animation to falling suns and we will buy our first plant.

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