Are you curious about developing cross-platform mobile games that work in a web browser?

Well, as you probably know, Apple doesn’t allow Flash to run on iOS devices, and Adobe has pulled the plug on Flash for mobile. This makes HTML5 your only solution – but actually a pretty good one!

The thing is, while there are many HTML5 game libraries available, only a few of them support mobile browsers. In this tutorial, you’ll try out one HTML5 game library that works great on the iPhone, Android, and the desktop – enchant.js!

You’ll make a game called called Penguin Dive, where players will take control of a penguin that’s swimming in the ocean, and dodge incoming ice boulders. The longer the penguin stays safely in the ocean, the higher the score. Once an ice boulder hits the penguin, it’s game over!

This tutorial assumes you are a complete beginner to enchant.js, but you must have some basic knowledge of JavaScript and HTML. Knowing how to set up your own local server also helps for testing purposes, but isn’t required.

If you’re ready, then let’s get this party started!

Introducing enchant.js

enchant.js is a fairly new HTML5+JavaScript game framework. The version as of writing is 0.51, which is DOM-based. The future version will move to HTML5 Canvas-based.

In case you’re wondering, DOM stands for Document Object Model. In this type of JavaScript coding, the code accesses the elements on a page via a structured hierarchy. Usually, the elements on the page are represented like a tree, where each HTML element is a branch or a leaf, and has a name or ID by which it can be accessed directly (or by way of a parent or grandparent).

The Canvas-based approach will rely on the new HTML5 <canvas> tag, which allows the code to define a canvas (or drawing area) and then draw directly on that surface, much as you would use CoreGraphics drawing functions in Objective-C.

Each approach has its pros and cons, but this tutorial won’t delve into those, since enchant.js will take care of the details internally. But it’s good to know the pros and cons of using enchant.js itself!

Pros of Using enchant.js:

It has a 2D scene graph system with a simple Flash-like API.

It’s cross-platform. Your game will work on iOS, Android, and desktop browsers.

It’s lightweight.

There are many plugins available to help you make specific types of games, such as a visual novel or an RPG.

It’s free and open-source!

Cons of Using enchant.js:

It lacks device orientation-related features.

It doesn’t yet support multi-touch.

Due to the framework’s Japanese origin, there is a lack of resources in English. (But this tutorial is helping to change that!)

Its cross-platform support is what makes enchant.js stand out from other HTML5 game frameworks. While it lacks some features, the current version is functional enough to make a complete working game.

Setting Up the Environment

Here is what you’ll need in order to write a game with enchant.js:

enchant.js: Download the framework from their github page. You can either clone the git repository, or use the ZIP icon at the top of the page to download a ZIP archive of the current source.

Text Editor: Since developing using enchant.js means working with JavaScript, decide what IDE/text editor to use. My favorite is Sublime Text 2. You can also use something like jsdo.it, which allows you to develop in your browser. :]

Web Server: This is optional. However, it’s better to test your HTML5 game on a web server rather than from your hard disk, since viewing a web page on your hard disk directly might disable some features. It also lets you test your game from your mobile device! There are many ways to set up a web server, but one of the easiest is to go with XAMMP.

Apart from the above, you need a web browser with a JavaScript console so that you can view the JavaScript output as you code.

Note: Note that although you are making a HTML5 game that will work on mobile browsers, usually you’ll want to test the game on a normal browser while you’re developing the game. This allows for faster test/run cycles, and lets you easily see the Javascript output.

In this tutorial, you will be using a normal web browser until later on in the tutorial, where I’ll show you how to get it working nicely on a mobile browser.

Your choices for a development browser are:

Google Chrome: You can enable the console by clicking on the Wrench Icon, then Tools, and selecting the JavaScript console.

Safari: You have to enable the Developer menu first. Go to Safari\Preferences and check Show Develop menu in menu bar in the Advanced Tab. You can then open the console through Develop\Show Error Console.

Firefox: You can either install the Firebug extension, or enable the console via Extras\Error Console or Tools\Web Developer\Error Console (depending on your version). Note Firebug has some extra cool features beyond the normal console.

Opera: Enable through Menu\Page\Developer Tools\Opera Dragonfly.

Internet Explorer: Don’t use this! :D Unless you really have no other choice – then grit your teeth and press F12 to get to the developer tools.

Preparing Your Project Structure

enchant.js doesn’t enforce any directory structure for projects. You can structure the project folders any way you like. So in this tutorial, you’re going to structure things in a way that makes sense to me. Hopefully, it will make sense to you, too. ;]

Go to the directory that you want to be your workspace and create a new folder named penguindive.

Next, create subfolders within your penguindive folder so that the folder structure is as shown:

penguindive/
penguindive/js
penguindive/js/lib
penguindive/res

The res and js folders will be where you store your JavaScript files and your game assets, respectively. The lib folder will be where you store third-party JavaScript files/libraries.

The next step is to put all the game assets you downloaded earlier inside the res folder. Simply extract the ZIP file and copy the files. Once you do that, you should have the following files in the res folder:

You will not be using all of these files in this tutorial. However, feel free to use them to extend the game on your own, as a challenge. There are some suggestions for how to do this at the end of the tutorial. :]

Next, extract the enchant.js archive you downloaded from GitHub. Copy the enchant.js file and put it in your js\lib folder.

Note: You’ll notice that there are two versions of enchant.js in the archive – enchant.js and enchant.min.js. The second file is the minified version, where extra spaces and carriage returns have been removed to make the smallest downloadable version possible for the code.

Since that version also replaces variable names and methods with short (usually incomprehensible) alternatives, it doesn’t lead to very human-readable code. So it’s best to use the standard version of the code during development and debugging (enchant.js) and to use the minified version in production (enchant.min.js).

You’re now ready to start the actual coding!

Why Hello There, Ocean!

Let’s start with something simple: saying hi to the world where your game will take place. :]

Launch your favorite text editor and start by creating the index.html file, which as I’m sure you’re aware, will be the first file loaded when the game folder is accessed via a browser:

The code above is all you need to get an enchant.js game working. Let’s go over it step-by-step:

Export all the library classes globally. This allows you to use classes from enchant.js without having to type the namespace every time.

Create a function that will be invoked once the HTML document is done loading. You will initialize your game inside this function.

Create an instance of the Game class, which is the main application class of an enchant.js game. The constructor for the Game class takes two arguments: the width and height of the game’s screen in pixels.

Preload the background image for the game. When you have resources that take a lot of time to load (like big images or background soundtracks), it’s a good idea to load them before you actually need to use them.

Configure the game settings. Notice the line setting the game frame rate to 30 fps (frames per second). This does not mean that the game will always run at 30 fps. It’s very likely that the fps will drop on mobile platforms. Think of this as a maximum fps that the game will try its best to achieve.

The Game object’s onload event will be invoked once the game finishes loading everything in the preload queue. This is the entry point of your game.

As the method name implies, this will start your game. Starting your game will initiate the preloading process, and invoke the onload method once the preloading is finished.

Note: The game’s frame rate and scale cannot be changed after you start the game. Make sure to set them before calling game.start()!

Save your main.js. It’s time to see if your game is running correctly on the desktop browser. Simply open index.html, or, if you’re using a web server, navigate to the game folder via localhost.

When you open the game page, there shouldn’t be anything on the screen – after all, you haven’t put anything there yet! But if you check your browser JavaScript console, you should see “Hi, Ocean!” displayed.

Node, Scene and Game: The Basic Concepts

When working with enchant.js, there are some basic concepts that you need to know:

Scene

enchant.js uses the concept of a scene to handle the game flow. A game can have many scenes, but only one of them can be running at a time. By switching scenes, you can change the game’s state/screen.

For example, a game’s flow might look like this:

According to the diagram, there are four scenes in the game. Starting from the Title Scene, players can go to the Game Scene, where the main gameplay takes place. From there, they can switch between the Game Scene and the Option Scene to adjust the game’s settings.

Once the player is back in the Game Scene and the game is over, the game moves to the Game Over Scene, before returning to the Title Scene again, ready for the next game session.

Game

As stated earlier, the Game class is the main application class. One Game object represents one single enchant.js game. The Game class also acts as a Scene Manager. It stores instances of scenes in a stack, where the top scene on the stack is the active scene.

In enchant.js, a game always comes with a scene called the Root Scene (i.e. the first scene in the stack). By manipulating the scene stack, you can change the game’s state easily.

There are three ways you can manipulate the scene stack through a Game object:

Replace: This replaces the active scene with a new one. You can’t go back to the old scene, unless you store a reference to it somewhere before replacing it.

Push: This pushes a new scene on top of the stack, making it the active scene. The old scene is kept inactive in the stack.

Pop: This removes the scene at the top of the stack, making the next scene in the stack the active scene.

Node

Scenes in enchant.js are implemented using a tree data structure. Hence, many objects in an enchant.js game are nodes. In fact, if you are familiar with Cocos2D development, the concept is fairly similar to that of a node in Cocos2D.

There are many types of nodes in enchant.js. Here are a few examples, all of which you’ll use shortly:

Sprite: a node for displaying static images and animation.

Label: a node for displaying text.

Group: a node for grouping many nodes together.

Therefore, a scene is actually a tree of nodes, where the root is a Scene node. It may have some children nodes that are sprites, labels, and so on.

Do you “node” what I mean? Not quite? Let’s write some code to help you understand this better! :]

Add the following lines to main.js after you print “Hi, Ocean!” to the console:

Create an empty scene. You will use this scene as your main game scene.

Create a Label node to display the text “Hi, Ocean!” on the screen. The Label class constructor takes one argument, which is the text you want to display.

Create a Sprite node for the background image. The constructor takes two arguments: the width and the height of the image you want to display. Once the sprite is created, you assign the image you want this sprite to display.

You can access the image data you have loaded into the game through the game’s assets dictionary. This dictionary will map the path to the loaded resource. Since you told the game to preload a file at path res/BG.png, this path will be used as a key that maps to the ocean background.

Add your new nodes to the scene. The addChild method means that the node you add will become one of the scene’s child nodes.

Note: The order in which you add nodes to a scene is important. In enchant.js, the framework will draw a newly-added node on top of those that were added previously.

If you switch the order in the code above, you won’t see the label even though it is actually in the scene. This is because the background would be on top of the label.

Your scene is ready. It’s time to make this scene your active scene. To do this, you simply push the scene onto the game’s scene stack.

Save main.js and reload your browser page. You should see something similar to the following:

Object-Oriented Style With enchant.js

enchant.js already comes with its own object-oriented framework. Without this, you would have to create a scene and add everything within the game’s onload event. While this is simple, the OOP framework that enchant.js provides makes it easier for you to extend your code, and your code will be cleaner in the long run!

OOP in enchant.js uses the same implementation as Prototype.js, in case you’re familiar with Prototype. So, in order to create a new class, you only need to do the following:

The above code creates SceneGame as a subclass of Scene. Let’s go over the code:

Invoke the constructor of Scene, which is the superclass of your SceneGame, to do any initialization it needs.

Often you’ll find yourself in need of accessing the game object, especially when you want to access the assets dictionary. Fortunately, the game instance is a singleton, meaning there is only one single instance of Game and it can be accessed from anywhere. This line of code will assign the singleton Game instance to the game variable for later use.

Create child nodes for the scene, just like before.

Add the child nodes as before, but this time use this instead of scene because the this variable refers to the current instance of SceneGame. Hence the line is still doing the same thing – that is, adding nodes to your scene node.

With this, you have finally created your first enchant.js class!

It’s time to use SceneGame. Replace the code inside game.onload with the following:

The first two lines are similar to what you did with the background. You create a new Sprite node sized 30×43 pixels, and assign the image file to the penguin sprite.

The next two lines set the penguin’s position. Notice how easy it is to access the screen and the penguin’s width. You can access and modify node heights similarly.

Finally, don’t forget to add the penguin to the scene. Otherwise you won’t see it on the screen!

Add the following code right after the line adding the bg node to the scene. Remember that the order in which you add nodes is important!

this.addChild(penguin);

You want the penguin to be on top of the background, but under the label. Therefore, you must add him after the background, but before the label.

Now save your changes and reload the page in your browser to see the current state of your game:

You should now see the penguin on the screen. Your first visual evidence of progress! :]

A Closer Look at Sprites

While the penguin looks like it’s just another Sprite node, it’s slightly different when compared to the background Sprite.

Take a look at how you created the penguin sprite:

penguin =new Sprite(30,43);

Remember what this means? This line created a sprite with a size of 30×43.

However, if you look at the file penguinSheet.png, you’ll see that the image’s size is actually 60×43. Why, that is certainly not 30×43!

So what does this mean? When you instantiate the sprite with a size of 30×43, but assign an image sized 60×43 to it, this is how enchant.js sees the image:

Sprite node in enchant.js treats the image you assign as a sprite sheet. It will use the size you’ve given as its frame size, and assign an index number to each frame. The index will start from 0, counting from left to right and top to bottom.

You can change the animation frame by setting the frame property of a Sprite. This is what you are going to do next!

Basic Animation

Since there are going to be many things going on with your penguin, it’s better to put him into a class of his own. And that’s how your upstart, boulder-challenging penguin prefers it.

Add the code for the Penguin class right below SceneGame in main.js, as follows:

Penguin is a subclass of Sprite. As you’ve probably noticed, the line that calls the superclass constructor is a bit different from what you used when you subclassed Scene. This is because a Sprite constructor takes two arguments. To send arguments to your superclass constructor, you pass them as an array in the second argument.

The two lines in section #2 animate your penguin. In the first line, you declare an instance variable, which will be used as a timer for your animation. The second line introduces you to the event system in enchant.js. If you are familiar with ActionScript or Corona development, you’ll find this easy to understand.

Simply put, objects in enchant.js can fire events that other objects might be interested in. If an object is interested in a specific event, you can tell that object to listen for that event and specify functions that should be invoked once that specific event occurs.

Hence, in the above line, you tell the penguin to listen for the ENTER_FRAME event, and call a method named updateAnimation every time this event occurs.

ENTER_FRAME is an event that is fired every frame, similar to the update function in a game loop.

Since you’ve moved all the sprite-related stuff to the Penguin class, all you need to do is instantiating an instance of the Penguin class and position it.

Save the file and refresh the browser to see what you’ve accomplished.

Your penguin is now moving! Er, at least he’s flapping his flippers. He’s alive – and the water currents are beckoning. Let’s get him on his way.

Touch Detection

Now that you’ve got the penguin flapping, it’s time to get him responding to player touches. In order to do this, you will divide the screen into three vertical sections. When the player clicks or touches on any section, the penguin will quickly move to that section of the screen.

Touch/click detection in enchant.js is as simple as listening for touch events. Add the following code to the end of the SceneGame constructor:

You divide the screen’s width by 3 to get the width of each section/lane.

The evt value for a touch event contains information about the touch position, and you can access it via x and y properties. Then you use this information to find the lane number. After you’ve determined which lane was clicked/touched, you tell the penguin to move to that lane.

Add the switchToLaneNumber method to the Penguin class (note that the new method goes in Penguin and not SceneGame):

The Ice class is also a subclass of the Sprite class. The Ice constructor takes an argument indicating the lane where it will appear.

Notice that your Ice class is missing two methods. The first one is setLane, which you will use to set the object’s position according to lane number. The second is update, which you call every time ENTER_FRAME occurs.

Once again, this is pretty straightforward. You keep adding speed to the ice’s y position so that it’ll move from the top of the screen to the bottom. You also use rotationSpeed to keep the ice boulder rotating.

Once the ice moves beyond the bottom of the screen, it is removed from the parent node, effectively removing it from the scene.

You can access a parent node of any node through the parentNode property. With it, you can tell the ice’s parent node to remove the ice from the tree structure once it moves beyond the bottom of the screen. Remember the node and scene relationship? If you add the ice to the scene, the scene becomes the parent node of the ice.

You’re using a resource, res/Ice.png, that you haven’t told the game to preload. So let’s go back to the beginning of main.js and add it to the preload list.

Modify the preload line to look like this:

game.preload('res/BG.png','res/penguinSheet.png','res/Ice.png');

And with this, your Ice class is frozen solid and ready to deploy. Why don’t you test it by making an ice boulder appear every three seconds!

To do this, go to SceneGame constructor. Add the following line after the TOUCH_START event listener line:

// Updatethis.addEventListener(Event.ENTER_FRAME,this.update);

Once again, you tell the scene to listen for ENTER_FRAME, and report the event to the update method.

You need a timer to know when to generate an ice boulder. Add this to the end of SceneGame’s constructor:

// Instance variablesthis.generateIceTimer=0;

Add the update method to SceneGame as follows:

update:function(evt){// Check if it's time to create a new set of obstaclesthis.generateIceTimer+= evt.elapsed*0.001;if(this.generateIceTimer>=0.5){var ice;this.generateIceTimer-=0.5;
ice =new Ice(Math.floor(Math.random()*3));this.addChild(ice);}}

Save your changes and run the game again. Now the ice boulders should appear at random positions every 0.5 seconds!

Collision Detection

Having run the game, you’ve probably noticed that…

Yep, the ice boulders go right through the penguin. You should do something about this, or your penguin will get lazy and before you know it, get eaten by a killer whale. Make him fight for his life! :]

Start by adding a new variable to the SceneGame constructor, so that the first line looks like this:

var game, label, bg, penguin, iceGroup;

Then add this code in the SceneGame constructor, right after creating the penguin:

// Ice group
iceGroup =new Group();this.iceGroup= iceGroup;

Here you have created a Group node called iceGroup. Still remember what a Group node is?

A Group is a node that can contain other nodes, just like what the scene’s doing with your sprite and label. You’ll use this group to store all the ice boulders, so that you can manage them all from one place.

Next, add the new group to the scene. Go to where you add nodes to the scene in the SceneGame constructor and add the following code, immediately after where you add the bg node:

this.addChild(iceGroup);

By adding the iceGroup after the background but before the penguin, you make sure that the penguin will always be above the ice. Using Group nodes, you can create a layer system that gives you more control over the rendering order.

Go to SceneGame’s update method. Remember where you generate an ice boulder? Make the following change:

//this.addChild(ice);this.iceGroup.addChild(ice);

You’re not adding new boulders directly to the scene anymore. Instead, newly created boulders are added to the ice group. But they’ll still be rendered on the scene, because you already added the group to the scene in the constructor.

That’s all fine and good, I hear you say. But what does all this have to do with boulders hitting the penguin? You’re getting there. :] In fact, it’s time to work on the collision detection so that you can find out when a boulder hits the penguin!

One good thing about a Group node is that you have assembled a collection of nodes you are interested in. You’ll go through each boulder in the group and see if it collides with your penguin.

Still inside SceneGame’s update method, add the following lines after the if block:

A Group node has a childNodes array that keeps track of all of its children. This block of code iterates through each child and checks if it collides with the penguin.

An instance of the Sprite class has an intersect method that you can use to check if two sprites are intersecting. Since Ice and Penguin are both subclasses of Sprite, you can check if the two collide by using this method. If a boulder collides with the penguin, you remove that boulder from the group.

Save main.js and refresh your browser. Now, when a boulder collides with your penguin, it should disappear!

For now, you’ll leave the penguin to imagine that he’s smashing apart those boulders with his beak each time he collides with one. You’ll implement the grim reality soon enough. ;]

Tally the Score

This game could use a way to keep score. So, let’s change the “Hi, Ocean” label into something more useful.

Go to where you create the label in the SceneGame constructor and modify the code to look like this:

The above line uses the text shadow property to add a black border around the text.

Finally, you keep a reference to the label in your SceneGame instance under the name scoreLabel.

Save and run the game again. The “Hi, Ocean” label should now be in the top center of the game screen, and should read, “SCORE 0”.

Of course, currently there is no scoring mechanism! You are going to increase the score as time passes.

Add the following two variables at the end of SceneGame’s constructor:

this.scoreTimer=0;this.score=0;

You use scoreTimer as a timer to increase the game score as time passes, while the score variable contains the game score (obviously!).

You want the label to report the player’s current score. Whenever the score is modified, the text on the label should be updated as well. Therefore, it is a better idea to wrap the score modification into a method.

Unlike images, audio files loaded by enchant.js will be kept as Sound objects inside the assets dictionary. You can access these objects directly and call the play method to play the audio.

Save and run the game. When the penguin hits a boulder, the hit sound effect should play, which sounds kinda like a board slamming a wall (well, at least if you’re using a browser that supports it).

Note: Audio playback might or might not work correctly, depending on the browser. It worked fine for me on Safari on a Mac, but would not work correctly with the latest Firefox beta if I was loading the file directly. But if I loaded the game via a local web server, then it worked fine on Firefox as well.

So, if you get a loader bar (it usually appears very quickly without the sound pre-loading, and so you might not even notice it) and it doesn’t complete, then try a different browser or, if you are loading the file directly, try loading it via a local web server. If nothing works, remove the sound pre-loading, and things should work correctly again.

Next, you’ll add the background music to the game. Go to where you declare instance variables inside the SceneGame constructor. Add the following after the instance variables:

Since there is no loop option in the enchant.js audio system, you have to implement it manually. This block of code checks to see if the audio’s current time has reached the end of the audio file. If it has, then the audio is played from the start again.

Save and run the game, and you should hear the background music play – a happy and silly tune, perfect for this game!

Every Penguin Has His Day

You’re almost there! It’s time to make life challenging for your carefree penguin. He’ll be punished for hitting the ice with death, and when he dies, you’ll allow the player to restart the game.

Start by creating a SceneGameOver class. Add this code to the end of main.js, just as with all the other classes:

Just as you did before, this will create a score label. The score variables come from the SceneGameOver constructor. This means that when you create an instance of this scene, you have to pass a final score to it.

Your labels are ready. It’s time to add them to the scene!

Add the following code immediately after the previous block:

// Add labelsthis.addChild(gameOverLabel);this.addChild(scoreLabel);

Finally, make the scene listen for the TOUCH_START event, so that players can restart the game by tapping on the screen. [TODO: Put this where?]

This sets the size of your game’s viewport. To understand more about the viewport, you can read the Apple Documentation on the subject. Simply put, the viewport is the area that determines how your content will be laid out in a mobile browser.

In enchant.js, the Game object will check to see if your game is running on a retina display device. If it is, it will modify this viewport meta tag and adjust the game size to appropriately, so you don’t have to worry about your game being displayed incorrectly on retina display devices.

One more thing you’ll notice on an iOS device is that your game isn’t really on the top left – there are some margins. Let’s fix this as well. Modify your HTML body in index.html to be as follows: