Flash game creation tutorial – part 5.3

Read all posts about "" game

Let’s go with another step.

In this part, we’ll learn how to (almost) complete our first game… a tunnel race game.

Read tutorials from 1 to 5.2 if you haven’t done it already and follow me in the game creation.

I’ll continue from the code optimization seen in part 5.2, to continue adding features to the scrolling game.

Adding a timer

If you plan to make a racing game, the timer is very important. Some of the topics covered in this example are taken from the Flash simple timer/countdown tutorial.

// attaching movies
_root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
_root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:0});
// kira setup
yspeed = 0;
xspeed = 0;
wind = 0.00;
power = 0.65;
gravity = 0.1;
upconstant = 0.75;
friction = 0.99;
// timer setup
start_time = getTimer();
countdown = 60000;
kira.onEnterFrame = function() {
	// timer
	elapsed_time = getTimer()-start_time;
	_root.count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
	// keys
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	// speed calculation  
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	if (xspeed>0) {
		this.kira.gotoAndStop(1);
	} else {
		this.kira.gotoAndStop(2);
	}
	// screen update
	_root.wall._y -= yspeed;
	_root.wall._x -= xspeed;
	_root.bg._y -= yspeed;
	_root.bg._x -= xspeed;
	// collision
	if (_root.wall.hitTest(this._x, this._y, true)) {
		xspeed = 0;
		yspeed = 0;
		_root.wall._x = 240;
		_root.wall._y = 0;
		_root.bg._x = 240;
		_root.bg._y = 0;
	}
};
function time_to_string(time_to_convert) {
	elapsed_hours = Math.floor(time_to_convert/3600000);
	remaining = time_to_convert-(elapsed_hours*3600000);
	elapsed_minutes = Math.floor(remaining/60000);
	remaining = remaining-(elapsed_minutes*60000);
	elapsed_seconds = Math.floor(remaining/1000);
	remaining = remaining-(elapsed_seconds*1000);
	elapsed_fs = Math.floor(remaining/10);
	if (elapsed_hours<10) {
		hours = "0"+elapsed_hours.toString();
	} else {
		hours = elapsed_hours.toString();
	}
	if (elapsed_minutes<10) {
		minutes = "0"+elapsed_minutes.toString();
	} else {
		minutes = elapsed_minutes.toString();
	}
	if (elapsed_seconds<10) {
		seconds = "0"+elapsed_seconds.toString();
	} else {
		seconds = elapsed_seconds.toString();
	}
	if (elapsed_fs<10) {
		hundredths = "0"+elapsed_fs.toString();
	} else {
		hundredths = elapsed_fs.toString();
	}
	return minutes+":"+seconds+":"+hundredths;
}

Line 4: Nothing to do with the timer, but I added a background to the cavern. The way I added the background is the same I added the main cavern. Look at the depth (0)... the background is behind all other objects

Line 5: Here I add the movieclip that will contain the timer. Look at the depth (12000)... the timer is in front of all aother objects. In the timer object I have a textarea called time_left that will be updated. We will add all texts covered in this tutorial in the same way

Lines 15-16: Timer setup... I want the level to be completed in 60 secods = 60,000 milliseconds. Again I strongly recommend to read the Flash simple timer/countdown tut.

Line 19: Determining elapsed time

Line 20: The text area time_left inside the movieclip count_down is updated according to the function time_to_string (lines 56-87). You can find this function fully explained... guess where?... Yes, at Flash simple timer/countdown tutorial!

You will notice nothing happens if the time reaches zero... I wanted it to fully test the game. You hould always test the game in a "god mode" to verify all levels are designed correctly, then start testing it in "normal mode".

The energy

Now, let's imagine we do not want the player to die if he hits the wall, but we want instead he to lose "energy" or "shields" or "bananas" until it reaches zero.

// attaching movies
_root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
_root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:0});
// kira setup
yspeed = 0;
xspeed = 0;
wind = 0.00;
power = 0.65;
gravity = 0.1;
upconstant = 0.75;
friction = 0.99;
energy = 100;
count_down.energy_left.text = "Shield left: "+energy;
// timer setup
start_time = getTimer();
countdown = 60000;
kira.onEnterFrame = function() {
	// timer
	elapsed_time = getTimer()-start_time;
	_root.count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
	// keys
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	// speed calculation   
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	if (xspeed>0) {
		this.kira.gotoAndStop(1);
	} else {
		this.kira.gotoAndStop(2);
	}
	// screen update
	_root.wall._y -= yspeed;
	_root.wall._x -= xspeed;
	_root.bg._y -= yspeed;
	_root.bg._x -= xspeed;
	// collision
	if (_root.wall.hitTest(this._x, this._y, true)) {
		energy -= Math.round(Math.sqrt(xspeed*xspeed+yspeed*yspeed));
		_root.count_down.energy_left.text = "Shield left: "+energy;
		xspeed = 0
		yspeed = 0
		_root.wall._y = old_y;
		_root.wall._x = old_x;
		_root.bg._y = old_y;
		_root.bg._x = old_x;
	} else {
		old_x = _root.wall._x+2*xspeed;
		old_y = _root.wall._y+2*yspeed;
	}
};
function time_to_string(time_to_convert) {
	elapsed_hours = Math.floor(time_to_convert/3600000);
	remaining = time_to_convert-(elapsed_hours*3600000);
	elapsed_minutes = Math.floor(remaining/60000);
	remaining = remaining-(elapsed_minutes*60000);
	elapsed_seconds = Math.floor(remaining/1000);
	remaining = remaining-(elapsed_seconds*1000);
	elapsed_fs = Math.floor(remaining/10);
	if (elapsed_hours<10) {
		hours = "0"+elapsed_hours.toString();
	} else {
		hours = elapsed_hours.toString();
	}
	if (elapsed_minutes<10) {
		minutes = "0"+elapsed_minutes.toString();
	} else {
		minutes = elapsed_minutes.toString();
	}
	if (elapsed_seconds<10) {
		seconds = "0"+elapsed_seconds.toString();
	} else {
		seconds = elapsed_seconds.toString();
	}
	if (elapsed_fs<10) {
		hundredths = "0"+elapsed_fs.toString();
	} else {
		hundredths = elapsed_fs.toString();
	}
	return "Time left: "+minutes+":"+seconds+":"+hundredths;
}

Line 14: Set the starting energy at 100

Line 15: Display player energy on screen

Line 51: In case of collision, the player does not die but his energy drains according to player speed. The higher the speed, the bigger the damage

Line 55-58: wall and background are resetted to their last position where no collision was detected

Lines 59-62: if there wasn't a collision, save actual position (with a little offset due by player speed)

These last lines remind a bit the collision checking seen in flash draw game tutorial part 4.

Now, next feature...

The brakes

I want the player to have the capability of using brakes, even if for a limited amount of time.

// attaching movies
_root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
_root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:0});
// kira setup
yspeed = 0;
xspeed = 0;
wind = 0.00;
power = 0.65;
gravity = 0.1;
upconstant = 0.75;
friction = 0.99;
energy = 100;
brakes = 100;
count_down.energy_left.text = "Shield left: "+energy;
count_down.brake_left.text = "Brakes left: "+brakes;
// timer setup
start_time = getTimer();
countdown = 60000;
kira.onEnterFrame = function() {
	// timer
	elapsed_time = getTimer()-start_time;
	_root.count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
	// keys
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	if ((Key.isDown(Key.SPACE))and(brakes > 0)) {
		yspeed = yspeed/2;
		xspeed = xspeed/2;
		brakes --;
		count_down.brake_left.text = "Brakes left: "+brakes;
	}
	// speed calculation   
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	if (xspeed>0) {
		this.kira.gotoAndStop(1);
	} else {
		this.kira.gotoAndStop(2);
	}
	// screen update
	_root.wall._y -= yspeed;
	_root.wall._x -= xspeed;
	_root.bg._y -= yspeed;
	_root.bg._x -= xspeed;
	// collision
	if (_root.wall.hitTest(this._x, this._y, true)) {
		energy -= Math.round(Math.sqrt(xspeed*xspeed+yspeed*yspeed));
		_root.count_down.energy_left.text = "Shield left: "+energy;
		xspeed = 0
		yspeed = 0
		_root.wall._y = old_y;
		_root.wall._x = old_x;
		_root.bg._y = old_y;
		_root.bg._x = old_x;
	} else {
		old_x = _root.wall._x+2*xspeed;
		old_y = _root.wall._y+2*yspeed;
	}
};
function time_to_string(time_to_convert) {
	elapsed_hours = Math.floor(time_to_convert/3600000);
	remaining = time_to_convert-(elapsed_hours*3600000);
	elapsed_minutes = Math.floor(remaining/60000);
	remaining = remaining-(elapsed_minutes*60000);
	elapsed_seconds = Math.floor(remaining/1000);
	remaining = remaining-(elapsed_seconds*1000);
	elapsed_fs = Math.floor(remaining/10);
	if (elapsed_hours<10) {
		hours = "0"+elapsed_hours.toString();
	} else {
		hours = elapsed_hours.toString();
	}
	if (elapsed_minutes<10) {
		minutes = "0"+elapsed_minutes.toString();
	} else {
		minutes = elapsed_minutes.toString();
	}
	if (elapsed_seconds<10) {
		seconds = "0"+elapsed_seconds.toString();
	} else {
		seconds = elapsed_seconds.toString();
	}
	if (elapsed_fs<10) {
		hundredths = "0"+elapsed_fs.toString();
	} else {
		hundredths = elapsed_fs.toString();
	}
	return "Time left: "+minutes+":"+seconds+":"+hundredths;
}

Line 15: Set the starting amount of brakes to 100

Line 17: Display player brakes on screen

Line 38: Checking if the player is braking (or pressing spacebar...) and the player has brakes left

Lines 39-42: Player speed is reduced by a half, brakes are reduced and new brakes value is displayed on the screen

Now we have all the information required on screen. Time to show them in a clearer way.

Text styles

Let's see how to give some style to our texts

// attaching movies
_root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
_root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
_root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:1});
// kira setup
yspeed = 0;
xspeed = 0;
wind = 0.00;
power = 0.65;
gravity = 0.1;
upconstant = 0.75;
friction = 0.99;
energy = 100;
brakes = 100;
with (count_down.brake_left) {
	text = "Brakes: "+brakes;
	textColor = 0x00ff00;
	background = true;
	border = true;
	borderColor = 0xffffff;
	backgroundColor = 0x000000;
	_alpha = 80;
}
with (count_down.energy_left) {
	text = "Shield: "+energy;
	textColor = 0x00ff00;
	background = true;
	border = true;
	borderColor = 0xffffff;
	backgroundColor = 0x000000;
	_alpha = 80;
}
with (count_down.time_left) {
	textColor = 0x00ff00;
	background = true;
	border = true;
	borderColor = 0xffffff;
	backgroundColor = 0x000000;
	_alpha = 80;
}
// timer setup
start_time = getTimer();
countdown = 60000;
kira.onEnterFrame = function() {
	// timer
	elapsed_time = getTimer()-start_time;
	count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
	// keys
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	if ((Key.isDown(Key.SPACE)) and (brakes>0)) {
		yspeed = yspeed/2;
		xspeed = xspeed/2;
		brakes--;
		if (brakes<60) {
			count_down.brake_left.textColor = 0xffff00;
		}
		if (brakes<30) {
			count_down.brake_left.textColor = 0xff0000;
		}
		count_down.brake_left.text = "Brakes: "+brakes;
	}
	// speed calculation    
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	if (xspeed>0) {
		this.kira.gotoAndStop(1);
	} else {
		this.kira.gotoAndStop(2);
	}
	// screen update
	_root.wall._y -= yspeed;
	_root.wall._x -= xspeed;
	_root.bg._y -= yspeed;
	_root.bg._x -= xspeed;
	// collision
	if (_root.wall.hitTest(this._x, this._y, true)) {
		energy -= Math.round(Math.sqrt(xspeed*xspeed+yspeed*yspeed));
		if (energy<60) {
			count_down.energy_left.textColor = 0xffff00;
		}
		if (energy<30) {
			count_down.energy_left.textColor = 0xff0000;
		}
		_root.count_down.energy_left.text = "Shield: "+energy;
		xspeed = 0;
		yspeed = 0;
		_root.wall._y = old_y;
		_root.wall._x = old_x;
		_root.bg._y = old_y;
		_root.bg._x = old_x;
	} else {
		old_x = _root.wall._x+2*xspeed;
		old_y = _root.wall._y+2*yspeed;
	}
};
function time_to_string(time_to_convert) {
	elapsed_hours = Math.floor(time_to_convert/3600000);
	remaining = time_to_convert-(elapsed_hours*3600000);
	elapsed_minutes = Math.floor(remaining/60000);
	remaining = remaining-(elapsed_minutes*60000);
	elapsed_seconds = Math.floor(remaining/1000);
	remaining = remaining-(elapsed_seconds*1000);
	elapsed_fs = Math.floor(remaining/10);
	if (elapsed_hours<10) {
		hours = "0"+elapsed_hours.toString();
	} else {
		hours = elapsed_hours.toString();
	}
	if (elapsed_minutes<10) {
		minutes = "0"+elapsed_minutes.toString();
	} else {
		minutes = elapsed_minutes.toString();
	}
	if (elapsed_seconds<10) {
		seconds = "0"+elapsed_seconds.toString();
	} else {
		seconds = elapsed_seconds.toString();
	}
	if (elapsed_fs<10) {
		hundredths = "0"+elapsed_fs.toString();
	} else {
		hundredths = elapsed_fs.toString();
	}
	return "Time: "+minutes+":"+seconds+":"+hundredths;
}

Lines 16-24: Note how I use the with statement to change brake text attributes.

According to Adobe Livedocs, the attributes you may be interested in are:

_alpha:Number - Sets or retrieves the alpha transparency value of the text field.

background:Boolean - Specifies if the text field has a background fill.

backgroundColor:Number - The color of the text field background.

border:Boolean - Specifies if the text field has a border.

borderColor:Number - The color of the text field border.

filters:Array - An indexed array containing each filter object currently associated with the text field. (you can see some filters in action in draw game creation tutorial part 1)

html:Boolean - A flag that indicates whether the text field contains an HTML representation.

htmlText:String - If the text field is an HTML text field, this property contains the HTML representation of the text field's contents.

_rotation:Number - The rotation of the text field, in degrees, from its original orientation.

text:String - Indicates the current text in the text field.

textColor:Number - Indicates the color of the text in a text field.

_x:Number - An integer that sets the x coordinate of a text field relative to the local coordinates of the parent movie clip.

_y:Number - The y coordinate of a text field relative to the local coordinates of the parent movie clip.

Lines 25-33: Same thing with the enery text

Lines 34-41: Same thing with the timer text

Lines 66-71: If the brakes are damaged (<60) or critical (<30), I change brakes text color to yellow or red Lines 90-95: Same thing with the energy text

Now we have a nice text representation... let's cover another thing...

Advancing levels

What kind of game do we have if we cannot advance levels? Now I am teaching you how to add new caves.

In the movieclip where you have the first cavern, simply add a frame and draw another cavern. You can add how many caverns you want, just remember to put a stop() in each frame and to add, in the end of the cave, a movieclip instanced as end

// attaching movies
_root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
_root.attachMovie("wall", "wall", 10000, {_width:5700, _height:5700});
_root.attachMovie("bg", "bg", 2000, {_width:5700, _height:5700});
_root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:1});
// kira setup
start_x = new Array(240, -2160,-1400);
start_y = new Array(0, 2700,2200);
level = 1;
position_bg(level);
yspeed = 0;
xspeed = 0;
wind = 0.00;
power = 0.65;
gravity = 0.1;
upconstant = 0.75;
friction = 0.99;
energy = 100;
brakes = 100;
with (count_down.brake_left) {
	text = "Brakes: "+brakes;
	textColor = 0x00ff00;
	background = true;
	border = true;
	borderColor = 0xffffff;
	backgroundColor = 0x000000;
	_alpha = 80;
}
with (count_down.energy_left) {
	text = "Shield: "+energy;
	textColor = 0x00ff00;
	background = true;
	border = true;
	borderColor = 0xffffff;
	backgroundColor = 0x000000;
	_alpha = 80;
}
with (count_down.time_left) {
	textColor = 0x00ff00;
	background = true;
	border = true;
	borderColor = 0xffffff;
	backgroundColor = 0x000000;
	_alpha = 80;
}
// timer setup
start_time = getTimer();
countdown = 60000;
kira.onEnterFrame = function() {
	// timer
	elapsed_time = getTimer()-start_time;
	count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
	// keys
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	if ((Key.isDown(Key.SPACE)) and (brakes>0)) {
		yspeed = yspeed/2;
		xspeed = xspeed/2;
		brakes--;
		count_down.brake_left.textColor = 0x00ff00;
		if (brakes<60) {
			count_down.brake_left.textColor = 0xffff00;
		}
		if (brakes<30) {
			count_down.brake_left.textColor = 0xff0000;
		}
		count_down.brake_left.text = "Brakes: "+brakes;
	}
	// speed calculation       
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	if (xspeed>0) {
		this.kira.gotoAndStop(1);
	} else {
		this.kira.gotoAndStop(2);
	}
	// screen update
	_root.wall._y -= yspeed;
	_root.wall._x -= xspeed;
	_root.bg._y -= yspeed;
	_root.bg._x -= xspeed;
	// collision
	if (_root.wall.hitTest(this._x, this._y, true)) {
		if (!_root.wall.end.hitTest(this._x, this._y, true)) {
			energy -= Math.round(Math.sqrt(xspeed*xspeed+yspeed*yspeed));
			count_down.energy_left.textColor = 0x00ff00;
			if (energy<60) {
				count_down.energy_left.textColor = 0xffff00;
			}
			if (energy<30) {
				count_down.energy_left.textColor = 0xff0000;
			}
			count_down.energy_left.text = "Shield: "+energy;
			xspeed = 0;
			yspeed = 0;
			_root.wall._y = old_y;
			_root.wall._x = old_x;
			_root.bg._y = old_y;
			_root.bg._x = old_x;
		} else {
			xspeed = 0;
			yspeed = 0;
			level++;
			energy += 100;
			brakes += 100;
			start_time += 60000;
			count_down.energy_left.textColor = 0x00ff00;
			count_down.brake_left.text = "Shield: "+energy;
			count_down.energy_left.text = "Shield: "+energy;
			count_down.brake_left.text = "Brakes: "+brakes;
			position_bg(level);
		}
	} else {
		old_x = _root.wall._x+2*xspeed;
		old_y = _root.wall._y+2*yspeed;
	}
};
function time_to_string(time_to_convert) {
	elapsed_hours = Math.floor(time_to_convert/3600000);
	remaining = time_to_convert-(elapsed_hours*3600000);
	elapsed_minutes = Math.floor(remaining/60000);
	remaining = remaining-(elapsed_minutes*60000);
	elapsed_seconds = Math.floor(remaining/1000);
	remaining = remaining-(elapsed_seconds*1000);
	elapsed_fs = Math.floor(remaining/10);
	if (elapsed_hours<10) {
		hours = "0"+elapsed_hours.toString();
	} else {
		hours = elapsed_hours.toString();
	}
	if (elapsed_minutes<10) {
		minutes = "0"+elapsed_minutes.toString();
	} else {
		minutes = elapsed_minutes.toString();
	}
	if (elapsed_seconds<10) {
		seconds = "0"+elapsed_seconds.toString();
	} else {
		seconds = elapsed_seconds.toString();
	}
	if (elapsed_fs<10) {
		hundredths = "0"+elapsed_fs.toString();
	} else {
		hundredths = elapsed_fs.toString();
	}
	return "Time: "+minutes+":"+seconds+":"+hundredths;
}
function position_bg(level) {
	wall.gotoAndStop(level);
	wall._x = start_x[level-1];
	wall._y = start_y[level-1];
	bg._x = start_x[level-1];
	bg._y = start_y[level-1];
}

Line 7: array with the 3 _x starting position of the level walls

Line 8: array with the 3 _y starting position of the level walls

Line 9: initializing starting level to 1

Line 10: calling the position_bg function. This function, located at lines 158-164, simply performs a gotoAndStop to the current level (frame) and places walls and backgrounds in their starting positions (declared in lines 7 and 8) according to the level

Line 94: When the player hits the wall, another test is performed to see if the player is hitting the end. If not, the game continues in the same way seen previously

Lines 110-122: If the player reached the exit, xspeed and yspeed are set to zero, level is increased, time, brakes and energy are increased by a bonus and the text on screen are updated. Finally, the position_bg function is called again.

Can you beat level 3?

Well, how you may see, I am designing a cavern racing game. Do you want to be part of it? You can! Soon you will find everything you need to design a level or more.

Meanwhile, download all source examples and have fun... until next tut...

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