Simple JavaScript Templating

While working on a little side project of mine, I came across the need for a really simple method of performing HTML templating within JavaScript. Since JQuerys method had been deprecated, and seeing as I had no real requirement for any fancy functionality, I decided to quickly throw together my own implementation, which can be grabbed below.

 /**
 * TPL provides an ultra light weight, super simple method for quickly doing HTML templating in javascript.
 * @author Carl Saggs
 * @version 0.2
 * @source https://github.com/thybag/base.js
 */
 (function(){

	/**
	 * template
	 * Template a HTML string by replacing {attributes} with the corisponding value in a js Object.
	 * @param String (Raw HTML or ID of template node)
	 * @param JS Object
	 * @return NodeList|Node
	 */
	this.template = function(tpl, data){
		//Find out if ID was provided by attempting to find template node by ID  
		var el = document.getElementById(tpl);
		// If result is null, assume was passwed raw HTML template
		if(el !== null) tpl = el.innerHTML;
		//transform result in to DOM node(s)
		var tmp = document.createElement("div");
		tmp.innerHTML = replaceAttr(tpl,data);
		var results = tmp.children;
		//if only one node, return as individual result
		if(tmp.children.length===1)results = tmp.children[0];
		return results;
	}

	/**
	 * replaceAttr
	 * Replace all {attribute} with the corisponding value in a js Object.
	 * @param String (raw HTML)
	 * @return String (raw HTML)
	 * @scope private
	 */
	var replaceAttr = function(tpl, data, prefix){
		//Foreach data value
		for(var i in data){
			//Used for higher depth items
			var accessor = i;
			if(typeof prefix !== 'undefined') i = prefix+'.'+i
			//If object, recusivly call self, else template value.
			if(typeof data[i] === 'object'){
				tpl = this.replaceAttr(tpl, data[i], i);
			}else{
				tpl = tpl.replace(new RegExp('{'+i+'}','g'), data[accessor]);
			}
		}
		//return templated HTML
		return tpl;
	}

	//Add tpl to global scope
	window.tpl = this;
}).call({});

Essentially the code just provides a simple way of passing in some arbitrary HTML markup, then swapping out any contained {bla} tags with the values stored in the associated JavaScript object.
Say for example we had a array of people objects and we wanted to apply a simple template to them, before appending them in to our document. To do this you could use code similar to the following:

var test = [
	{"name":"Dave","age":22},
	{"name":"James","age":42},
	{"name":"Tim","age":27}
];
test.forEach(function(personObj){
	var el = tpl.template("<div class='person'><strong>{name}</strong><span class='right'>{age}</span></div>",personObj);
	document.body.appendChild(el);
});

Alternately if you had some more complex markup, or just wanted to separate the templates from the general script a little more, you can specify your template HTML in script tags (or any other elements) and reference them by id. For the example above you would just have something like this within your html document

<script id='myTemplate' type='text'>
	<div class='person'>
		<strong>{name}</strong>
		<span class='right'>{age}</span>
	</div>
</script>

Which could then be utilised in the following manner.

var el = tpl.template("myTemplate", personObj);

The script will also happily support passing in multidimensional objects which can be used in the templates as obj.attr.anotherattr etc.

As with most code I write, the source is on github and may be updated periodically with bug fixes and new features. Currently my templating method is incredibly basic and has almost no features compared to pretty much all others out there. That said, it does what I need it to, so its not all bad ūüôā

Thanks for reading,
Carl

PHP SharePoint Lists API release

A new version of my PHP SharePoint Lists API has now been released; the new version includes multiple bug fixes, optimisations and a number of new features.

The most notable new feature of the PHP SharePoint Lists API is the query method. The query function allows users to run complex query’s against sharepoint lists using an easy to follow and expressive SQL like syntax.

For example, using the query feature you can easily query a list of pets to return all items relating to dogs under 5, ordered by age.

$sp->query('list of pets')
   ->where('type','=','dog')
   ->and_where('age','<','5')
   ->sort('age','ASC')
   ->get();

“OR” querys can also be used, for example, if you wanted to return a list of 10 pets that were either cats or dogs, you might write:

$sp->query('list of pets')
   ->where('type','=','cat')
   ->or_where('type','=','dog')
   ->limit(10)
   ->get();

The PHP SharePoint Lists API is available on Github and can be used for free in any projects you may wish (under the terms of the MIT Licence). You can download it directly by clicking here.

PJAX-Standalone – Pushstate Ajax

PJAX or Pushstate AJAX is a¬†fairly¬†new twist on the traditional AJAX page loading idea, although unlike its predecessors PJAX takes¬†advantage¬†of the new Pushstate history API’s in order to provide it with real permalinks and history as opposed the the document.hash based hacks which the former has had to make do with.

The result is that its now possible to gain the performance boosts that AJAX page loading makes possible, across the majority of the major browsers (IE not included), without any fear of compromising backwards compatibility or the native behaviours of the browser (back button etc).

Unfortunately the main source of PJAX goodness is JQuery plugin ( jquery-pjax) meaning that those who favour alternative JavaScript frameworks Рor even none at all Рare left out in the cold.

To remedy this, I decided to create my own standalone implementation of PJAX (Which I insightfully named as PJAX-Standalone). Like its counterpart PJAX-standalone was designed to be highly customisable while at the same time, incredibly easy to get working. For many webpages nothing more than the addition of an ID to your content container and a single call to the PJAX-Standalone script is required.

For those who want more functionality a number of callbacks can also be set in addition to being able to invoke PJAX page loading programmatically as well.

You can see an example of the script in action on the PJAX-Standalone demo page.

Full details on how to use and configure PJAX-Standalone can be found on  Github.

Ubuntu 11.10 – Setting up with LXDE

I like Ubuntu, it’s not¬†every ones favourite linux¬†distribution, but for me, it’s always done what I’ve needed it to.¬†Installation¬†is simple and painless, and almost everything I want comes with it out of the box. Or at least it used to.

Maybe I’m just falling into the “I hate change” trap, but Unity, for me at least, just isn’t what I’m after. Despite a number of¬†attempts¬†to get used it it, ¬†it just ¬†feels awkward to use and¬†doesn’t really fit with the way I want to interact with my computer.¬†Switching back to the gnome¬†environment¬†doesn’t really do the trick either, as I just find myself annoyed at how the gnome 3 “classic” mode has stripped out so many of the features I took for granted. Gnome 3 itself… lets not even go there. So there is the problem, as much as I like Ubuntu, it no longer provides me with an interface I’m comfortable with.

Rather than just continue to moan about all this stuff at great length, I decided I would actually spend a little time being semi-constructive and have a tinker with some of the other options out there (XFCE ¬†and LXDE being the main contenders). Since I’ve used xfce in the past, I opted to give my attention to LXDE.

I already had a blank Ubunutu 11.10 installation sitting around in VirtualBox, so I decided to use that as my base, rather than downloading and installing the proper lubuntu installation.

To begin, I booted up virtual box and logged in to the Ubuntus default unity environment. Then to add the LXDE desktop, I opened up the terminal and ran:

sudo apt-get install lxde

After agreeuing to its demands (50 or so mb of space) and waiting for it to complete, I logged out, switched my¬†environment¬†from “Unity” to “LXDE” (right click the cog next to the login box to select this) and¬†logged back in.

I was then greeted by the following functional (although not especially pretty) desktop.

LXDE Default Desktop

LXDE Default Desktop

Although not as fully featured as gnome, I was happy to find the interface provided pretty much everything I wanted (including the ability to freely customise the panels). The only real issues I found with the interface, was the clunky and cluttered menu, and its (in my opinion) somewhat unattractive looks. Thankfully, this being Linux, both issues were fairly straightforward to solve.

My first target was the start menu, having come from a windows system the thing I missed most in the menu was the ability to quickly search for what I was after. To solve this problem, I opted to use Cardapio as it offered the above functionality in addition to being stand alone (making it easy to get running).

To get cardapio installed, you’ll want to run the following 3 commands in the terminal which will add the cardapio repository and then download cardapio itself (along with¬†¬†tracker – in order to allow file searches, and python-glade2 which is a missing¬†dependency¬†of cardapio).

sudo add-apt-repository ppa:cardapio-team/unstable
sudo apt-get update
sudo apt-get install cardapio tracker python-glade2

Once cardapio is installed, the next step is the slighly more difficult task of setting it up in place of the default start menu. Since I was unable to find¬†any reliable documention on how to do this properly, I fiddled around and finally settled on the solution of “botching” it by replacing the panels “Menu” with¬†an “Application launch bar” containing only the cardapio icon.

To do this right click the taskbar and select “Add / Remove panel items”. Then in the dialog, select “Add” and “Appliction launch bar”.¬†This should place the new “appliction launch bar” on the end of the panel, use the up button to move it in front of the existing “Menu”.¬†Double clicking this will now give you the¬†opportunity¬†to add applictions to the “launch bar”.¬†Unfortunately, Cardapio is no where to be seen.

This is becuse cardapio by deafult is set to hidden. To fix this, in your terminal window run.

sudo nano /usr/share/applications/cardapio.desktop

Then using nano, change the value of “NoDisplay” from true to false and save over the original file.

On opening your appliction launch bar again, you should now find Cardapio helpfully listed under “Accessories”. Hit add to move it in to the¬†Launcher, then close the window and give it a try.

With a decent start manager now in place, the next step is just to pretty it up.

To start with I right click the task bar, selected “Panel Settings” and changed the panel Edge to “top” (to place the panel at the top of the desktop). Then in the “Appearance” tab, I change from “Image” to solid “color¬†(with optacity)” and¬†adjusted the colour and opacity¬†in order to provide a semi-transparent black taskbar.

Next, install avant-window-navigator (my dock of choice) using:

sudo apt-get install avant-window-navigator

Once installed, open the start menu and select AWN (just search avant) which should start it running. Don’t worry that it looks hidious at this point. Just right click the dock and select dock preferences, then in the main panel tick the box that says “start Awn automatically” and close it.

To make AWN (Avant Window Navigator) display correctly, you will now need to install and enable a “compositor”. I opted to use “xcompmgr” for this purpose.¬†Install it using:

sudo apt-get install xcompmgr

And to ensure it starts up whenever your copy of ubuntu does, You’ll need to create it a new startup entry.

Run:

sudo nano /etc/xdg/autostart/XCompmgr.desktop

And add the following data:

[Desktop Entry]
Encoding=UTF-8
Name=XCompmgr
Type=Application
Comment=XCompmgr--a light compositor
Exec=xcompmgr
Terminal=false
OnlyShowIn=LXDE

Once this is done, save, then  logout and in again to see the effects.

Now you have a dock, there is not much point having your running applictions listed up top, so right click the panel, select “add/remove items” and remove¬†the “Task bar” and any other unwanted bits from it.

You can also right click AWN and select a more fitting theme within dock preferences.

To finish off¬†prettying¬†up the desktop, I’d suggest changing the desktop background by right clicking the desktop, selecting preferences and then setting it to use an image of your choice.¬†Adjusting¬†the Theme can then be done using lxAppearence (I stuck with clearlook but switched the highlight colour from orange to dark grey)¬†and Configure the window chrome using the “openbox configution manager”. I switched the theme from “Onyx” to “Carbon”.

The end result, with a little luck should now be a somewhat prettier looking LXDE, with a decent start menu and a nice dock.¬†What’s¬†more, even with all the extra stuff, It’s still quite¬†noticeably¬†nippier than both Unity and Gnome.

LXDE Tweaked

LXDE Tweaked

As one final task for those using the AutoLogin feature in Ubuntu, you will need to set Ubuntu to use LXDE by default. You can do this with the following command:

sudo /usr/lib/lightdm/lightdm-set-defaults -s LXDE

Making HTML5 games by someone who knows nothing about making games: Part 2

Tank combat Screenshot

Tank Combat

Hello, welcome to the (somewhat overdue) second part of my “Making HTML5 games by someone who knows pretty much nothing about making games” series. If you’ve not read the first part ( see here ) then it’s probably a good idea to check that out first as the plan is to try and continue from where I left off. If you want to jump right in you can grab a copy of the code produced previously here.

So, just as a recap, the “game” if it can be called that at this stage is being build using the Sprite.js framework and currently consists of a black screen and an ugly looking triangle, which can be controlled using both the arrow and wasd keys. In order to try and bring the “game” closer to something worthy of that description, the next logical step is to start adding a few more features to our game. Shooting, bad guys, stuff like that.

To do this, its probably a good idea to figure out exactly what kind of game we are planning to make, and thus which features its going to need. In the previous tutorial, I’d kinda been thinking of creating a space style shooter, although, to be honest, I don’t really think the movement method fits to well with that. Additionally, I feel like trying something a bit different.

So what’s the new plan?

Tank Combat

Use a tank to fight off the evil alien invaders.

The main aim of this tutorial is to create the above game, with the following four key features;

  • The ability to drive the tank with the arrow and wasd keys.
  • The ability to aim and shoot using the mouse.
  • To have some sort of enemy to fight.
  • To have some graphics that actually fit the new game idea.

Given this, I think the first step is to start bringing our existing “game” into line with the new vision.
To start, I’ve created a new “tank” sprite (just a really basic pixel tank).

Tank Sprite

The tank sprite consist’s of three panels. The first two display the tank body at different stages of movement (basically the tracks move slightly) and the third shows the tanks gun¬†turret, which needs to be separate from the hull so we can position and rotate it separately.

To add the sprite into the game, we will need to update our “ship” sprite definition. I will also rename “ship” to “tank” while here, just to avoid confusion (remember in addition to changing the sprite file, its also important to update the sprite definition with the new sprites width and height).

tank = this.mytank = this.scene.Sprite("tank.png",{
	"layer": this.layer, //Layer tanks will be displayed in.
	"x": 100, 	//X position of sprite
	"y": 100, 	//Y position of sprite
	"w": 36, 	//width of sprite.
	"h": 59 	//height of sprite.
});

To go with the new sprite, you may also want to change the game’s background colour from black to green (like grass) so it fits a little better with the new theme.

Although the tank sprite is now in the game, it’s movement still feels a little wrong, since it was originally set up on the premise that we were going to be controlling a space ship. Because of this I think its worth spending a little time tweaking the way our sprite moves. To start friction plays a much bigger role when not in space, so to replicate this I’ve added an else, to slow the tank down when not accelerating and, in addition I also lowered the acceleration speed from 0.5 to +0.2.

if(this.inputs.keyboard.up){
	if(speed<5) speed = speed+0.2;
}else{
	//Apply friction
	if(speed>0) speed = speed-0.1;
}

While we are playing with movement, it’s also a good time to add some code to stop the tank from constantly flying of the screen as you drive around. To do this, in its simplest form, we just need to add some code that will check whether or not the x & y coordinates the tank is moving too are within the current scene (on screen) and if not, stop that movement from being applied.

To do this add something along the lines of this just above where the new tank position and angle are applied to the sprite (above the comment “//Tell the tank”).

	//Ensure new X position is inside playable area
	if(nx < 0 || (nx + this.mytank.w) > this.layer.w){
		nx = this.mytank.x;
	}
	//Ensure new Y position is inside playable area
	if(ny < 0 || (ny + this.mytank.h) > this.layer.h){
		ny = this.mytank.y;
	}

With a little luck you should find that you are no longer able to drive your tank outside of the game area. While this gets the job done, it (for me at least) feels a little clunky. My solution to this was simply to swap the outright stop effect for a simple bounce effect instead. The new code looks as follows:

	//Ensure new X position is inside playable area
	if(nx < 0 || (nx + this.mytank.w) > this.layer.w){
		speed = -(speed*0.4);
		nx = this.mytank.x;
	}
	//Ensure new Y position is inside playable area
	if(ny < 0 || (ny + this.mytank.h) > this.layer.h){
		speed = -(speed*0.4);
		ny = this.mytank.y;
	}

It works in a very similar way to the simple stop, except rather than simply stopping the ship it also reverses the ship’s momentum at the same time.

Now that it is possible for the tank to have negative¬†momentum, we need to ensure we still apply friction as the current system is only doing this for positive speed. ¬†To¬†achieve¬†this, add a check for “is speed is less than zero” and if so add to our speed until it reaches zero again.

if(this.inputs.keyboard.up){
	if(speed>0) speed = speed-0.1;
	if(speed<0) speed = speed+0.1;
}

The conversion of our existing “space game” into a “tank” game is now nearly complete. To finish off the conversion, we just need to give our tank its turret.

Adding the turret in a basic way should be fairly simple, so for now, let’s just create a new sprite object to be the turret (ensuring we have the correct offsets so that the turret part of our sprite image is all that is¬†visible).

turret = this.myturret = this.scene.Sprite("tank.png",{
	"layer": this.layer, //Layer tanks will be displayed in.
	"x": 100, 	//X position of sprite
	"y": 100, 	//Y position of sprite
	"w": 36, 	//width of sprite.
	"h": 59, 	//height of sprite.
	"xoffset":75,
	"yoffset":0,
	});

Once that is done, we then need to add some code to keep our turret’s position in sync with the main tank. Under the “mytank.update();”, add the following code.

this.myturret.position(nx,ny);
this.myturret.setAngle(ang);
this.myturret.update();

With a little luck you should now have something along the lines of this:

The next step is to give our tank the ability to aim it’s turret, so when bad guys finally do get added, we can shoot them.

As with the keyboard inputs, getting the mouse position in Sprite.JS is fairly simple and is somthing we can just ask spirte.js’s input object to give us. From this and the tank’s own X,Y coordinates, figuring out which way our turret needs to be angled to fire where we point shouldn’t actually be all that difficult (thanks to a handy little math function called atan2).

//Get center point for the tank
tank_cent_y = this.mytank.y+(this.mytank.h/2);
tank_cent_x = this.mytank.x+(this.mytank.w/2);
//Work out angle that the cursor is from tank.
cursorAngle = Math.atan2(
	(this.inputs.mouse.position.y - tank_cent_y),
	(this.inputs.mouse.position.x - tank_cent_x)
 )+1.571;//Add roughly 90 degrees.

Now we have the angle, we can pass it to the “myturrent.SetAngle” method, so that it’s aim will now follow the¬†cursor¬†(instead of just picking up the its angle from the tank hull as it is currently).

this.myturret.setAngle(cursorAngle);

Now we can aim our tank, it makes¬†sense¬†to give it the ability to fire. As with everything else so far, the first thing is to create the missile sprite, for laziness I just went with another quick “paint.exe” job:

 

Missile Sprite

Getting it into the game though, will be a little different to how the tank body/turret were added, as unlike them, chances are we are going to want lots of missiles, not just the one. Thus rather than storing each missile individually, we’ll need to keep track of them in an array.

First,  define a new array to hold all our missiles at the top of the engine object.

this.missiles = [];

Then create a new function we can call every time the tank fires, in order to create us a new missile. For¬†simplicity’s¬†sake I just called mine “fireMissile”.

this.fireMissile = function(){
	//Code here
}

Within this method,  we then want to add the code to generate a new sprite and to store it in to our missiles array.

missile = this.scene.Sprite("missile.png",{
	"layer": this.layer,
	"w":4,
	"h":11,
	"angle": 0,
	"x": 0,
	"y": 0

});
this.missiles.push(missile);

The complex bit here is now going to be working out where the missile  needs to be placed, in order to fire from our tanks turret. Getting the angle is the simplest task as we can just grab it from our turret.

var a = this.myturret.angle;

While the x and y coordinates are a little more complex, as although we could just grab the tanks x and y and use that, a missile suddenly appearing in the middle of the tank and flying out doesn’t really make much scene. Instead, we need to figure out the coordinates of the point thirty or so pixels in front of our tank in the direction that the turret is facing.

To start, we are still going to need to get the centre point.

x = this.mytank.x+(this.mytank.w/2);
y = this.mytank.y+(this.mytank.h/2);

Given that, we can then use the same bit of math we use to calculate tank momentum, in order to figure out where our missile is going to be thirty pixels away from the centre of the tank (travelling in the correct direction). I ended up tweaking this to twenty eight pixels as it seemed to  fit a little better.

My resulting “fireMissile” function ended up looking pretty much like this:

this.fireMissile = function(){
	var a = this.myturret.angle;
	var x = (this.mytank.x+(this.mytank.w/2))+ (28 * Math.sin(a));
	var y = (this.mytank.y+(this.mytank.h/2))+ (28 * Math.cos(a))*-1;
	missile = this.scene.Sprite("missile.png",{
		"layer": this.layer,
		"w":4,
		"h":11,
		"angle": a,
		"x": x,
		"y": y
	});
	this.missiles.push(missile);

}

In order to make clicking actually call the function, you then need to add the following line under the rest of the movement/input code in the run function:

if(this.inputs.mouse.click) this.fireMissile();

At this point you will probably notice that none of the missile sprites added to the game are actually showing up yet, this is because we haven’t yet added a mechanism to update (and therfore draw) the new sprites.

To do this the easiest option is to again create an additioal function, then ensure its called ever time the game loop runs, by adding code such as the following to the bottom of the run function.

this.updateMissiles();

Next you need to create the updateMissiles function in order to give the¬†aforementioned¬†code¬†something¬†to call.¬†Effectively¬†the purpose of the updateMissiles function will be to loop through all missiles contained in the “missiles” array, and apply any updates needed (movement, redrawing etc).

To¬†implement¬†movement, we can use the same technique we used to calculate our missiles¬†initial¬†location (and to move the tank itself around) ¬†in order to¬†calculate¬†the missiles next position. This can then be applied to the sprite before “update()” is called to redraw the sprite in the new location.

this.updateMissiles = function(){
	this.missiles.forEach(function(m){
		var x = m.x+ (6 * Math.sin(m.angle));
		var y = m.y+ (6 * Math.cos(m.angle))*-1
		m.position(x,y);
		m.update();
	});
}

Although this works fine, it’s probably a good idea to add a little bit of functionality to clean up sprites we no longer need, as once a missile leaves the game area there’s not a lot of point keeping it updated, or indeed, in the game at all.

To do this we will need to be able to remove sprites from the “this.missiles” array in engine, meaning we need to ensure the engine is avaible outside the scope of the main game object. (As the .forEach() method will put us in its own scope). To do this simply define a variable called engine above of the engine function.

In order to calculate whether or not we now want to remove a missile, we will need to get it’s x and y position and check they are both above zero and not beyond the width or height of our game area. If it is, we will then want to call “remove()” on the sprite itself and then remove it from our missiles array.

if(!(
	(m.x>0 && m.x < m.layer.w) &&
	(m.y>0 && m.y < m.layer.h)
)){
	m.remove();
	engine.missiles.splice(engine.missiles.indexOf(m),1);
}

Assuming everything has gone to plan, you should now have a game that looks like this:

So we have a tank, we can drive around and can shoot missiles. I guess the next thing on the agenda is to create something to fight. To start I quickly created a new sprite to use as our “bad guy aliens”.

Tank Sprite

Then i added a additional array to our engine object so we have somewhere to keep track of them (essentially they are going to work in much the same way that missiles do now).

Under our “this.missiles” array, add a:

this.monsters = [];

Then create the outline of your new spawnSlug (which is my monster of choice) and updateMonster methods.

this.spawnSlug = function(x,y){
//stuff here
}
this.updateMonsters = function(){
//stuff here
}

Creating a new slug is going to be almost identical to how missiles are created. We just setup our monster sprite and add the result to our” monsters” array.
The angle itself doesn’t really matter so I’ve just set it as one, and the x and y coordinates to spawn our new slug are passed in as parameters.

this.spawnSlug = function(x,y){
	slug = this.scene.Sprite("slug.png",{
		"layer": this.layer,
		"w":16,
		"h":39,
		"angle": 1,
		"x": x,
		"y": y
	});
	this.monsters.push(slug);
}

Since the slug sprite has a few steps of animation, it’s also a good time to make use of Sprite.js’s Cycle method, which essentially allows us to easily animate our sprite using the sprite panel we created. This is done by providing an array of steps, each consisting of the x and y offset we should apply to our Sprite panel and the duration each panel should display for. Once setup the Cycle can then be attached to the slug sprite.

In order to keep track of the new Cycle object, I’ve chosen to store it within the Sprite object itself in an attribute called animation.

//Create slug sprite
this.spawnSlug = function(x,y){
	slug = this.scene.Sprite("slug.png",{
		"layer": this.layer,
		"w":16,
		"h":39,
		"angle": 1,
		"x": x,
		"y": y
	});
	//setup animation.
	slug.animation = scene.Cycle([
		[0,0,5],
		[16,0,5],
		[32,0,5],
		[48,0,5],
		[32,0,5],
		[16,0,5]
	]).addSprite(slug);
	this.monsters.push(slug);
}

Now we can create slug sprites, the next step is to do something with them once they are in the game. As with the missiles this is done by iterating through the list of monsters and applying certain actions to each, before finally updating the sprite. It is useful to note that if you call update on a cycle (as stored in the m.animation) you no longer need to call update on the Sprite itself in order to apply any movement/rotation.

this.updateMonsters = function(){
	//Loop through each monster sprite
	this.monsters.forEach(function(m){
		m.animation.next().update();
	});
}

Now we can start adding some behaviours to our monster, for example making them slowly advance towards the player. Using “atan2” again, we can ¬†figure out which direction our sprite needs to travel in in order to find our tank (in the same way that we did when working out which direction to point our turret.)

var a = Math.atan2(
	(engine.mytank.y-m.y),
	(engine.mytank.x-m.x)
)+1.571;//90 degrees

Using this angle we can then point our sprite towards the tank and, then using the movement code now powering both the tank itself and it’s missiles, give our monsters the ability to move. The full code may look something like:

this.updateMonsters = function(){
	//Loop through each monster sprite
	this.monsters.forEach(function(m){
		var a = Math.atan2(
			(engine.mytank.y-m.y),
			(engine.mytank.x-m.x)
		)+1.571;
		//Work out new location
		var x = m.x+ (1 * Math.sin(a));
		var y = m.y+ (1 * Math.cos(a))*-1;
		//Apply changes
		m.position(x,y);
		m.setAngle(a)
		m.animation.next().update();
	});
}

In order to test that everything is now working as we expect, we just need to add a little code to our game to spawn the new slug monsters at certain intervals.

if((engine.ticker.currentTick % 200)==0){
	this.spawnSlug(400,-50);
}

The above code will simply add a new slug monster, every 200 ticks of the game loop. Having monsters that want to eat our tank is all well and good, but not a lot of fun if we can’t shoot them. To start, lets add a hp variable to your tank sprite.

this.mytank.hp = 5;

And the same to your monsters, within the spawnSlug method. (I gave mine 2 hp)

slug.hp = 2;

Now comes the hard part, collision detection, fortunately for us, we don’t need to worry to much about this.¬†Sprite.js helpfully comes packaged with its own collision detection system, stored in “lib/collison.js” . Adding this to our game, suddenly adds a host of useful “collidesWith” style methods for detecting collisions (no Math required).

<script type="text/javascript" src='../vendor/lib/collision.js'></script>

To make use of this, navigate back in to your “updateMonsters” method and under the code to apply sprite changes, add:

//Detect collisions
col = m.collidesWithArray(engine.missiles);
if(col !== false){ //false means there were no collisions
	//Take 1 hp away from this monster.
	m.hp--;
	//If monster has less than 1 hp (0), remove it from the game.
	if(m.hp < 1){
		//Remove sprite
		m.remove();
		//remove fictional sprite from our array
		engine.monsters.splice(engine.monsters.indexOf(m),1);
	}
	//remove missile
	col.remove();
	//remove missile from our array
	engine.missiles.splice(engine.missiles.indexOf(col),1);
}

Essentally the above code checks to see¬†whether¬†the current monster has collided with any of the missiles ¬†stored within the missiles array. If no collisions were detected then the “m.collidesWithArray()” ¬†will return false and nothing will happen.

Alternately, if there was a collision between the current monster and a missile, 1 hp is removed from the monster and a check is done to ensure the monsters isn’t dead (if its hp is below 1 (as in 0)), if the monster turns out to be dead, it is then removed from the game.¬†Once this is complete, the missile that hit the monster is then also removed from the game, regardless of whether the monster was killed.

If you play the game now, you should find you are able to shoot the slug monsters as they come towards you. Fun as this is, being invulnerable takes away from the satisfaction, so the next step will be to add a little danger.

Under the above collision code, add:

//Has a monster got to your tank?
col_me = m.collidesWith(engine.mytank);
if(col_me !== false){
	//If so, remove the monster, and take 1hp away from your tank
	m.remove();
	engine.monsters.splice(engine.monsters.indexOf(m),1);
	engine.mytank.hp--;
	//Check to see if the tank is dead?
	if(engine.mytank.hp < 1){
		engine.ticker.pause();
		alert("game over");
	}
}

This code ¬†does the same thing as the previous collision code, except it is checking for collisions between the current monster and your tank, taking away your hp and¬†removing¬†the monster whenever one gets to you. If your tank runs out of hp, “game over” is then triggered by pausing the game loop and displaying a “game over” warning.

Because spawning is currently quite¬†predictable, I think it’s¬†worth adding a slightly better spawning mechanism, just to make the direction the monsters come from a little less predictable, and to additionally add a slowly increasing level of difficulty to the game.

Create a new function called spawnMonster, with code that looks something like;

this.spawnMonster = function(){
	//50% chance of spawning top/bottom or left/right
	if(Math.round(Math.random())==1){
		//If left or right, randomly choose a height to attach
		//our new monster at
		h = Math.floor(Math.random()*this.layer.h);
		if(Math.round(Math.random())==1){
			//attach right
			this.spawnSlug(this.layer.w+50,h);
		}else{
			//attach left
			this.spawnSlug(-50,h);
		}
	}else{
		//if top/bottom, figure out what width to add our sprite
		//at
		w = Math.floor(Math.random()*this.layer.w);
		if(Math.round(Math.random())==1){
			//at bottom
			this.spawnSlug(w,this.layer.h+50);
		}else{
			//at top
			this.spawnSlug(w,-50);
		}
	}
}

The above code essentially flips a coin on whether the monster should spawn at the top/bottom or left/right of the game area. Then depending on which is picked, pick a random position on either the x or y axis (just off screen) to add a sprite. The side the sprite will spawn on is then selected by another coin flip (so to speak).

Once this is done, go to the “run” function and just above where the speed variable is being defined, define a second one and call it spawnrate. Set it to 200. Now within the run method itself, replace the previous monster spawning code with:

//Spawn monster every time tick is a multiple of spawnrate
if((this.ticker.currentTick % spawnrate)==0){
	//If spawn rate is higher than 20, decrese it by 2.
	if(spawnrate>20) spawnrate=spawnrate-2;
	//Spawn a monster somewhere
	this.spawnMonster();
}

The new code will call the this.spawnMonster to create a new slug in a random location, every time the ticker equals a multiple of “spawnrate”. Additionally, each spawn, the time before the next spawn decreases slightly, meaning the monsters will begin to spawn at a faster and faster rate (until the maximum of one every 20 ticks is reached).

To finish off,  make sure to add all the new sprite images to your scene.loadImages back in your bootstrap function, just to avoid the game starting before all sprites have been loaded in to memory.

scene.loadImages([
	'tank.png',
	'slug.png',
	'missile.png',
	 ], function() {

Hopefully, if everything went to plan your game should now look and play something like this:

Now the game is more a less playable and pretty much all our original goals have been completed. I just wanted to add a few final tweaks, that should hopefully make the game that little bit more enjoyable to play. 90% of this change just being the addition of a Score and the visibility of your hp.

To add the HP & score box, I added the following html in to the page (under the game_map div).

<div id='score_board'>
	<div id='score'>0</div>
	<div >Health: <span id='hp'>5</span>/5</div>
</div>

Combined with the following CSS

#score_board {position:absolute;width:100px;right:0;top:0;color:#fff;z-index:9999;}
#score_board div {text-align:center;}
#score{font-size:5em;font-weight:bold;}

This just adds a div on the top right, with a big number to indicate the score and a smaller line of text to tell you your hp.¬†To make both the HP & score counter work, add a score attribute to the main game object (below “this.inputs”).

this.score = 0;

Then in the updateMonsters method, just below where we removed destroyed monsters from the game, add the following code.

engine.score++;
document.getElementById('score').innerHTML = engine.score;

Then, a little¬†further¬†down where hp is being deducted from your own tank (just under “engine.mytank.hp–;”) add

document.getElementById('hp').innerHTML = engine.mytank.hp;

to keep your HP in sync with the UI.

And last but not least, to make the loosing screen a little less annoying, replace the “game over” alert with:

document.body.innerHTML ='<div class="end"><h1>Game Over!</h1><div>Your Score: '+engine.score+'</div></div>';

And add the following bit of additional css to your styles:

.end {
	background-color:#fff;
	color:#000;
	width:400px;
	text-align:center;
	margin-top:50px;
	padding:10px;
}

With that complete, for the purposes of this tutorial. Your done! Congratulation, you should now have a simple tank game that looks more or less like this:

Keep in mind, at this point the game is still really basic, so I encourage you to have a go at developing it further. Just as a few ideas of things you may want to consider adding:

  • Sounds for when firing the cannon, driving and blowing up monsters.
  • More monsters types, and maybe some smarter monster behaviours.
  • High scores?
  • Some terrain, to drive around.
  • Mobile support (Sprite.js) adds some basic stuff for mobile, but the game would¬†benefit¬†a lot from a properly mobile oriented control system.

All code seen in this tutorial and comprising the demos is released as Open Source under the MIT Licence. The source for all demos can be found here.

Thanks for reading,