Create a flash artillery game – step 2

Read all posts about "" game

Welcome to the 2nd part of this tutorial. I recommend you to read the 1st part if you haven’t done it yet and we are ready to start.

Fixing bullets amount

In the last example, when you shot a bullet, it “lives” forever. I mean, once the bullet movieclip is on the stage, there isn’t any routine to check if the bullet should exist or not.

Try to imagine thousands of bullets that continue falling down at increasing speed. Obviously, if you fire a large amount of bullets, the movieclip starts lagging.

We need to remove bullets when they are off the stage.

Mouse.hide();
gravity = 2;
attachMovie("crosshair", "crosshair", 1);
attachMovie("tank", "tank", 2, {_x:230, _y:350});
crosshair.onEnterFrame = function() {
	this._x = _xmouse;
	this._y = _ymouse;
};
tank.onEnterFrame = function() {
	mousex = _xmouse-this._x;
	mousey = (_ymouse-this._y)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	if (angle>160) {
		angle = 160;
	}
	if (angle<20) {
		angle = 20;
	}
	firepower = Math.sqrt(mousex*mousex+mousey*mousey);
	if (firepower>200) {
		firepower = 200;
	}
	this.cannon._rotation = angle*-1;
};
function onMouseDown() {
	angle = tank.cannon._rotation-1;
	start_ball_x = tank._x+48*Math.cos(angle*Math.PI/180);
	start_ball_y = tank._y+48*Math.sin(angle*Math.PI/180);
	cannonball_fired = attachMovie("cannonball", "cannonball_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:start_ball_x, _y:start_ball_y});
	cannonball_fired.dirx = Math.cos(angle*Math.PI/180)*firepower;
	cannonball_fired.diry = Math.sin(angle*Math.PI/180)*firepower;
	cannonball_fired.onEnterFrame = function() {
		this.diry += gravity;
		this._x += this.dirx/30;
		this._y += this.diry/30;
		if ((this._x<0) or (this._x>500) or (this._y>350)) {
			this.removeMovieClip();
		}
	};
}

Lines 42-44: Check if the bullet if out of visible left, right and bottom area (I did not include the top because a bullet is supposed to fall down…) and if true, removes the bullet movieclip.

In this case, the only movieclips active are those visible on stage plus the ones falling from the upper edge of the stage.

Maximum bullets at the same time

Now we need to put a limit to the maximum bullets fired at the same time. It would be too easy if we let the player fire a large amount of bullets. So we are going to put a limit.

Mouse.hide();
gravity = 2;
fired = 0;
max_firepower = 3;
attachMovie("crosshair", "crosshair", 1);
attachMovie("tank", "tank", 2, {_x:230, _y:350});
crosshair.onEnterFrame = function() {
	this._x = _xmouse;
	this._y = _ymouse;
};
tank.onEnterFrame = function() {
	mousex = _xmouse-this._x;
	mousey = (_ymouse-this._y)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	if (angle>160) {
		angle = 160;
	}
	if (angle<20) {
		angle = 20;
	}
	firepower = Math.sqrt(mousex*mousex+mousey*mousey);
	if (firepower>200) {
		firepower = 200;
	}
	this.cannon._rotation = angle*-1;
};
function onMouseDown() {
	if (fired350) {
				this.removeMovieClip();
				fired--;
			}
		};
	}
}

Line 3: Variable designed to count the bullets currently on stage

Line 4: Maximum firepower allowed. Changing this value you will change the maximum bullets allowed to be shot at the same time. Changing this value will affect gameplay.

Line 34: When the player wants to fire, I check if the bullets on stage are minor than the maximum bullets allowrd

Line 35: if true, increases the fired variable

Line 48: decreases the fired variable when a bullet is removed. If you look at line 46, you will see the control is performed only on bullets leaving the stage to the bottom. This will always happen even for bullets thare are leaving to left or right, since when they fall, sooner or later they will leave to the bottom. This will make the game a little bit harder, because if you fire a bullet out to the right, you will have to wait for it to leave the stage to the bottom to have the bullet reloaded.

Now it’s time to introduce the other great star in an artillery game

The ground

I created a new movieclip linkaged as ground that represents… well… the ground.

Mouse.hide();
gravity = 2;
fired = 0;
max_firepower = 3;
attachMovie("crosshair", "crosshair", 1);
attachMovie("tank", "tank", 2, {_x:295, _y:255});
attachMovie("ground", "ground", 3, {_x:0, _y:200});
crosshair.onEnterFrame = function() {
	this._x = _xmouse;
	this._y = _ymouse;
};
tank.onEnterFrame = function() {
	mousex = _xmouse-this._x;
	mousey = (_ymouse-this._y)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	if (angle>160) {
		angle = 160;
	}
	if (angle<20) {
		angle = 20;
	}
	firepower = Math.sqrt(mousex*mousex+mousey*mousey);
	if (firepower>200) {
		firepower = 200;
	}
	this.cannon._rotation = angle*-1;
};
function onMouseDown() {
	if (fired350) or (ground.hitTest(this._x, this._y, true))) {
				this.removeMovieClip();
				fired--;
			}
		};
	}
}

Lines 6-7: Tank and ground are placed on the stage as if the tank were on the ground (of course…)

Line 47: the test to remove the bullet is extended to its collision with the ground. At the moment, I do not care about explosions or accurate hit test

The enemy

In an artillery game, you are supposed to shot to an enemy… so I linkaged another movieclip as enemy… it should be that red square (you know, red squares are evil).

Mouse.hide();
gravity = 2;
fired = 0;
max_firepower = 3;
place_enemy();
attachMovie("crosshair", "crosshair", 1);
attachMovie("tank", "tank", 2, {_x:295, _y:255});
attachMovie("ground", "ground", 3, {_x:0, _y:200});
crosshair.onEnterFrame = function() {
	this._x = _xmouse;
	this._y = _ymouse;
};
tank.onEnterFrame = function() {
	mousex = _xmouse-this._x;
	mousey = (_ymouse-this._y)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	if (angle>160) {
		angle = 160;
	}
	if (angle<20) {
		angle = 20;
	}
	firepower = Math.sqrt(mousex*mousex+mousey*mousey);
	if (firepower>200) {
		firepower = 200;
	}
	this.cannon._rotation = angle*-1;
};
function onMouseDown() {
	if (fired350) or (ground.hitTest(this._x, this._y, true))) {
				this.removeMovieClip();
				fired--;
			}
		};
	}
}
function place_enemy() {
	enemy_placed = attachMovie("enemy", "enemy", _root.getNextHighestDepth(), {_x:0, _y:350});
	enemy_placed.yspeed = 0;
	enemy_placed.onEnterFrame = function() {
		this.yspeed += gravity/10;
		this._x++;
		while (_root.ground.hitTest(this._x+this._width/2, this._y+this._height, true)) {
			this._y--;
			this.yspeed = 0;
		}
		if (!_root.ground.hitTest(this._x+this._width/2, this._y+this._height+1, true)) {
			this._y += this.yspeed;
		} else {
			this.yspeed = 0;
		}
		if (this._x>500) {
			this.removeMovieClip();
			place_enemy();
		}
	};
}

Line 5: call to a place_enemy function that will… uh… something like placing an enemy…

Line 55: here starts the function place_enemy

Line 56: Placing an enemy in the bottom left of the stage

Line 57: Init enemy yspeed at zero. It’s obvious that I won’t move the enemy with a motion guide but with pure actionscript, just in case tomorrow I would like to change the terrain. I am using some of the basics explained in the tutorial called Create a flash draw game like Line Rider or others – part 5 so give it a look if you haven’t done it yet.

Line 58: Function to be executed every time the enemy enters in a frame.

Lines 59-69: As said, these are lines already explained in the the tutorial called Create a flash draw game like Line Rider or others – part 5

Lines 70-73: When the enemy reaches the right border, I remove it and call the function again, creating another enemy.

And we have our walking enemy… want to hurt it?

The killable enemy

In this tutorial I won’t cover energy, health and so on, but I will during next tuts. At the moment, when a bullet hits an enemy, he/it dies and repops in the starting point.

Mouse.hide();
gravity = 2;
fired = 0;
max_firepower = 3;
place_enemy();
attachMovie("crosshair", "crosshair", 1);
attachMovie("tank", "tank", 2, {_x:295, _y:255});
attachMovie("ground", "ground", 3, {_x:0, _y:200});
crosshair.onEnterFrame = function() {
	this._x = _xmouse;
	this._y = _ymouse;
};
tank.onEnterFrame = function() {
	mousex = _xmouse-this._x;
	mousey = (_ymouse-this._y)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	if (angle>160) {
		angle = 160;
	}
	if (angle<20) {
		angle = 20;
	}
	firepower = Math.sqrt(mousex*mousex+mousey*mousey);
	if (firepower>200) {
		firepower = 200;
	}
	this.cannon._rotation = angle*-1;
};
function onMouseDown() {
	if (fired350) or (ground.hitTest(this._x, this._y, true))) {
				this.removeMovieClip();
				fired--;
			}
			if (enemy.hitTest(this._x, this._y, true)) {
				this.removeMovieClip();
				enemy.removeMovieClip();
				fired--;
				place_enemy();
			}
		};
	}
}
function place_enemy() {
	enemy_placed = attachMovie("enemy", "enemy", _root.getNextHighestDepth(), {_x:0, _y:350});
	enemy_placed.yspeed = 0;
	enemy_placed.onEnterFrame = function() {
		this.yspeed += gravity/10;
		this._x++;
		while (_root.ground.hitTest(this._x+this._width/2, this._y+this._height, true)) {
			this._y--;
			this.yspeed = 0;
		}
		if (!_root.ground.hitTest(this._x+this._width/2, this._y+this._height+1, true)) {
			this._y += this.yspeed;
		} else {
			this.yspeed = 0;
		}
		if (this._x>500) {
			this.removeMovieClip();
			place_enemy();
		}
	};
}

Lines 52-57: if a bullet hits THE enemy (I will explain that bold “the” later), I remove both the bullet (decreasing the fired variable) and the enemy and place another enemy.

It’s very simple, but I wrote that “the” because I know that A bullet on the stage can hit only THE only enemy on the stage.

When we’ll have lots of bullet that can hit lots of targets, it gets a bit more complicated.

That’s what I’ll cover during next step, coming soon.

Meanwhile, download the sources and give me feedback.

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