This talk will be mostly about my experience on how I moved from Flash to using HTML5 as a platform for my game which includes libraries that I've used and techniques I've contrived during my learning experience.
I will be using my game, Wings Of Lemuria, as an example for this talk.
It's something I started out in late 2009 as a pet project with the purpose of pushing the limitations of what I can do creatively and technically. It's a turn-based game.
I initially built the prototype in Flash with ActionScript 3.0 and thought the concept was playable enough. I decided to dedicate some time to it and hopefully get something up for people to try out. My first problem surfaced when some parts of the animation became choppy and CPU intensive because I was using Sprite objects and MovieClips.
Upon researching, I discovered a technique used traditionally by game developers called Blitting where you copy some pixels and paint it over a raster canvas.
I developed my own blitting library in Flash and was pretty happy with the results due to its incredible performance.
However, the limitation was that you can't scale or rotate any pixel data since you're just storing them into a buffer and re-painting them using bitmapData.copyPixels
command. So in a way, my efforts became useless.
At some point, I grew frustrated with the project and decided to put it into hiatus.
After a while and in mid-2011, HTML5 was becoming more prevalent to the Flash community as an alternative for building rich interactive media. So I tried it, read the Canvas 2D API and wrote a quick demo that worked with the sprite animations I've already made months prior.
The performance was neither better nor worse. But the Canvas 2D API allowed me to scale, rotate and animate the bitmap data the way I want to which solves the problem I had before in my blitting library.
Also since JavaScript is a scripted language, there's no compiling process which enabled me to code and debug faster.
I felt comfortable with my new found technology and invested a year's time learning it.
In the end, I went with it and decided to develop my game in HTML5.
Playable in both desktop and mobile.
Huge potential in terms of market share. Google, Apple, and Microsoft are supporting it.
You can use a library and still have access to the annotated version of the code. Helps me become a better developer by learning from the work of experienced programmers.
Months that preceeded my decision to build my game in HTML5, is knowing what available libraries that are already out there. As much as possible, I avoid the itch to re-invent the wheel so I could focus on the actual product itself.
"Any time you're solving a problem that's already been solved, you're being inefficient."
Only invent something when necesarry or when your idea solves a particular set of problems.
HTML5 utility belt. It includes a canvas library, a sound manager, a tweening engine, and a preloader utility.
EaselJS works as a canvas library. It has an API similar to Flash.
ActionScript
var container:Sprite = new Sprite();
stage.addChild(container);
JavaScript with EaselJS
var canvas = document.querySelector('canvas#game');
var stage = new createjs.Stage(canvas);
var container = new createjs.Container();
stage.addChild(container);
ActionScript
var sound:Sound = new Sound(new URLRequest('sound.mp3'));
sound.play();
JavaScript with SoundJS
var sound = new createjs.SoundJS();
sound.play('sound.mp3');
without SoundJS using the Audio
API
var sound = new Audio('sound.mp3');
sound.play();
without SoundJS using the AudioContext
API for more sound control.
var buffer = null;
var context = new webkitAudioContext();
function loadSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
buffer = buffer;
}, onError);
}
request.send();
}
loadSound();
private var loader:Loader;
public function Main() {
load = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.onComplete);
loader.load('image.png');
}
private function onComplete(e:Event):void {
trace('preload complete!');
}
JavaScript with PreloadJS
var loader = new createjs.Preloader();
loader.onComplete = function() {
console.log('preload complete!');
};
loader.loadFile('image.png');
loader.load();
JavaScript without PreloadJS
var image = new Image();
image.onload = function() {
console.log('preload complete!');
};
image.load('image.png');
For loading dependencies using the AMD pattern.
For taking care of the nesting and vendor prefixes.
Express JS for running the server application, and Socket.IO for managing WebSockets and its fallback protocols.
For Ninja style HTML/CSS development.
This isn't part of web design, but I use this to host my node.js app.
I still rely on the Flash IDE for animating my sprites mainly because it's something I'm fairly familiar with. In order to get this to work with the HTML5 canvas, I publish the SWF and load it into Zoé which is a Sprite sheet exporter of the CreateJS suite. It exports a JSON file with the frameData in it, along with the compressed PNG image.
For static bitmap elements, I use a software called TexturePacker which is widely used in the Corona SDK community for game development in iOS and Android. It basically does the same thing as Zoé with the exception that I don't need to import the individual elements in Flash anymore. It reads a directory automatically.
In Flash, one of the things I liked is how everything is packaged and easily managed as class files. In JavaScript, there's no official way of doing this. One solution is using namespaces for your app. Problem is, it's still accessible at the global scale.
Luckily we have AMD to the rescue. It allows the code to be separated and modularized as much as possible.
Modules are asynchronusly loaded during development then concatenated, minified and baked during deployment.
This solution enables me to debug the JavaScript code easily.
define(moduleId, dependencies, definition);
define('carClass', ['settings'], function(settings) {
return function() {
var Car() {
this.speed = settings.speed;
}
return Car;
}
});
I separated the UI from the game canvas for a variety of reasons.
- It's easier to set the texts and styling of the UI through CSS.
- CSS3 transitions and transforms are hardware accelerated.
- CSS3 Keyframe animations are more maintainable than hardcoded JavaScript animation behaviors.
For images, I used a CSS sprites for combining PNG assets into one file. This reduces HTTP requests which is perfect for a browser-based game.
Although not necesarry, stylus provides me with a minimalistic coding environment for writing CSS allowing me to code faster.
- Variables
- Computation
- Mixins
- Nesting
- Optional colon-less and semi-colonless syntax
- Optional indented syntax
- Not as mature as SASS with Compass
- No support for image spriting
- Pre-requisite knowledge has high learning curve
I chose node as my web server because it uses JavaScript. It allows me to use client-side code with the server and vice versa.
- Simplicity and ease of use
- Ease to configure routes
- Sinatra-like design
- Has fallback mechanisms
- Uses event emissions
My name is James Florentino and I'm a creative and passionate front-end designer who's currently working for a startup building web-based chat applications. My roots originate from the Flash design era but now have fully migrated to utilizing HTML5 technologies for web applications and games.