Index

The Basics of Developing

Enchant.js is a library for developing games in Javascript.

Games using enchant.js can be posted to websites at will. Since these games run independantly, within a single div, they can be posted on other web pages and still function perfectly.

The basic method for creating games is based off of pre-defined code, which, along with the required data files for applications and the library containing enchant.js, is stored and uploaded in a single folder. To play the game, the user just has to access the index.html file in the uploaded folder.

Organizing a Game

Creating a game in enchant.js involves bringing together several elements. These elements, and their explanations, are listed below.

The Game Object

The Game object oversees the game, the system running it, and the game’s basic functionality. All games run frum within the Game object.

Every Game object creates a default Scene object with the name rootScene.

Several games can be created on a single web page, and in this instance, the only things stored on the page are the Game objects and each game’s number.

Scene Objects

Scene objects are a grouped collection of objects visible at the same time. Scene objects are used to manage the visibility of Node objects, which are the displayable elements, or primitives, which make up a game. For instance, when a game has a Start screen, changing the screen from the Start screen to the screen where the game is actually played is carried out by switching out Scene objects.

Games can contain either a single Scene object or multiple Scene objects. In very simple games, changing out images and creating transitions can be accomplished by adding and removing elements from the rootScene.

Also, Scene objects can be stacked into layers, and managed as such. For example, in a shooting game, or any game where there is a score displayed on-screen, the Scene object containing the score is placed in front of the Scene object containing the actualy scene where the game is being played.

Node Objects

Node objects are visual elements which make up a game. In actuality, the game uses objects which inherit the functionality of pure Node objects. (The below are used as Node-type objects.) Examples of Node-type objects include the following:

  • Sprite object: Object which displays a drawing or image
  • Label object: Object which displays text
  • Map object: Object which displays a game map

The Game Lifecycle

Games have lifecycles. In a game, which starts after enchant.js is initialized, many different processes are run. If a user navigates to a differnet page, or closes the browser, the game ends, but there are many ways for a game to end which can be engineered during development.
For instance, a game over screen can be displayed (showing the final score), or the player can be returned to the menu, etc. There are many games which don’t really end, since they return to the menu screen when the game is over.

In essance, in games created with enchant.js, the ending of a game isn’t of great importance, which is why we’ll move on to the essential part of a game’s inner workings, starting from the initialization of the game.

Initialization

When an enchant.js game initializes, the following things happen:

  1. Enchant.js is initialized
  2. Game objects are created
  3. Game objects are initialized
    • Elements which make up objects are preloaded
    • Starting game-code is set
  4. The game begins
  5. The game waits for preloading to complete, and then continues
  6. The beginning game code is executed

In the above, preloading elements is paramount. A simple implementation of preloading is shown below:

enchant();

var game = new Game(320, 320);
game.preload('preload1.gif', 'preload2.wav');
game.onload = function () {
  // Game code is written here
};
game.start();

1. enchant.js is initialized

(line 1) Firstly, enchant.js is initialized. This makes it so regardless of where on the page they are placed, enchant.js objects and variables can be used.

2. Game objects are created

(line 3) The Game object, as described above, plays a central role to the game itself, and carries out what happens on the screen. When the Game object is initialized, the resolution of the screen is set. In this example, a Game object which contains a game screen of resolution 320 pixels wide by 320 pixels tall is created.

3. Game objects are initialized

(line 4-7) Here the initial settings for game objects are set. These initial settings contain definitions for settings such as fps (frames per second) and so on.

4. Elements which make up objects are preloaded

(line 4) These are described in more detail in Carrying out Object Element Preloading.

5. Starting game-code is set

(lines 5-7) The code for the game itself is set right after the game begins. Essentially, this creates the first scene, the starting menu, etc.

6. The game begins / preloading

(line 8) The command for the game to begin is issued here. Not that the system has been specifically waiting until now (things advance as normal), but this is where the game program itself actually commences. This happens by game.onload being called. If no code has been written for the game, the processing of the game stops here. Next comes the preloading stage, and the system will wait for this to finish before executing the game code.

7. The beginning game code is executed

Once preloading is complete and the game starts, processing of the game starts up again. At this time, the elements set up from lines 5-7 above into game.onload are executed. Basically, it is at this point that the code for a user’s game is used, so we will start writing this code.

If a game has gotten very large, the code for the very beginning of the game (e.g. code for the menu screen) can be written separately from the main game code, and then called at this point.

State changes and Events

A game made in enchant js contains several states. Things called Events occur depending on those states. By defining specific code to be processed when those ovents occur, a game is made.

Here are the primary events:

  • ENTER_FRAME: Occurs when a frame starts
  • A_BUTTON_DOWN: Occurs when the A button is pressed
  • B_BUTTON_DOWN: Occurs when the B button is pressed
  • DOWN_BUTTON_DOWN: Occurs when the down cursor key is pressed
  • LEFT_BUTTON_DOWN: Occurs when the left cursor key is pressed
  • RIGHT_BUTTON_DOWN: Occurs when the right cursor key is pressed
  • UP_BUTTON_DOWN: Occurs when the up cursor key is pressed

For more detailed information regarding other specific types events, please consult the official enchant.js documentation.

Reverse Referense

Important Points

The Reverse Reverence below is a collection of information regarding the initialization of enchant.js. Please use the following template as a reference.

Note: Please be aware that in the Basics (drawing) section, the sample code is based off of appropriately created scenes.

If in this reference you come across classes or methods you are not familiar with, please consult the official enchant.js documentation

The Basic Template

enchant();
window.onload = function () {
  var game = new Game(320, 320);
  game.onload = function () {
    // Anything written here is processed
  };
  game.start();
}

Basics (drawing)

Creating and Erasing a Scene

Here we’ll make a Scene. Making a Scene involves the following:

  1. Creating the Scene
  2. Adding Node objects
  3. calling pushScene()

There are only 3 steps. When pushScene() is called, the Scene is displayed on the screen.

var scene = new Scene();
game.pushScene(scene);
// an example of adding a Node object
scene.addChild(sprite);

If there was only one Scene shown, it can be erased with popScene().

game.popScene(); 

Showing an Image

To use an image, we use Sprite objects.

var sprite = new Sprite(64, 64); sprite.image = game.assets['chara0.gif']; scene.addChild(sprite); 

In order to put an image onscreen, it must have been loaded ahead of time.

window.onload = function () {
   enchant();
   var game = new Game(320, 320); game.preload('chara0.gif');
   game.onload = function() {
      var scene = new Scene();
      var sprite = new Sprite(32, 32);
      sprite.image = game.assets['chara0.gif'];
      scene.addChild(sprite);
      game.pushScene(scene);
   };
   game.start();
}; 

Samples

Related Topics

Erasing Images

Images can be displayed by using the Scene’s addChild() method, and can be erased by using the opposite removeChild() method.

// Erases a sprite from the screen
game.rootScene.removeChild(sprite) 

Showing Text

To show text on the screen, use a Label.

var label = new Label("test");
scene.addChild(label)
 window.onload = function () { enchant(); var game = new Game(320, 320); game.onload = function () { var scene = new Scene(); var label = new Label("test"); scene.addChild(label); game.pushScene(scene); }; game.start(); }

Sample

Playing Sounds

To play a sound, we use the Sound object’s play() method.

game.assets['audio.wav'].play(); 

Since sound objects are not Node objects, it is not necessary to register them to a Scene, like Sprites or Labels. However, like other elements used in the game, they must be loaded before they are called.

enchant();
window.onload = function () {
  var game = new Game(320, 320);
  game.preload('jump.wav');
  game.onload = function() {
    game.assets['jump.wav'].play();
  };
  game.start();
};

Related Topics

Basics (manipulation)

Loading Elements

To load elements during a game, the game object’s load() method is used. The load method can be used to load images, sounds, or any other necessary files.

game.load('imagefile.png' function () {
   // Code written here is executed after loading is complete
});

The load() method can only load a single file. Therefore, when loading multiple files, it is necessary to call the load() method for each file to be loaded. If you are loading in multiple files, it is much easier to preload them instead.

// Sample which loads an image and displays it on-screen

Related Topics

Frame Processing

Frame processing is carried out using the ENTER_FRAME Event. With each advancing frame, the ENTER_FRAME event occurs, so any methods registered to occur when that event happens will be called at the beginning of every frame.

game.addEventListener('enterframe', function () {
  // Write code to be processed every frame here
});
// Sample which moves an image to the right
enchant();
window.onload = function () {
    var game = new Game(320, 320);
    game.preload('chara0.gif');
    game.onload = function() {
        var scene = new Scene();

        var sprite = new Sprite(32, 32);
        sprite.image = game.assets['chara0.gif'];
        scene.addChild(sprite);

        game.addEventListener('enterframe', function() {
          sprite.x += 1;
        });
        game.pushScene(scene);
    };
game.start();
};

Processing Taps (clicks)

TOUCH_START and TOUCH_END Events are triggered when the player touches (clicks) the screen). (Note: Tapping the screen on a smart phone and clicking on the screen on a computer are treated as the same thing in enchant.js.) When the player taps or clicks on a displayed Node object, a TOUCH_START Event for that Node object is dispached immediately at the point in time at which the screen is touched or the mouse button is clicked. Consequently, the TOUCH_END Event occurs at the point in time when the player stops touching the Node object, or when the mouse button is released.

Methods and other code can be registered for a Node object’s specific events. This can be used to create interactivity as well as animation.

Register specific methods you want run when an object is touched or released, to event listeners of that specific object.

sprite.addEventListener('touchend', function() {
  // Code written here will be executed when the the user stops touching (or lets up the mouse button from) the sprite
}); 
// This sample shows an image that will move to the right when clicked
enchant();
window.onload = function () {
    var game = new Game(320, 320);
    game.preload('chara0.gif');
    game.onload = function() {
        var scene = new Scene();

        var sprite = new Sprite(32, 32);
        sprite.image = game.assets['chara0.gif'];
        scene.addChild(sprite);

        sprite.addEventListener('touchstart', function() {
            sprite.x += 1;
        });

        game.pushScene(scene);
    };
    game.start();
};

Sample

Maps

A Note on Maps

The map functionality provided by enchant.js can be used to easily create maps for 2D RPGs!

To use the map functionality the following must be prepared ahead of time:

  • The Tile Set
  • Map Data

The tile set is essentially a sprite sheet containing all the tiles that will be used on the map, layed out in a grid with each cell the same size.

tileset image

Map data specifies how these tiles should be laid out, one tile at a time. This data is prepared in a JavaScript array.

var baseMap = [
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0]
];

Creating Maps

To create a map, use a Map object.

// Create a Map and draw it on-screen
var map = new Map(16, 16);
map.image = game.assets['map0.gif'];
var baseMap = [
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0]
];
map.loadData(baseMap);

scene.addChild(map);

In the above code, the following happens:

  1. The Map object is created
  2. The loaded tile set image is passed to the Map object’s image property
  3. The map data Array is passed to the Map object’s loadData method
  4. Preparation for the Map object is complete

From here, since preparation to draw the Map object is complete, it is displayed on-screen by adding it to the scene with addChild().

Obstacle Detection on Maps

To check if a specific place on the map contains an obstacle, the Map object’s hitTest() method can be used.

Obstacle detection using hitTest() is dependant on the ability to read the collisionData property of the Map object in question. The collisionData property contains map data which shows if there is an obstacle for each cell (defined by either a 0 or 1).

// Obstacle Detection on Maps
var map = new Map(16, 16);
map.image = game.assets['map0.gif'];
var baseMap = [
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0],
  [  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0]
];
map.loadData(baseMap);

var colMap = [
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0],
  [  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0],
  [  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
  [  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0]
];
map.collisionData = colMap;

if (map.hitTest(100,100) === true) {
  alert('hit!');
}

Sprites

Moving Sprites

Moving a sprite can be achieved by modifying the Sprite object’s x and y properties.

// x and y positions are specified on the Sprite's properties
sprite.x = 100; sprite.y = 20; 

The Sprite object’s x and y properties always contain the Sprite’s current location, so can be used like this:

// Move the Sprite to the left by 10
sprite.x -= 10;

In this way, it is possible to move a Sprite relative to its current location.

Sprite Rotation and Size

Rotating a Sprite can be accomplished with the Sprite object’s rotate() method.

// Rotate the Sprite by 120 degrees
sprite.rotate(120);

As you can probably tell from the code, the unit of measurement used for the rotation angle is in degrees. Also, the current angle of a Sprite object can always be acquired from a Sprite object’s rotation property.

// View a Sprite's current angle of rotation
console.log(sprite.rotation);

Scaling a Sprite can be achieved with the Sprite object’s scale() method.

// Double the width of a Sprite
sprite.scale(2, 1); 

Also, to find out the current scale factor of a Sprite, the Sprite object’s scaleX and scaleY properties can be referenced.

// View the Sprite's current scale factor
console.log(sprite.scaleX);
console.log(sprite.scaleY);

Sprite Transparency

To change the transparency of a Sprite, use the Sprite object’s opacity property.

// To give the sprite an opacity of 50%
sprite.opacity = 0.5; 

The value of the opacity property must be between 1 and 0. Completely opaque (visible) is 0, and completely transparent is 1.

Using the Canvas with Sprites

The HTML5-provisioned Canvas element can be used as a Sprite’s drawing element (what appears on the screen) in place of an actual image. When a Canvas element is used in this way, it must first be prepared as a Surface object.

// use a Canvas element as a Sprite's drawing element
var surface = new Surface(320, 320);
sprite.image = surface;

When a Surface object is used by a Sprite, it can be used by designating it as the Sprite’s image property.

Since several methods using the Canvas element are supported for Surface objects, please check the Official enchant.js Documentation for more information.

Collision Detection with Sprites

Whether or not a given Sprite is has collided (or is touching) another sprite can be determined with the intersect() and within() methods.

The intersect method detects if the area of one Sprite is colliding or in contact with something else. Note, if you create a 64×64-sized Sprite, but then use a 30×30-sized image for the Sprite, the Sprite’s original area of 64×64 will be used for detection, so be careful.

// Detect if sprite collides with sprite2
if(sprite.intersect(sprite2)) {
  alert("hit!");
}

The within() method detects collision based on the distance from the central point of the sprite and the central point of another object.

// if the distance between the center point of sprite and sprite2 is 40 or less, the alert is displayed
if(sprite.within(sprite2, 40)) { alert("hit!"); } 

Labels (text)

Changing Color and Font

Changing the text color of a Label is achieved with the Label object’s color property.

// Change the label color to red
label.color = '#f00';

Any color value valid in CSS can be used.

For example:

  • #123
  • #123456
  • black

are all valid color values.

Changing the font of a Label is done by using the Label object’s font property.

// Change the Label's font
label.font = "8px cursive";

Any CSS font property value can be used.

(Warning: The font property in CSS different from the font-family property. When declaring the font property, at minimum the font-size and font-family must be declared for this to work properly.

Moving a Label

Moving a Label is achieved by changing the Label object’s x and y properties.

// Display the Label at position 100,20 (x,y)
label.x = 100;
label.y = 20;

Also, the current position of a Label is always retained in the Label’s x and y properties.

// Move a Label to the left by 10
label.x -= 10;

In this way, Labels can be moved relative to their current position.

Changing Label Transparency

Label transparency can be controlled with the Label object’s opacity property.

// Make the label 50% transparent
label.opacity = 0.5;

he value of the opacity property must be between 1 and 0. Completely opaque (visible) is 0, and completely transparent is 1.

Miscellaneous

Changing Scene Background Color

A Scene’s background is determed by the Scene object’s backgroundColor property.

// Change a Scene's background color to red
scene.backgroundColor = 'red';

Any color value valid in CSS can be used.

Changing Game FPS

In order to change the fps of a game, modify the Game object’s fps property.

// Make the game run at 30 frames per second
game.fps = 30;

Note that this property is only called when game.start() is executed, and must be changed before that method is called in order to take effect. Changing the fps of a game once it has started is not possible.

Scaling the Game Screen

To change the scale factor of a game screen, modify the Game object’s scale property.

// Enlarge the game screen by a factor of 2
game.scale = 2;

Note that this property is only called when game.start() is executed, and must be changed before that method is called in order to take effect. Changing the scale of a game once it has started is not possible.

Changing the Scene Shown During Loading

To change the screen shown when loading, modify the Game object’s loadingScene property.

// Change the screen shown when loading
game.loadingScene = myscene;

The loading scene must be specified before game.start() executes.

Preloading Elements

In enchant.js, elements can be loaded before game.start() executes.

// Preload elements
game.preload('data1.jpg', 'data2.png', 'data3.wav'); 

As shown above, multiple elements can be preloaded by inserting commas between them. It is also possible to load a single element too.

This post is also available in: Japanese