JavaScript
enchant.js
More than 3 years have passed since last update.

ドットインストールのenchant.js入門のまとめです。
enchant.jsは簡単にゲームを開発することができるので、モック作成にもオススメです。

ドットインストール enchant.js入門

※ 簡略化のため、手順等を書き換えている箇所がありますのでご注意下さい。

1. enchant.jsとはなにか?

概要

  • 日本製のゲーム開発フレームワーク
  • HTML5 + JavaScript
  • マルチプラットフォーム

公式サイト(日本語)

必要となる知識

  • HTML / CSS
  • JavaScript

必要となるツール

  • ブラウザ(Google Chrome)
  • テキストエディタ

2. 開発の準備を進めよう

まずenchant.jsをダウンロードします。
そして簡略化のために、新しく作業ディレクトリを作り、必要最低限のファイルをコピーします。

$ mkdir game
$ cp enchant.js-builds-0.8.2-b/build/enchant.js game
$ cp enchant.js-builds-0.8.2-b/images/chara1.png game
$ cp enchant.js-builds-0.8.2-b/examples/beginner/hellobear/index.html game

ディレクトリの配置を変更したのでenchant.jsの読み込み先を変更します。

index.html
<script type="text/javascript" src="enchant.js"></script>

enchant.jsを有効にし、ブラウザが表示されたときにconsole.logで文字列が表示されるかテストします。

main.js
enchant(); // enchant.jsの有効化

window.onload = function() {
    console.log('hello world');
};

3. クマを表示してみよう

Coreオブジェクト: ゲーム本体
- rootScene: 画面
-- Spriteオブジェクト: 部品(クマ)

Coreオブジェクトは画面であるrootSceneをプロパティに持っています。
rootSceneに部品であるSpriteオブジェクトをaddChildメソッドで載せて表示しています。

main.js
enchant();

window.onload = function() {
    var core = new Core(320, 320);
    core.preload('chara1.png');
    core.onload = function() {
        var bear = new Sprite(32, 32);
        bear.image = core.assets['chara1.png'];
        bear.x = 0;
        bear.y = 0;
        core.rootScene.addChild(bear);
    };
    core.start();
};

4. クマを動かしてみよう

core.startメソッドを実行するとフレームがカウントアップされ始めます。
その際にenterframeというイベントが発生するので、クマの座標を動かす処理を登録しておくことによって、フレームがカウントアップされ始めたときにクマを動かすことができます。
コアのフレームの速度はcore.fps(frame per second)で指定することができます。

main.js
core.fps = 15;
core.onload = function() {
    bear.on('enterframe', function() {
        this.x += 10;
        this.rotate(2); // 2度ずつ回転
        this.scale(1.01, 1.01); // 縦横1.01倍ずつ拡大
        if (this.x > 320) this.x = 0; // 画面からはみ出したらx座標を0に戻す
    });
};

5. アニメーションを作ってみよう

chara1.pngはスプライトシートという複数の画像をタイル状に配置した1枚の画像です。
bear.frameの値を変更することによって表示する画像を切り替えることができます。
表示する画像の範囲はbear.frameの値が増加するごとに左上から右にスライドしていきます。
this.ageはスプライトオブジェクトが動き始めて何フレーム経ったかを表します。

main.js
bear.frame = 1;

bear.on('enterframe', function() {
    this.x += 5;
    this.frame = this.age % 3;
    if (this.x > 320) this.x = 0;
});

6. クマを操作してみよう

ブラウザのキーボード入力はcore.inputで受け取ることができます。
スマホのタップやマウスのカーソルを合わせてクリックする際のイベントはtouchstartで受け取ることができます。
登録するfunctionの引数にはタッチした座標が格納されます。

main.js
bear.on('enterframe', function() {
    if (core.input.left) this.x -= 5;
    if (core.input.right) this.x += 5;
    if (core.input.up) this.y -= 5;
    if (core.input.down) this.y += 5;
});

bear.on('touchstart', function() {
    core.rootScene.removeChild(this);
});

core.rootScene.on('touchstart', function(e) {
    bear.x = e.x;
    bear.y = e.y;
});

7. ラベルを表示してみよう

テキストの埋め込みにはラベルを使います。
core.frameで全体のフレーム経過数が取得できるので、それをcore.fpsで割ると開始から何秒経ったかを表示できます。

main.js
var label = new Label();
label.x = 280;
label.y = 5;
label.color = 'red';
label.font = '14px "Arial"';
label.text = '0';
label.on('enterframe', function() {
    label.text = (core.frame / core.fps).toFixed(2);
});
core.rootScene.addChild(label);

8. 衝突判定をしてみよう

  • intersect
    ざっくりとした衝突判定です。

  • within
    オブジェクト同士の中心間の距離を使用した衝突判定です。

main.js
bear.on('enterframe', function() {
    if (core.input.right) this.x += 5;

    if (this.intersect(enemy)) {
        label.text = 'hit!';
    }

    if (this.within(enemy, 10)) {
        label.text = 'HIT!';
    }
});

9. ゲームオーバー処理をしてみよう

新しいシーンを作成し、backgroundColorをblackに設定します。
衝突判定が起こったときにcore.pushSceneを使うことによって、新しく作ったシーンをrootSceneの上に載せることができます。
ゲーム自体の停止はcore.stopメソッドで行われます。

main.js
var gameOverScene = new Scene();
gameOverScene.backgroundColor = 'black';

bear.on('enterframe', function() {
    if (this.within(enemy, 10)) {
        core.pushScene(gameOverScene);
        core.stop();
    }
});

10. クラスを作ってみよう

ゲームを作っていくと、同じような部品を複数用意したいときがあると思います。
そのようなときに役立つのがこのクラスです。
1行目はSpriteオブジェクトを継承したクラスを作成していて、initializeでコンストラクタ関数を指定しています。
作成したオブジェクトは今までのようにnewで生成することができます。

main.js
var Bear = Class.create(Sprite, {
    initialize: function(x, y) {
        Sprite.call(this, 32, 32);
        this.x = x;
        this.y = y;
        this.image = core.assets['chara1.png'];
        this.on('enterframe', function() {
            this.x += 5;
        });
        core.rootScene.addChild(this);
    }
});

var bear = new Bear(0, 0);
var bear = new Bear(0, 100);

11. クマをたくさん表示させてみよう

rand(n)というnまでの乱数を表示させる関数を作成し、クラスを利用することでクマをたくさん表示させています。
クラスの有用性がはっきりとわかる例でしょう。

main.js
core.onload = function() {
    var Bear = Class.create(Sprite, {
        initialize: function(x, y) {
            Sprite.call(this, 32, 32);
            this.x = x;
            this.y = y;
            this.frame = rand(5);
            this.opacity = rand(100) / 10;
            this.image = core.assets['chara1.png'];
            this.on('enterframe', function() {
                this.rotate(rand(10));
            });
            core.rootScene.addChild(this);
        }
    });

    var bears = [];
    for (var i=0; i < 100; i++) {
        bears[i] = new Bear(rand(320), rand(320));
    }
};

function rand(n) {
    return Math.floor(Math.random() * (n + 1));
}

12. Timelineを使ってみよう

Timelineはアニメーションに特化したクラスです。

moveByメソッドによって移動距離にアニメーションをつけることができます。
移動する位置を座標で指定したい場合はmoveToメソッドを使います。

Easingとはふわっとした動きのことで、アニメーションの動きをしていすることができます(詳しくは公式サイト参照)。
Timelineはメソッドをつなげて実行させることができ、またandメソッドでつなげることによって複数のメソッドを並列して実行させることができます。

main.js
// this.tl.moveBy(縦の移動距離, 横の移動距離, アニメーションのフレーム数)
this.tl.moveBy(rand(100), 0, 40, enchant.Easing.BOUNCE_EASEOUT)
       .moveBy(-rand(100), -rand(20), rand(20))
       .fadeOut(20)
       .fadeIn(10)
       .loop();

終わりに

以上でenchant.js入門は終了です。

ドットインストールは新しい技術を学ぶ上での情報が体系的にまとまっています。
時間もそれほどかけないで見ることができるので、かなりオススメのサービスです。
事実、僕も新しい技術を学ぶ際には必ず見るようにしています。

不明点等あれば本家のサイトを参考にしてみて下さい。