Editors Note: The tutorial is a little bit outdated now, but it still works. However if you would like to learn more on this topic and get a more detailed verison plus all the extras and resources, you should check out my ebook: From Zero to the Appstore – Blueprints for an HTML5 Game.

Here I’m starting a series of 4 articles on how to create a small game with EaselJS that “can” run on your mobile device (unfortunately it won’t run on all mobile devices) – however I also plan on a future posting on how to use technologies like cocoonJS to create a WELL-PERFORMING native app from this.

The FINAL result

The result is going to look similar to this (but with better code!) – In case you take a look at the source-code: This is NOT a good example on how to code cleanly – I did this as a quick mashup to try out a few things. – You can also do another jump, while in the air:

To test this on your mobile device, point your mobile browser to: http://demos.indiegamr.com/jumpy

The result of Part 1&Part 2

Let’s get started with the basics – Setting up the Stage

Working with EaselJS is pretty simple, especially when you worked with ActionScript3 before, as a lot of the methods and classes are based on ActionScript3-equivalents. So basically the first thing you have to do in order to see a result, is to create a canvas-element and set up the “Stage” here is how this can be done:

Initializing the Stage // creating the canvas-element canvas = document.createElement('canvas'); canvas.width = 500; canvas.height = 250; document.body.appendChild(canvas); // initializing the stage stage = new Stage(canvas); 1 2 3 4 5 6 7 8 // creating the canvas-element canvas = document . createElement ( 'canvas' ) ; canvas . width = 500 ; canvas . height = 250 ; document . body . appendChild ( canvas ) ; // initializing the stage stage = new Stage ( canvas ) ;

However, if you tried this out, it wouldn’t bring you that much of a result, because in order to actually see something the Stage has to be ‘updated’ (stage.update();) by EaselJS, also this is something, that has to be done every frame – so to do that, we can setup an event, that will update the Stage every frame.

Ticker.setFPS(30); Ticker.addListener(tick); function tick(e) { stage.update(); } 1 2 3 4 5 Ticker . setFPS ( 30 ) ; Ticker . addListener ( tick ) ; function tick ( e ) { stage . update ( ) ; }

Great! Now we have a stage, that is updated with 30 frames/second.

More basics – Adding something to the stage

Now that we’ve setup the Stage, we can obviously still see nothing, because there is no object/image there to display.

The basic flow of doing this is to: 1) Preload an Image then 2) Create an DisplayObject with that image and finally 3) add this DisplayObject to the Stage(or another Container)

Preloading an image var img = new Image(); img.onload = onImageLoaded; img.src = 'asset/myImage.png'; function onImageLoaded(e) { var myBitmap = new Bitmap(img); stage.addChild(myBitmap); } 1 2 3 4 5 6 7 8 var img = new Image ( ) ; img . onload = onImageLoaded ; img . src = 'asset/myImage.png' ; function onImageLoaded ( e ) { var myBitmap = new Bitmap ( img ) ; stage . addChild ( myBitmap ) ; }

Preloading:

Some might ask here, why I’m not introducing PreloadJS to preload all the assets (or in this case: one asset) – well PreloadJS is a very nice way to do so – and I also recommend using it for some projects, but I tried running the app with the cocoonJS-launcher and receiveed a big load of Errors from cocoon(due to cocoon’s limited JS-parsing). Now this is NOT the fault of PreloadJS, however since preloading assets is nothing super-complicated, that requires super-extensive knowlege(basically one function), I chose to use an own 5-line implementation to achieve this.

Great! – So how do I make a game from this?

Well, a typical game usually needs the following things:

Part 1: User-Input (Keystrokes, MouseClick, Touch) & Movement

Part 2: Collisions between objects

Part 3: Animations

User Input

To listen to userinput-events we first have to distinguish if the device is a touch-device or has a regular screen and add the according event listeners.

adding touch/click/key listeners //check for a touch-option if ('ontouchstart' in document.documentElement) { canvas.addEventListener('touchstart', function(e) { handleKeyDown(); }, false); canvas.addEventListener('touchend', function(e) { handleKeyUp(); }, false); } else { document.onkeydown = handleKeyDown; document.onkeyup = handleKeyUp; document.onmousedown = handleKeyDown; document.onmouseup = handleKeyUp; } function handleKeyDown(e) { // execute things on KeyDown // e.g. hero.jump(); } function handleKeyUp(e) { // execute things on KeyUp } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 //check for a touch-option if ( 'ontouchstart' in document . documentElement ) { canvas . addEventListener ( 'touchstart' , function ( e ) { handleKeyDown ( ) ; } , false ) ; canvas . addEventListener ( 'touchend' , function ( e ) { handleKeyUp ( ) ; } , false ) ; } else { document . onkeydown = handleKeyDown ; document . onkeyup = handleKeyUp ; document . onmousedown = handleKeyDown ; document . onmouseup = handleKeyUp ; } function handleKeyDown ( e ) { // execute things on KeyDown // e.g. hero . jump ( ) ; } function handleKeyUp ( e ) { // execute things on KeyUp }

This is pretty straight forward and should widely explain itself.

Movement

To create movement, the simples thing to do is e.g. to alter the position of an object a little bit every frame, just like this:

adding movement function tick(e) { //this will move the object down by 1 pixel myBitmap.y += 1; //this will update the stage stage.update(); } 1 2 3 4 5 6 function tick ( e ) { //this will move the object down by 1 pixel myBitmap . y += 1 ; //this will update the stage stage . update ( ) ; }

However in order to get the whole thing not too messy, once there are more objects involved in the scene, we should setup an own class for each object, or at least each object that is moving, as an example I put together the following:

Hero.js (function (window) { function Hero(image) { this.initialize(image); } Hero.prototype = new Bitmap(); // save the original initialize-method so it won't be gone after // overwriting it Hero.prototype.Bitmap_initialize = Hero.prototype.initialize; // initialize the object Hero.prototype.initialize = function (image) { this.Bitmap_initialize(image); this.name = 'Hero'; this.snapToPixel = true; } // we will call this function every frame to Hero.prototype.tick = function () { this.y += 1; } // this will reset the position of the hero // we can call this e.g. whenever a key is pressed Hero.prototype.reset = function() { this.y = 0; } window.Hero = Hero; } (window)); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ( function ( window ) { function Hero ( image ) { this . initialize ( image ) ; } Hero . prototype = new Bitmap ( ) ; // save the original initialize-method so it won't be gone after // overwriting it Hero . prototype . Bitmap_initialize = Hero . prototype . initialize ; // initialize the object Hero . prototype . initialize = function ( image ) { this . Bitmap_initialize ( image ) ; this . name = 'Hero' ; this . snapToPixel = true ; } // we will call this function every frame to Hero . prototype . tick = function ( ) { this . y += 1 ; } // this will reset the position of the hero // we can call this e.g. whenever a key is pressed Hero . prototype . reset = function ( ) { this . y = 0 ; } window . Hero = Hero ; } ( window ) ) ;

With the Hero-class implemented, we can now create a hero object and apply some interaction, all together it would look like this:

Game.js if ('ontouchstart' in document.documentElement) { canvas.addEventListener('touchstart', function(e) { handleKeyDown(); }, false); } else { document.onkeydown = handleKeyDown; document.onmousedown = handleKeyDown; } var stage, canvas, hero, img = new Image(); function init() { canvas = document.createElement('canvas'); canvas.width = getWidth(); canvas.height = getHeight(); document.body.appendChild(canvas); stage = new Stage(canvas); img.onload = onImageLoaded; img.src = 'assets/hero.png'; } function onImageLoaded(e) { hero = new Hero(img); stage.addChild(hero); hero.reset(); Ticker.setFPS(30); Ticker.addListener(tick); } // move the hero down by 1px // and update/render the stage function tick() { hero.tick(); stage.update(); } // whenever a key is pressed then hero's // position will set to y=0; function handleKeyDown(e) { hero.reset(); } init(); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 if ( 'ontouchstart' in document . documentElement ) { canvas . addEventListener ( 'touchstart' , function ( e ) { handleKeyDown ( ) ; } , false ) ; } else { document . onkeydown = handleKeyDown ; document . onmousedown = handleKeyDown ; } var stage , canvas , hero , img = new Image ( ) ; function init ( ) { canvas = document . createElement ( 'canvas' ) ; canvas . width = getWidth ( ) ; canvas . height = getHeight ( ) ; document . body . appendChild ( canvas ) ; stage = new Stage ( canvas ) ; img . onload = onImageLoaded ; img . src = 'assets/hero.png' ; } function onImageLoaded ( e ) { hero = new Hero ( img ) ; stage . addChild ( hero ) ; hero . reset ( ) ; Ticker . setFPS ( 30 ) ; Ticker . addListener ( tick ) ; } // move the hero down by 1px // and update/render the stage function tick ( ) { hero . tick ( ) ; stage . update ( ) ; } // whenever a key is pressed then hero's // position will set to y=0; function handleKeyDown ( e ) { hero . reset ( ) ; } init ( ) ;

here’s how it should look like(depending on the background-color, that you chose for your html-body):

Of course this is very basic, and the movement is absolutely not realistic, since there is no acceleration in the movement, but we can fix this by adding a velocity-object to the hero, just add the following:

realistic movement //add this to the "initialize"-method this.velocity = {x:0,y:12}; //now we update the "tick"-method with: this.velocity.y += 1; this.y += this.velocity.y; //and this goes into the "reset"-method: //getHeight() is a utility-function, but can also be //replaced with a hardcoded-number this.y = getHeight() / 1.25; this.velocity.y = -15; 1 2 3 4 5 6 7 8 9 10 11 12 //add this to the "initialize"-method this . velocity = { x : 0 , y : 12 } ; //now we update the "tick"-method with: this . velocity . y += 1 ; this . y += this . velocity . y ; //and this goes into the "reset"-method: //getHeight() is a utility-function, but can also be //replaced with a hardcoded-number this . y = getHeight ( ) / 1.25 ; this . velocity . y = - 15 ;

and this is how it should look like by now:

Awesome, now we have a basic “game”, with a character falling down, that will be reset on any user-input. The next parts are going to cover collisions and animations.

You can download the source-files here: download

Agenda