Game dev competition: js13k

js13kLooking for inspir­a­tion to make some­thing this month? The js13k game com­pet­i­tion chal­lenges developers to cre­ate a fully func­tion­ing HTML5 game in under 13 kilo­bytes and star­ted on Wednesday.

Js13kGames is a JavaScript cod­ing com­pet­i­tion for HTML5 game developers. The fun part of the compo is the file size limit set to 13 kilo­bytes. Theme for 2014 is The Elements: Earth, Water, Air and Fire. The com­pet­i­tion star­ted at 13:00 CEST, 13th August 2014 and will end at 13:00 CEST, 13th September 2014. See the Rules for details, good luck and have fun!

There’s been a couple of good posts come out of the com­pet­i­tion so far that are worth a read, even if you’re not look­ing to compete:

* How to Minify Your HTML5 Game for the Js13kGames Competition by Andrzej Mazur
* Arcade Audio for js13kGames by Jack Rugile

It def­in­itely looks like a fun chal­lenge, so if you’ve got a spare week­end or two between now and the 13th you should give it a shot!

Chrome touchcancel event & scrolling instead of touchmoving

When you’re devel­op­ing for Chrome for Android, one of the little quirks is that some­times your touch­move events appear to stut­ter and get can­celled almost imme­di­ately. This is evid­ent when you’re try­ing to pan or slide a can­vas, except the Chrome for Android stops after 300 ms and starts scrolling the page instead.

This is actu­ally by design due to the way Chrome pre­vents pages from break­ing scrolling, and it’s fairly easy to fix by call­ing event.preventDefault() in your touch­move handler.

myElement.ontouchmove = function(e){
    // Do things
    e.preventDefault();
}

Using Pixi.js

Pixi.js is a pretty cool low-level game engine that uses Canvas or WebGL to render 2D graphics.

Pixi.js doesn’t give you dir­ect access to the ori­ginal event, so if you’re try­ing to drag ele­ments on a Pixi can­vas, call­ing preventDefault() on your event gives you a func­tion not defined error.

Pixi actu­ally passes the ori­ginal event as e.originalEvent, so for Pixi touch­move events you should use the fol­low­ing code;

myPixiElement.touchmove = function(e){
    // Do things
    e.originalEvent.preventDefault();
}

Further read­ing

For more inform­a­tion on why Chrome is break­ing the touch­move hand­ler, check out Wilson Page’s dis­cov­ery of the 300 ms touch­move can­cel­la­tion or more gen­er­ally the HTML5Rocks touch and mouse primer.

Installing NPM packages globally on Windows

For some reason (per­haps in multi-user envir­on­ments) a default install of Node on Windows may not put the cor­rect NPM global pack­age loc­a­tion in the path.

If you’re hav­ing issues like the following:

'grunt' is not recognized as an internal or external command,
operable program or batch file.

Where Grunt might be any global pack­age, such as Browserify, add the fol­low­ing loc­a­tion to your path:

Windows 7: C:\Users\{username}\AppData\Roaming\npm

Replace {username} with your cur­rently logged in user.

This should make global Node mod­ules dis­cov­er­able and usable on your system.

Interactive SVG and the ABC NRL Infographic

I recently worked on an infographic for ABC Grandstand Sport, show­ing an accu­mu­lated field of all the scores for each of the NRL grand finalists.

The Tech

The infographic uses a plain SVG file and a small amount of Javascript to per­form the task. The imple­ment­a­tion is actu­ally quite simple, with most of the heavy lift­ing to gen­er­ate the graphic being done on my PC before being uploaded to the server as a static SVG.

The ini­tial stages of the pro­ject involved access­ing the data and turn­ing it into some­thing we could visu­al­ise. I wrote a Node script to access the SportsFlash API and pull down every game of the sea­son. From there I cre­ated a Fiddle to do up some quick visu­al­isa­tions show­ing how the points relate to each other.

From there my col­leagues Ben and Lincoln dis­cussed how best to present the inform­a­tion, and worked on some actual designs.

Designing with SVG

Ben used Fireworks to cre­ate a few dif­fer­ent SVG vari­ations includ­ing all the line mark­ings to scale and a back­ground pat­tern we could repeat to save on bandwidth.

Fireworks out­put to SVG where I used Inkscape to make a few changes includ­ing cre­at­ing some empty group ele­ments for the auto-generated con­tent I was going to add later.

Adding the Data

I wrote another Node script to san­it­ise all the data from the SportsFlash API and sep­ar­ate out the two teams’ plays onto either side of the field.

Once the data was sor­ted it was a fairly simple mat­ter of cre­at­ing a circle ele­ment for each point, as well as a path link­ing each con­nec­ted dot together.

These were placed in two sep­ar­ate groups for convenience.


<circle r="7" cx="836" cy="406" id="t-1-e-3-0" class="first t-1-e-3" fill="maroon"><title>Round 14 - Try scored by Jorge Taufua  (vs Canterbury-Bankstown Bulldogs)</title></circle>

Styling and Interaction

SVG is styleable with CSS so we could tweak the design on the fly, and even­tu­ally settled on what you see here.

Traditionally we’ve used client-side code such as D3 to imple­ment inter­act­ives and infograph­ics. This time the SVG was already gen­er­ated so all it needed was a couple of onclick events to change change the CSS when someone clicked/hovered a point.

This meant there was actu­ally very little code required to imple­ment the inter­ac­tion, and pos­sibly points to the abil­ity to add anim­a­tion and inter­activ­ity to design-heavy infograph­ics in the future.

Browser Support & jQuery

Because we’re using SVG for this infographic, it only sup­ports IE9 and above. We added altern­at­ive con­tent for older browsers in the form of a static image, which is rel­at­ively easy to add using the <object> tag.

<object width="100" height="100" data="myfile.svg">
    <img src="myfile.png" alt="The roosters prove the long range threat."/>
</object>

One of the gotchas that I hit at the last minute was my use of jQuery didn’t work prop­erly with the external SVG file. We’re using an old ver­sion which doesn’t sup­port SVG well at all, so I had to rewrite bits of code to use the document.querySelectorAll call.

In future I won’t be using jQuery for SVG inter­act­ives because newer ver­sions of Javascript sup­port cool stuff like forEach, indexOf and querySe­lector, and there’s no need to sup­port older browsers in this case. Furthermore, pure Javascript can be included inside the SVG file which means more port­ab­il­ity and less dependencies.

Conclusion

While there’s a few things I’d do dif­fer­ently next time, I’m pretty happy with the res­ult here. The end product is a stan­dalone, inter­act­ive graphic that we can reuse elsewhere.

The browser sup­port is fairly good for this kind of thing these days, and the abil­ity to spe­cify fall­back con­tent is great for those that don’t sup­port it. There’s really no reason not to be using SVG for these kinds of things.

Bugs and errata

The Race

One inter­est­ing bug I noticed was that Chrome calls the window.onload method before the SVG doc­u­ment has fully loaded. This only seems to hap­pen once the HTML doc­u­ment has cached and can be repro­duced by click­ing back and for­ward to reload the page from cache.

The fix isn’t straight­for­ward and I ended up adding a quick timeout on load, but optim­ally you’d be able to bind to a load event on the object. I’ll look into this and report back.

Adobe SVG

The Adobe SVG plu­gin presents prob­lems for devel­op­ing inter­act­ive SVG graphics.

With this plu­gin installed, a SVG doc­u­ment embed­ded using an <object> ele­ment doesn’t load in Chrome and falls back to whatever altern­at­ive con­tent you’ve specified.

Furthermore, even though the SVG doc­u­ment loads in IE it doesn’t present the same API as a reg­u­lar SVG doc­u­ment so it requires extra code to get working.

I haven’t found any real work­arounds for this other than unin­stalling the Adobe SVG viewer. This plu­gin was dis­con­tin­ued with XP in 2009 so it shouldn’t be used these days, how­ever I don’t have any mar­ket share stats for this one.

Apache & SVGZ

If you’re using Apache and want to use svgz files in your site, add this to your con­fig­ur­a­tion .htac­cess file:

AddType "image/svg+xml" .svgz
AddEncoding gzip .svgz

This firstly sets the content-type and secondly instructs the browser to unzip it once it’s downloaded.

Offline Apps

One of the things a lot of people don’t real­ise about web apps is that they don’t actu­ally have to run off a server. These days with little effort at all you can write a web app that runs dir­ectly on the tar­get com­puter which reduces infra­struc­ture costs and makes the app more respons­ive for the end user.

There are a num­ber of reas­ons you might make an off­line app, but it’s espe­cially use­ful in cases where web access may be lim­ited (kiosks, trade shows, etc), some­where imme­di­ate action might be required (such as point of sales sys­tems, doctor’s sur­ger­ies), or where the func­tion­al­ity just makes sense to per­form on the cli­ent side (such as cal­cu­lator apps, to do lists, image edit­ors etc).

How do I make an off­line app?

There’s a few tech­no­lo­gies that let you do this, for instance:

  • Web Stores such as the Chrome Web Store
  • Packaged desktop solu­tions like node-webkit and the now-defunct Adobe Air
  • Hosted, but off­line applic­a­tions delivered from your web­server using con­ven­tional meth­ods but cached for off­line use using AppCache.

I’m not going to focus on any par­tic­u­lar tech­nique, rather than go through some gen­eral tac­tics you can use to cre­ate a fully off­line app.

What’s an off­line app anyway?

An off­line app is exactly what it sounds like, it runs on your com­puter like a reg­u­lar app, regard­less of your Internet connection.

These apps use tech­no­lo­gies such as Javascript, local stor­age and cache mani­fests to keep the app on the cli­ent side. These apps can also be used to update data on the server but might util­ise cach­ing to save web requests until the user is online. The primary pur­pose of an off­line app doesn’t require an Internet con­nec­tion to run.

Offilne apps are denoted in the Chrome web store by a lightning bolt.

The Chrome Web Store denotes off­line apps with a light­ning bolt icon. You can tick a box when you pub­lish your app, put­ting “Offline” in the name is optional.

How to make my web app offline

There’s a bunch of tech­niques you can use, but the most basic one is ensur­ing all your applic­a­tion logic is executed in the browser, and that there are no server-side com­pon­ents (such as log-in, stor­age, processing).

A good start might be to make sure your app runs straight off your hard disk. If you can double-click your HTML file and your web app launches and oper­ates cor­rectly then there’s a good chance it’s going to work great as an off­line app. This isn’t a hard and fast rule though, as depend­ing on your plat­form you may have more or less func­tion­al­ity at your disposal.

Once your applic­a­tion is built, one of the more standards-based approaches is to use App Cache to instruct the browser to cache your app for off­line use.

Specific Technologies for Offline Apps

Some spe­cific tech­no­lo­gies exist that work really well for off­line web apps.

TechnologySupportDescription
AppCacheIE10+AppCache lets you spe­cify the files that need to run off­line. The browser caches these files for sub­sequent app loads.
Web StorageIE8+Web Storage lets you store per­sist­ant data with an inter­face akin to an asso­ci­at­ive array.
File APIsIE10+/Android 3+Read, manip­u­late and write files to disk. Especially use­ful in con­junc­tion witht he drag & drop API.

Of course there’s a bunch of other tech­no­lo­gies, both stand­ard and pro­pri­et­ary which you can use to make your web app rock on vari­ous plat­forms. If you don’t need gen­eral web sup­port, check out the doc­u­ment­a­tion for the web app stores or ren­der­ing engines you’re plan­ning to support.

Ultimately, the best way to make an off­line web app is to break the ties with that server-side code. It’s a shift in think­ing from tra­di­tional web devel­op­ment, but the pay­offs can be huge.

Practical SVG Manipulation for use in Games

I tried to do a demo of some of the SVG stuff I’ve been play­ing with recently at BrisJS, but due to a com­edy of errors I was unable to do much more than talk about it. So I figured I’d write up some of my find­ings here.

SVG in Canvas

Basically what I’ve been doing recently is exper­i­ment­ing with SVG sprites for use in HTML5 Canvas games.

SVG is an XML-based vec­tor image format that’s often used in graphs and inter­act­ive fea­tures, but it’s actu­ally really good as a graph­ics inter­change format for use in games because it can be manip­u­lated really eas­ily with Javascript.

Here’s a SVG image so you can check it out. You can inspect it in the DOM inspector which will show you the ele­ments and attrib­utes we can manip­u­late with JS.

I drew it in Inkscape, but because it’s all XML-based we can adjust the col­ours and styles of the image dynam­ic­ally in the browser.

A Quick Demo

I’ve put together a quick demo of the tech­nique which shows a basic col­our­ising of col­our mapped images such as the one above.

Changing the col­our of SVG images is a pretty simple fea­ture which people use all the time in reg­u­lar SVG oper­a­tions. Generally this might be used to cre­ate a rollover effect or adjust the col­our of a bar in a dough­nut graph, but with this demo you can choose two col­ours and use them to col­our­ise the entire SVG image.

Check it out at assets.kyd.com.au/svg-recolour/demo/demo.html

How it works

I’ve used the col­or­box lib­rary to per­form col­our modi­fic­a­tion oper­a­tions on the input col­ours to gen­er­ate high­lights and shades, which cor­res­pond with the vari­ous key col­ours in the source image.

I’ve then per­formed a basic string search and replace on the tar­geted col­ours to make the changes to the image so it uses the col­ours you’ve chosen rather than the ori­ginal col­ourmap. This some­thing that could very nicely be done with jQuery select­ors for instance, but isn’t some­thing I’ve had time to do yet.

  • 1-or8
  • 3-or8
  • 5-or8
  • 7-or8
  • 10-or8
  • 11-or8
  • 10-or8
  • 7-or8
  • 5-or8
  • 3-or8

The demo also has a game time fea­ture, which per­forms fur­ther col­our modi­fic­a­tions based on the in-game “hour” of the day. So for instance at mid­night the col­ours you ori­gin­ally chose would be heav­ily desat­ur­ated and tin­ted with a blue col­our to sim­u­late night time. In the even­ing, sun­set adjusts the col­ours to add oranges and reds before fad­ing into night.

The final fea­ture of the demo is a little logic which flicks lights on and off once it gets dark, and altern­ates neon signs on and off at intervals.

And then?

SVG tends to be a little slow in select browsers, and espe­cially so with com­plex images which you can prob­ably see in the demo. While this might be okay when you’re just dis­play­ing a static image, it becomes totally unac­cept­able in high-performance situ­ations where you need to draw it sixty times per second.

We can get around this issue by pre-drawing the SVG images to another Canvas object (not pic­tured). This off-screen Canvas holds a bit­map rep­res­ent­a­tion of the image and con­sequently renders to our game can­vas much faster because the heavy lift­ing has already been done.

We can take this a step fur­ther and render all the vari­ations of a par­tic­u­lar image if we have enough memory, res­ult­ing in a long ini­tial load but a fast game once it’s done.

As a side note, using this method trig­gers addi­tional secur­ity pre­cau­tions in the browser which may pre­vent you from per­form­ing some game-related tasks.

Where from here?

Ultimately I’d like to imple­ment this in my game engine and pro­ced­ur­ally gen­er­ate com­plex game worlds, but for now this is just a concept.

I’ve also been play­ing with trans­form­ing tex­tures and apply­ing them to objects within the SVG envir­on­ment as a sort of 2D tex­ture map­ping, but I’m not espe­cially happy with the res­ults so I think I’m going to stick with vec­tor graph­ics for now.

warehouse-toy

Anyway, if you like the idea you should totally have a play and see what you can come up with. You can also check out my code on GitHub if you’d like to see exactly what I’ve done.

A private key for specified extension already exists

So your Chrome app is ready to go? Awesome! You’re pack­ing it up to test on all your devices when sud­denly… A private key for specified extension already exists. Reuse that key or delete it first.

Pack Extension Error

The Pack Extension Error is actu­ally a pretty simple one to get around. It’s caused because the exten­sion has already been packed in the past, and Chrome auto­mat­ic­ally cre­ated a private key for the package.

The auto­mat­ic­ally cre­ated key has the same file­name as the folder you selec­ted, and is in the same par­ent folder as your exten­sion, You can choose to either delete it (and another will be cre­ated next build) or select the key from the dialog.

Chrome CRX Keys

Each Chrome app is signed with a key, and if you don’t spe­cify one it’s auto­mat­ic­ally cre­ated for you.

You can see from the com­mand line below that the pack-extension com­mand cre­ates both a crx (exten­sion) and a pem (key) file.

$ ls
build-chrome  build-chrome.sh  chrome.zip  libs
$ google-chrome --pack-extension=build-chrome/
Created the following files:
Extension: build-chrome.crx
Key File: build-chrome.pem
Keep your key file in a safe place. You will need it
to create new versions of your extension.
$ ls
build-chrome      build-chrome.pem  chrome.zip
build-chrome.crx  build-chrome.sh   libs

The next time we run the pack-extension com­mand above it will fail because we also need to spe­cify the --pack-extension-key para­meter like so:

$ google-chrome --pack-extension=build-chrome/ --pack-extension-key=build-chrome.pem

None of this is par­tic­u­larly obvi­ous from within Chrome itself, which just gives you the unhelp­ful Pack Extension Error dia­log box. It’s a fairly easy fix though, just hit “Browse…” and the pem file should be right there.

Chrome SecurityError: DOM Exception 18

Of the more cryptic and frus­trat­ing Chrome errors are the SecurityErrors. These bad boys show up at inop­por­tune times and ruin your day with an “Uncaught Error” and a big red excep­tion killing your code in its tracks.

So you’re play­ing around with HTML5 Canvas when all of a sud­den you’re get­ting a Uncaught Error: SecurityError: DOM Exception 18 in the con­sole. What’s it mean?

DOM Exception 18

This excep­tion is thrown when your code is try­ing to access some­thing it shouldn’t, includ­ing cross-domain resources or stuff on your local filesystem.

Once you hit this one you will either need to loosen your browser secur­ity set­tings which is never optimal, or find out how to work around it.

HTML5 Canvas & Exception 18

Which brings us to the case of the com­plain­ing can­vas. Loading images into your can­vas from another domain will “taint” your can­vas, mean­ing any attempts to read the can­vas back again will fail with this error.

This is because your Javascript adheres to a same-origin policy to increase secur­ity. It’s essen­tially done as a con­tain­ment meas­ure so that a rogue script can’t use your browser to access resources you’re authen­tic­ated against.

Hypothetical Canvas Attack

For instance, if I hypo­thet­ic­ally wanted to access your email and your browser didn’t pre­vent cross-site-scripting, I could per­form a $.ajax('http://gmail.com'). This would pull down your logged-in gmail page, and then I could send all your email mes­sages back to my server.

The same applies for images.

This fea­ture pre­vents a rogue site pulling down your Facebook pho­tos, for instance (which again could hypo­thet­ic­ally be done), ren­der­ing them to a can­vas in order to get a hold of the bin­ary image data then send­ing it back to the attack server.

So the second you draw a third party image to your can­vas, you can no longer read back the res­ult­ing image.

The easy solu­tion is to host all your images loc­ally or if that’s not pos­sible you could use a script to pull down and serve the images on your behalf.

SVG Image & Canvas SecurityError

If you’re play­ing around with draw­ing SVG to Canvas in Chrome, you may also run into this secur­ity error, but for a dif­fer­ent reason.

Chrome bombs out printing a SVG

This appears to be a Chrome-specific fea­ture (per­haps a bug?) whereby the SVG doc­u­ment is con­sidered to be of dif­fer­ent ori­gin to the can­vas. This goes a step fur­ther than simply check­ing the ori­gin of the url, it out­right black­lists all SVG images regard­less of ori­gin, includ­ing images encoded in data: uris.

This means that whenever you paint a SVG to your can­vas you’re taint­ing your can­vas and won’t be able to pull inform­a­tion back out of it. This severely hinders efforts to use SVG images as dynamic game sprites, and can be frus­trat­ing to debug because it isn’t imme­di­ately obvi­ous what’s happening.

Working around the same-origin policy

It’s actu­ally pos­sible to spe­cify a cus­tom policy to over­ride the default same-origin beha­viour. This is done via cus­tom HTTP head­ers, which means you’ll need access to your web server to make these changes.

I haven’t yet exper­i­mented with this tech­nique myself, but you can read about it on HTML5 Rocks. I’ll be play­ing with this in the fol­low­ing days, but if you’ve had luck with this tech­nique, do let me know in the comments.

SVG images on a HTML5 Canvas

I wrote a while back about using SVG sprites in a HTML5 Canvas game, but there’s actu­ally a bet­ter way of doing it that doesn’t involve an external JavaScript lib­rary like canvg.

Rendering SVG to a HTML5 Canvas

It’s trivi­ally easy to load up a SVG image as a JavaScript Image ele­ment and draw that to the can­vas. There’s a few ways you can do this, with the easi­est being:

var source = new Image();
source.src = 'http://example.org/myfile.svg';
source.width = '100';
source.height = '100';

This example loads the source file into a new Image ele­ment, ready to be applied to a Canvas the same as any other image.

This takes the hassle and unpre­dict­ab­il­ity out of using a third party lib­rary because it uses the nat­ive browser’s SVG cap­ab­il­it­ies, and will prob­ably be faster to boot.

There are still a few quirks when it comes to load­ing SVG images this way, in par­tic­u­lar the browser may not get the width and height right. In the example above we’ve hard-coded the dimensions.

Actually Rendering to a Canvas

To actu­ally draw a SVG image to a can­vas, it’s the same as any other Image object.

// Set up our canvas on the page before doing anything.
var myCanvas = document.createElement('canvas');
myCanvas.width = 640;
myCanvas.height = 480;
document.getElementsByTagName('body') [0].appendChild(myCanvas);
// Get drawing context for the Canvas
var myCanvasContext = myCanvas.getContext('2d');
// Load up our image.
var source = new Image();
source.src = 'http://example.org/myfile.svg';
source.width = '100';
source.height = '100';
// Render our SVG image to the canvas once it loads.
source.onload = function(){
	myCanvasContext.drawImage(source,0,0);
}

This code loads the SVG image, cre­ates an image in the <body> and renders the SVG to the Canvas ele­ment. The onload is import­ant because it makes sure the image has com­pletely loaded before try­ing to draw it.

Rendering Dynamically Created SVG

If you’re going to be dynam­ic­ally cre­at­ing or modi­fy­ing your SVGs, this tech­nique won’t work.

Any SVG ele­ments loaded as Images no longer have a DOM access­ible for you to manip­u­late, so you will need to pre-load the SVG file and manip­u­late it prior to load­ing it in an Image. You can use any num­ber of tech­niques here such as XHR which I won’t go into.

The dif­fi­cult bit is load­ing the mod­i­fied SVG string back into an Image in order to plop it down onto a can­vas. The solu­tion to this is base64 encod­ing the image and cre­at­ing a Data URI.

The fol­low­ing code will cre­ate a data URI by base64 encod­ing the SVG string:

// My SVG file as s string.
var mySVG = '<svg […]';
// Create a Data URI.
var mySrc = 'data:image/svg+xml;base64,'+window.btoa(mySVG);
// Load up our image.
var source = new Image();
source.src = mySrc;

The btoa func­tion is a nat­ive func­tion to encode a string to base64, but is not offi­cially stand­ard­ised yet. It is a part of the WHATWG liv­ing stand­ard and is sup­por­ted in all SVG/Canvas-capable browsers with the excep­tion of IE9. If you require back­wards com­pat­ib­il­ity or IE9 sup­port there are count­less base64 lib­rar­ies out there you can use instead.

Some Caveats to using SVG on a Canvas

This tech­nique is great provid­ing you don’t require sup­port for IE8, in which case you’re out of luck and should look into using a third party ren­der­ing lib­rary in con­junc­tion with a Canvas shim.

If you’re only look­ing at tar­get­ing mod­ern browsers like Android 3+ and IE9+ this tech­nique will work per­fectly and give you the power and speed of the browser’s nat­ive SVG implementation.