Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Tower Defense game, Flash and Game development.

Welcome to the 2nd part of this tutorial. I recommend you to check part 1.

In this tutorial, we will place our first base, and it will start to fire.

Let’s have a look at the objects:

Tower Defense

base: it’s the base

bullet: it’s the bullet the base will shoot

cant_build: it’s the area where you can’t build a base

minion: already explained in part 1.

path: already explained in part 1.

range: it’s the firing range of the base

Now, a little actionscript all in the first frame:

base_range = 300;
can_be_placed = false;
placed = false;
attachMovie("path", "path", _root.getNextHighestDepth());
attachMovie("cant_build", "cant_build", _root.getNextHighestDepth());
attachMovie("range", "range", _root.getNextHighestDepth(), {_width:base_range, _height:base_range});
attachMovie("base", "base", _root.getNextHighestDepth());
waypoint_x = new Array(40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420);
waypoint_y = new Array(140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20);
delay = 25;
new_monster = 0;
monsters_placed = 0;
onEnterFrame = function () {
	if (monsters_placed<25) {
		new_monster++;
	}
	if (new_monster == delay) {
		monsters_placed++;
		new_monster = 0;
		min = attachMovie("minion", "minion"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:40, _y:-20});
		min.point_to_reach = 0;
		min.speed = 1;
		min.onEnterFrame = function() {
			dist_x = waypoint_x[this.point_to_reach]-this._x;
			dist_y = waypoint_y[this.point_to_reach]-this._y;
			if ((Math.abs(dist_x)+Math.abs(dist_y))<1) {
				this.point_to_reach++;
			}
			angle = Math.atan2(dist_y, dist_x);
			this._x = this._x+this.speed*Math.cos(angle);
			this._y = this._y+this.speed*Math.sin(angle);
			this._rotation = angle/Math.PI*180-90;
		};
	}
};
base.onEnterFrame = function() {
	if (!placed) {
		this._x = _root._xmouse;
		this._y = _root._ymouse;
		_root.range._alpha = 100;
		can_be_placed = true;
		if (_root.cant_build.hitTest(this._x-this._width/2, this._y-this._height/2, true) or _root.cant_build.hitTest(this._x+this._width/2, this._y+this._height/2, true) or _root.cant_build.hitTest(this._x+this._width/2, this._y-this._height/2, true) or _root.cant_build.hitTest(this._x-this._width/2, this._y+this._height/2, true)) {
			_root.range._alpha = 0;
			can_be_placed = false;
		}
	}
};
range.onEnterFrame = function() {
	if (!placed) {
		this._x = _root._xmouse;
		this._y = _root._ymouse;
	}
};
onMouseDown = function () {
	if (can_be_placed) {
		placed = true;
	}
};

Line 1: Defining the base range

Line 2: Defining if the base can be placed

Line 3: Defining if the base has been placed

Line 5: Attaching the cant_build movieclip

Line 6: Attaching the range movieclip and setting its width and height to match base_range

Line 7: Attaching the base movieclip

Line 36: Function to be executed for the base at every frame

Line 37: If the base is not already placed...

Lines 38-39: Move the base to the mouse pointer

Line 40: Set the transparency of the range to 100 (fully opaque)

Line 41: Updating can_be_placed to true

Line 42: If a corner of the base is over the cant_build area...

Line 43: Setting the transparency of the range to 0 (fully transparent)

Line 44: Setting can_be_placed to false

What I've done: I let the player move the base with the mouse. If the base can't be placed, because it's over the walking path, I hide the range to make the player know he is on an area where he can't build.

Line 48: Function to be executed for the range at every frame

Lines 49-52: Same thing of lines 37-39... if the base has not been placed, then move the range with the mouse

Line 54: Function to be executed when the player clicks the mouse

Line 55: If the base can be placed...

Line 56: Then set placed to true. Now the base is placed

Look: you can now place your base, but only outside the walking path.

Now, we will make the base fire at the foes

base_range = 300;
can_be_placed = false;
placed = false;
firing = false;
attachMovie("path", "path", _root.getNextHighestDepth());
attachMovie("cant_build", "cant_build", _root.getNextHighestDepth());
attachMovie("range", "range", _root.getNextHighestDepth(), {_width:base_range, _height:base_range});
attachMovie("base", "base", _root.getNextHighestDepth());
waypoint_x = new Array(40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420);
waypoint_y = new Array(140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20);
delay = 25;
new_monster = 0;
monsters_placed = 0;
onEnterFrame = function () {
	if (monsters_placed<25) {
		new_monster++;
	}
	if (new_monster == delay) {
		monsters_placed++;
		new_monster = 0;
		min = attachMovie("minion", "minion"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:40, _y:-20});
		min.point_to_reach = 0;
		min.speed = 1;
		min.onEnterFrame = function() {
			dist_x = waypoint_x[this.point_to_reach]-this._x;
			dist_y = waypoint_y[this.point_to_reach]-this._y;
			if ((Math.abs(dist_x)+Math.abs(dist_y))<1) {
				this.point_to_reach++;
			}
			angle = Math.atan2(dist_y, dist_x);
			this._x = this._x+this.speed*Math.cos(angle);
			this._y = this._y+this.speed*Math.sin(angle);
			this._rotation = angle/Math.PI*180-90;
			if (bullet.hitTest(this._x, this._y, true)) {
				firing = false;
				bullet.removeMovieClip();
				this.removeMovieClip();
			}
			if (placed) {
				distance_from_turret_x = base._x-this._x;
				distance_from_turret_y = base._y-this._y;
				if ((Math.sqrt(distance_from_turret_x*distance_from_turret_x+distance_from_turret_y*distance_from_turret_y)400) or (this._x>500)) {
							firing = false;
							this.removeMovieClip();
						}
					};
				}
			}
		};
	}
};
base.onEnterFrame = function() {
	if (!placed) {
		this._x = _root._xmouse;
		this._y = _root._ymouse;
		_root.range._alpha = 100;
		can_be_placed = true;
		if (_root.cant_build.hitTest(this._x-this._width/2, this._y-this._height/2, true) or _root.cant_build.hitTest(this._x+this._width/2, this._y+this._height/2, true) or _root.cant_build.hitTest(this._x+this._width/2, this._y-this._height/2, true) or _root.cant_build.hitTest(this._x-this._width/2, this._y+this._height/2, true)) {
			_root.range._alpha = 0;
			can_be_placed = false;
		}
	}
};
range.onEnterFrame = function() {
	if (!placed) {
		this._x = _root._xmouse;
		this._y = _root._ymouse;
	}
};
onMouseDown = function () {
	if (can_be_placed) {
		placed = true;
	}
};

Line 4: Setting the firing variable to false. Now the base is not firing

Line 34: Performing an hit test between the minion and the bullet. At this time in the script we haven't already met the bullet, but anyway at this time I am performing this test

Line 35-37: If the test is positive, then remove the bullet and the minion that was hit (at this time minions do not have energy, so my turret is one shot one kill), then set firing to false.

Lines 40-41: Calculating x and y distance between the bullet and the minion

Line 42: If the distance between the bullet and the minion is less than half the range (in our case the range is the diameter of the circle, so half the range is the radius)

Line 43: Boom! The turret fires!

Line 44: Placing the bullet on stage, in the same position of the turret

Line 45: Setting bullet direction, accordind to its x and y distances from the minion

Line 46: Function to be executed for the bullet at every frame

Lines 47-48: Moving the bullet using trigonometry. If you don't know what is trigonometry, then head to this tutorial

Line 49: Checking if the bullet is flying out of the stage

Lines 50-51: In this case, remove the bullet and set firing to false again to let the turret fire once more

And here it is our firing turret. You may need to reload the page to have the minion walking while you will place the turret and start killing them.

The fire rate sucks a lot, and the same thing does turret's AI. But I got all those features in only 81 lines, I am sure I will create the complete game in less than 500 lines.

Not today, anyway. Today, download the source and if you have suggestion... just leave a comment.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.