enchant.js Developers Blog

The Latest News on the HTML5 + JavaScript Game Engine enchant.js

Archive for January, 2012

ユビキタスエンターテインメントのiOS向けシューティングゲーム「GRANDARIUS WING STRIKE」が、enchant.js を使ってHTML5+JavaScriptに移植されました。同タイトルは AppStoreで有償で配布しているもので、HTML5版ではそのステージ1を遊ぶことができます。

TechWaveGIGAZINEをはじめいくつかのメディアに取り上げていただきました。

プレイはこちらから。

技術的な詳細は以下のブログ記事を参照してください。

wise9 – HTML5/enchant.js版グランダリウスのソースは739行! HTML5/enchant.jsの生産性はObjective-Cの50倍はあるかも

  • コメントは受け付けていません。
  • Filed under: お知らせ
  • そろそろWebGLにも対応したバージョンがリリースされそうなenchant.js。みんなやってるかな?
    ところでTwitterで気になる発言を目にしました。

    enchant.jsのクラス継承のところでつまづいている、ということだったので、今日はこの微妙にややこしい問題を扱ってみようと思います。

    まず、JavaScriptのクラス継承は、プロトタイプベース継承と言って、ちょっと特殊です。
    JavaScriptのクラス継承については@ITのこの記事が非常に解り易くまとまっています。


    しかしこのプロトタイプベース継承という考え方が、そもそもC++やRuby、Javaなど、他のクラスベース継承を採用した言語から入門した人にはちょっとわかりにくいのです。

    すごく大雑把に説明すると、プロトタイプベースというのは、.prototypeに指定された要素が常にコピーされるというやり方。

    これを説明するために、まずはJava(クラスベース)のクラス定義をおさらいしましょう。

    //Javaの場合
    class A {
      int x;
      public A(){
        x=1;
      }
      public  int method(){
        System.out.println(x);
      }
    }
    
    //クラスを使うとき
    A a = new A();
    a.method();
    

    みたいな感じになります。

    JavaScriptは、Javaと名前は似てますが、クラスの考え方がプロトタイプベースと、全く異なる考え方になっています。

    同じことをするクラスをJavaScript(プロトタイプベース)で書くと以下のようになります。

    //JavaScriptの場合
    A = function(){
        this.x=1;
    };
    A.prototype.method = function(){
    	document.write(this.x);
    }
    
    //クラスを使うとき
    var a = new A();
    a.method();
    

    Javaと比較するとなんじゃこりゃ、という感じです。
    名前は似てるのに違い過ぎて衝撃を受けます。

    しかしもっとひどいのは、継承をした場合。
    Javaで継承をすると以下のようなコードになります。

    //Javaの場合
    class A {
      int x;
      public A(){
        x=1;
      }
      public  int method(){
        System.out.println(x);
      }
    }
    
    class B extends A {
      int y;
      public B(){
        super(); //親クラスのコンストラクタを呼ぶ
        y=100;
      }
      public  int anotherMethod(){
        System.out.println(x*y);
      }
    }
    
    //継承したクラスを使うとき
    B b = new B();
    b.method(); //親クラスのメソッド呼び出し
    b.anotherMethod(); //継承したクラスのメソッド呼び出し
    

    extendsというキーワードで継承するクラスを指定するわけです。
    AとBのクラス定義がハッキリ別れているので、パッと見た感じ解り易いです。

    ところがJavaScriptの継承はこれに慣れているとかなり不思議なやりかたになっています。

    A = function(){
        this.x=1;
    };
    A.prototype.method = function(){
    	document.write(this.x);
    }
    
    B = function(){
        A.call(this); //親クラスのコンストラクタを呼ぶ
        this.y=100;
    }
    B.prototype = new A(); //ここで継承している
    B.prototype.anotherMethod = function(){
    	document.write("<BR>"+this.x*this.y);
    }
    
    var b = new B();
    b.method();
    b.anotherMethod();
    

    継承をしている部分は、B.prototypeになんと生成したA(継承元クラス)のオブジェクトを突っ込んでいます。

    というのは、JavaScriptの場合、コンパイル言語ではなくインタプリタ言語である、という特性が大きく活かされた継承モデルになっているのです。

    JavaScriptでは、prototypeプロパティに指定されたメンバーは、new演算子で新しくインスタンス生成する際に自動的にコピーされます。

    そして継承とは、親クラスの内容をまるごと子クラスがコピーする(厳密にはコピーされるのではなく、暗黙的に参照される。詳しくは@ITの記事参照)、というのがJavaScriptの基本的なやり方なのです。

    これは処理系(JavaScriptの)を実装する側からすると、非常に簡単にクラス継承を実現できることになります。なにしろ単にコピーするだけでいいんですから。

    クラスを定義したり継承したりするための特殊な構文も必要ありません。

    その代わり、デメリットとして、そもそもオブジェクト指向が持っている重要な機能としての隠蔽化の機能が全く実現できない(全てのメンバーがpublicであること)ということが挙げられます。

    これは巨大で堅牢なプログラムを書くには大きな障害になります。
    誰でもいつでも好きなように言語全体の構造を変更できてしまうのです。

    たとえば、JavaScriptでは組み込みクラスの配列がありますが、好きなタイミングで配列の機能そのものを追加したり変更したりすることができます。

    Array.prototype.remove=function(obj){ //配列の任意の要素を削除するメソッドremoveを追加
    	for(i = 0; i < this.length; i++){
     		if(this[i] === obj){
     			this.splice(i,1);
    		}
    	}
    }
    
    var hoge = [1,2,3,4];
    
    hoge.remove(3);
    
    for(i=0;i<hoge.length;i++)
    	document.write(hoge[i]+','); //配列の中身を表示
    

    上記は配列の任意の要素を削除するメソッドremoveを組み込みクラスに追加した例です。

    しかし、JavaScriptはいったいなぜ、プロトタイプ継承なんていう特殊なやりかたを採用したのでしょうか。

    それにはいろいろな理由が考えられます。
    が、ひとつ言えることは、コンパクトなプログラムを手早く書くには、プロトタイプ継承は慣れれば便利だということです。

    好きなタイミングで好きなメンバーを追加したり、オブジェクトごとにメンバーの内容を変更したりといったことが容易です。

    これは、Javaなどの一般的なクラスベース言語では第一級関数(関数を変数と同格に扱うこと)がサポートされていないのに対し、JavaScriptでは第一級関数をサポートしているということが大きいと思います。

    そのぶん、これを駆使してプログラムを書くと、コードはかなり混乱しやすくなります。
    そのかわり、慣れると非常に素早く目的とするプログラムを書くことが出来るようになります。

    だから複数人でJavaScriptのプログラム開発をやるときは注意が必要です。
    名前空間がバッティングしたり、触って欲しくないプロパティを触られてしまうリスクも発生します。

    ただ、ゲームプログラミングにおいては、実はクラスベース継承の方が基本的に向いています。
    そこでenchant.jsでは、クラスベース継承を擬似的にサポートするためのユーティリティ関数として、Class.createが用意されています。

    Class.createの使い方は簡単です。

    enchant(); //enchant.jsを使うおまじない
    
    A = Class.create({       // Class.createでのクラス宣言
        initialize:function(){  //コンストラクタ
            this.x=1;
        },
        method:function(){
            document.write(this.x);
        }
    });
    
    //使う場合は通常のJavaScriptと同じ
    var a = new A();
    a.method();
    

    ミソは、Class.createにリテラル表現のオブジェクトを渡しているところです。

    こうすると、一見、Javaのクラス宣言のようなクラス定義を表現できます。
    継承する場合のコードは以下のような感じに成ります

    enchant();。
    
    A = Class.create({
        initialize:function(){
            this.x=1;
        },
        method:function(){
            document.write(this.x);
        }
    });
    
    B = Class.create(A,{   //Aを継承
        initialize:function(){
    	A.call(this);  // Aのコンストラクタを呼び出し
            this.y=100;
        },
        anotherMethod:function(){
            document.write(this.x*this.y);
        }
    });
    
    var b = new B();
    b.method();
    b.anotherMethod();
    

    こうすると、prototypeを使って継承するよりは見た目がスッキリします。
    クラスベースの継承に慣れたプログラマにとっても、JavaScriptのプロトタイプ継承をそのまま使うよりは読み易いコードになります。

    そのうえ、プロトタイプベースの機能も使えるので、工夫次第でJavaでは表現するのに手間取るような過激なコードを書くこともできます。

    例えばインスタンスごとに同じ名前で全く違う動作をするメソッドを追加したりするなどです。

    enchant();
    
    A = Class.create({
        initialize:function(){
            this.x=1;
        },
        method:function(){
            document.write(this.x);
        }
    });
    
    var m = [];
    for(i=0;i<10;i++){
        var obj = new A();
        m.push(obj);
        switch( i % 4 ){
            case 0:
    	    obj.method=function(){ //method()を全く違う内容に書き換えている
    	        document.write("<BR>");
    	    };
    	    break;
            case 1:
    	    obj.method=function(){ //method()を全く違う内容に書き換えている
    	        document.write("booe");
    	    };
            case 2:
    	    obj.x=2
    	    break;
        }
    }
    
    for(i=0;i<m.length;i++)
        m[i].method();
    

    こんなことができます。
    これをゲームプログラミングに応用すると、敵キャラの基本的なクラスをClass.createで定義しておき、雑魚キャラの細かい動きのところだけ同じメソッド名で違う内容にする、といったことが可能です。

    呼び出す時は配列に対して一括で同じメソッド名を呼ぶだけなので、プログラミングがし易くなります。

    もちろん、クラスベースの言語でも、全ての敵キャラのパターンにあわせて別のクラスを定義したりすれば実現できますが、ゲームで使う雑魚キャラの動きなどはそれほど大きく違うこともないので、本当に違う部分「だけ」を定義するならプロトタイプベースのメリットを活かした方が得です。

    こんなふうに、メソッドやプロパティの名前が同じなら、同じ動作をする「はずだ」というプログラミング手法を「ダックタイピング」と呼んだりします。

    この「ダックタイピング」が自由に使えるようになると、それができない言語に比べて何倍も効率的なコードを書くことが出来るのです。

    今回はちょっと難しい話をしてしまったかもしれません。
    どうですか?解っていただけたでしょうか。

  • 1 Comment
  • Filed under: 未分類
  • animation.enchant.js v0.1 公開

    本日、公式プラグイン animation.enchant.js のベータ版をリリースしました。このプラグインの機能は将来的に enchant.js 本体に組み込まれる予定です。

    ダウンロードは github からどうぞ。

    animation.enchant.js はアニメーションキューの機能を追加します。v0.1では、アニメーションキューを組み込んだSpriteクラス:AnimationSprite クラスを呼び出すことによって利用できます。

    単にトゥイーンライブラリとして、たとえば「ある場所にSpriteを簡単に移動させたり」「フェードアウト/インしたり」「視覚処理を付けて、ぬるっと移動・拡大縮小させたり」することができるだけではなく、ある処理にディレイをかけたり、処理の前後に自由に関数を実行したりすることもできます。

    サンプルは以下の通りです。赤いスプライトをクリックすると、キューに様々なアニメーションが追加され、実行されます。

    animation.enchant.js サンプル – jsdo.it – share JavaScript, HTML5 and CSS

    トゥイーンの追加

    bear = new AnimationSprite(32, 32);
    bear.animation.addTween({
        rotation: 360,
        scaleX: 2,
        scaleY: 2,
        time: 30
    });
    

    回転しながら拡大し、大きくなる。
    (bear.rotation は bear オブジェクトの回転角度、bear.scaleX, scaleY は縮尺を表します。上記のコードで実行している addTween メソッドで、bear のキューに30フレームかけて rotation, scaleX, scaleY を変化させるアクションを追加しています)

    トゥイーンは、x, y, scaleX, scaleY, opacity(不透明度), rotation などのプロパティだけではなく、どんなプロパティでも自由に変化させるすることができます。

    但し、時間を指定する time のほか、onload、callbackなど、指定することでトゥイーンを拡張できるプロパティもあります。

    • time: トゥイーンが終了するまでのフレーム数(必須)
    • onload: トゥイーンが始まったときに実行される関数
    • callback: トゥイーンが終わったときに実行される関数

    onload, callback は指定されていない場合は実行されません。

    イージング

    イージングとは、プロパティの値の変化を単に直線的に行うのではなく、数式に従って様々な効果を付けることを指します。例えば変化がだんだんと加速するような効果、端でバウンドするような効果をつけることができます。

    enchant.Easing のプロパティとして、デフォルトのイージング関数がいくつか登録されています。Robert Penner 氏によるものを利用しています(BSDライセンス)。

    bear = new AnimationSprite(32, 32);
    bear.animation.addTween({
        x: 320,
        y: 320,
        easing: enchant.Easing.BACK_EASEOUT,
        time: 30
    });
    // (320, 320) まで移動する。いったん端を通り過ぎて戻るような視覚効果がある
    
    bear = new AnimationSprite(32, 32);
    bear.animation.addTween({
        scaleX: 2,
        scaleY: 2,
        easing: enchant.Easing.BOUNCE_EASEOUT
        time: 30
    });
    // Spriteを拡大する。端でバウンドしたような視覚効果がある。
    

    ActionScript向けのトゥイーンライブラリ「Tweener」にプリセットされている数式はすべて使うことができます。イージングの数式についてグラフ化したものが Tweenerのドキュメント に記載されています。実際に動きを確認するには Aquioux氏のブログ をご参照ください。

    簡易記法

    トゥイーンを簡易的に記述する記法があります。

    bear = new AnimationSprite(32, 32);
    
    // 30フレームで (320, 320) に移動する。(moveTo: 絶対座標)
    bear.animation.moveTo(320, 320, 30);
    
    // 30フレームで (320, 320) に移動する。(moveBy: 相対座標)
    bear.animation.moveTo(-320, -320, 30);
    
    // フェードアウトする
    bear.animation.fadeOut(30);
    
    // フェードインする
    bear.animation.fadeIn(30);
    

    制御

    アニメーションだけではなく、様々な関数の実行にも利用できます。

    // 30フレーム後に消える
    bear.animation.delay(30).then(function(){
        game.rootScene.removeChild(this);
    });
    // delay(30) は、30フレーム経過するまで何もしないアクションを追加する
    // then(...) は、引数に渡した関数を実行するアクションを追加する
    // アクションは追加された順に実行されるので、30フレーム経過したあと指定した関数が実行される
    
    bear.animation.repeat(function(){...}, 60, 3);
    // 60フレームのあいだ、3フレームおきに1回指定した関数を実行する
    
    bear.animation.after(function(){...}).then(function(){...})
    // 1つ目の関数が true を返すまで待ったあと、2つ目の関数を実行する
    // after(..) は毎フレーム渡した関数を実行し、true を返したなら次のアクションに移る
    
    bear.animation.loop();
    // アニメーションキューをループさせる
    // (あるアクションが終わるとき、アクションは破棄されずキューの最後に追加される)
    
    bear.animation.pause();
    // アニメーションキューの実行を一時停止する
    
    bear.animation.start();
    // アニメーションキューの実行を再開する
    
    bear.animation.clear();
    // アニメーションキューを空にする
    

    animation.enchant.js によって追加された機能は、複雑なアニメーションの管理を必要とするゲームに最適です。本格的なゲームをどんどん作ってみてください!お待ちしています。

  • 8 Comments
  • Filed under: 未分類
  • about “enchant.js”

    enchant.js is an HTML5 + JavaScript based game engine. It is a standalone library that enables cross-platform application development for PC, Mac, iPhone, iPad, and Android from just 30 KB of source code.

    enchant.js was developed at Ubiquitous Entertainment Inc.'s Akihabara Research Center, and released April of 2011. Nearly 200 games have been created in its first two months of release, making it the world's most-used HTML5 game engine.

    enchant.js Official Website

    facebook Like