この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
前回、Haxe で CreateJS を使用する環境を作りました。引き続き今回は、Flash で作成したシンボルを Toolkit for CreateJS で書きだして、Haxe で使えるようにしてみます。もちろん、Dynamic 型ではなく、クラスを定義してオートコンプリートが効くようにする事を目指します。これができるようになると、いよいよ Flash っぽくなってきますね。
Haxe で JavaScript のライブラリを使用する
Toolkit for CreateJS(長いので以下 TfCJS)に取り掛かる前に、少し回り道になりますが Haxe で JavaScript のライブラリを使用する方法について説明しておきます。
前回、Haxe 内で CreateJS や jQuery を使えるように、既存の Haxe 向けライブラリを haxelib コマンドでインストールしました。これらの有名な JavaScript ライブラリは、Haxe 向けのライブラリも用意されているため、感謝しつつそれらをインストールするだけで済んでしまいます。しかし、いつでもそのような Haxe 向けのライブラリが用意されているわけではありません。もし自分で作成した JavaScript ライブラリを Haxe で使用する場合、Haxe へ対応させる作業は自分で行うことになります。
仮に、以下の様な JavaScript があったとします。
utils.Tracer.js
if (typeof console === "undefined" || console === null) {
console = {};
}
if (typeof console.log !== "function") {
console.log = function () {};
}
if(typeof utils === "undefined" || utils === null) {
utils = {};
}
utils.Tracer = {
trace: function(str){
console.log(str);
}
};
console.log() をラップしただけの、ライブラリと呼ぶのも躊躇われる js ですが、これを Haxe に対応させてみます。と言っても手順は簡単で、JavaScript ライブラリが持つメソッドを記述した extern クラスファイルを作るだけです。
まず JavaScript の名前空間と同じ utils パッケージを作り、その中に JavaScript のオブジェクト名と同じ Tracer クラスを作ります。Tracer クラスの中身には、以下のように記述します。
/src/utils/Tracer.hx
package utils;
extern class Tracer {
public static function trace(str:String):Void;
}
"extern" を付けることがが重要です。このクラスが、実行時に使用可能になるオブジェクトのインターフェイス定義である事を示します。これだけで、Tracer クラスが使用可能になりました。
試しに Main.hx 等で "Tra" とタイプすると補完が出てこなくて焦りますが、"utils" からタイプすると出てきます。
余談ですが、コンソール出力してくれる機能は haxe.Log クラスの trace で実装されているので、自作する必要はありません。
Toolkit for CreateJSで作ったライブラリを使用する
ではこの応用で、 TfCJS から書きだしたライブラリを Haxe に取り込んでみます。まず Flash で、こんなアニメーションを作ってみました。
MovieClipAssets.swf
[SWF]https://cdn-ssl-devio-img.classmethod.jp/wp-content/uploads/2013/01/MovieClipAssets.swf, 100, 100[/SWF]
これを TfCJS で書きだすと、こんな感じのjsが出力されます。
MovieClipAssets.js
(function (lib, img, cjs) {
var p; // shortcut to reference prototypes
// stage content:
(lib.MovieClipAssets = function() {
this.initialize();
// レイヤー 1
this.instance = new lib.SampleMovieClip();
this.instance.setTransform(50,50);
this.shape = new cjs.Shape();
this.shape.graphics.f("#999999").s().p("AH0nzIAAPnIvnAAIAAvnIPnAA").cp();
this.shape.setTransform(50,50);
this.addChild(this.shape,this.instance);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,100,100);
// symbols:
(lib.Tween1 = function() {
this.initialize();
// レイヤー 1
this.shape = new cjs.Shape();
this.shape.graphics.f("#000000").s().p("AhjhjIDHAAIAADHIjHAAIAAjH").cp();
this.addChild(this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(-9.9,-9.9,20,20);
(lib.SampleMovieClip = function(mode,startPosition,loop) {
this.initialize(mode,startPosition,loop,{},true);
// レイヤー 1
this.instance = new lib.Tween1("synched",0);
this.timeline.addTween(cjs.Tween.get(this.instance).to({rotation:360},49).wait(1));
}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(-9.9,-9.9,20,20);
})(lib = lib||{}, images = images||{}, createjs = createjs||{});
var lib, images, createjs;
この js では、Flash のステージコンテンツに対応している MovieClipAssets オブジェクトと、作成したシンボル "SampleMovieClip" に対応した SampleMovieClip オブジェクト、また、その中で使われている Tween1 オブジェクトが、名前空間 lib の中に定義されています。
では、この js ファイルをプロジェクトの bin ディレクトリにコピーした後、先ほどの JavaScript ライブラリをHaxeに対応させる手順に則って、これらに対応する extern クラスを lib パッケージ内に作成していきます。
/src/lib/MovieClipAssets.hx
package lib;
import createjs.easeljs.Container;
extern class MovieClipAssets extends Container {
}
/src/lib/SampleMovieClip.hx
package lib;
import createjs.easeljs.MovieClip;
extern class SampleMovieClip extends MovieClip {
}
シンボル独自のメソッドやプロパティは持たないため、それぞれに対応する CreateJS のクラスの継承だけで事足ります。
ただし、現在 haxelib に登録されている CreateJS-Haxe(v1.1) の MovieClip クラスにはバグがあるようで、このままコンパイルするとエラーになってしまいます。Github からバグ修正済みの MovieClip.hx をダウンロードして差し替える必要があります。
https://github.com/nickalie/CreateJS-Haxe/blob/master/createjs/easeljs/MovieClip.hx
差し替える対象のファイルは、Haxe インストールディレクトリの下の \lib\createjs\1,1\createjs\easeljs に入っています。
それでは早速、実際に作ったクラスを使ってみます。
/bin/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<title>CreateJSTest</title>
<meta name="description" content="" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.3.0.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.5.0.min.js"></script>
</head>
<body>
<script src="NewProject.js"></script>
<script src="MovieClipAssets.js"></script>
<canvas id="canvas" width="250" height="250"></canvas>
</body>
</html>
/src/Main.hx
package ;
import createjs.easeljs.Stage;
import createjs.easeljs.Ticker;
import js.JQuery;
import js.Lib;
import lib.MovieClipAssets;
import lib.SampleMovieClip;
class Main {
private var stage:Stage;
//エントリポイント
public static function main():Void{
new Main();
}
//コンストラクタ
public function new() {
new JQuery(Lib.document).ready(function(e:JqEvent):Void {
stage = new Stage(cast Lib.document.getElementById("canvas"));
//MovieClipAssetsをステージに追加
var mca:MovieClipAssets = new MovieClipAssets();
stage.addChild(mca);
//SampleMovieClipをステージに追加
for (i in 0...20) {
var smc:SampleMovieClip = new SampleMovieClip("independent", 0, true, null);
stage.addChild(smc);
smc.x = 250 * Math.random();
smc.y = 250 * Math.random();
}
//24fpsでstageを描画更新する
Ticker.setFPS(24);
Ticker.addListener(stage);
});
}
}
実行結果
Flash で作ったステージコンテンツ(グレーの四角)をまるごと使うことも、シンボル(回転する黒い四角)ごとに個別に使う事もできます。Flash コンテンツを TfCJS で書き出す際には色々と制限があり、Flash で作ったものを何でも書き出せるわけではありませんが、静止画像やシンプルなアニメーション程度なら全く問題はありません。
注意点
TfCJS は、デフォルトで lib, images, createjs の各名前空間を使用するため、もし Haxe 側でこれらと競合するパッケージに extern ではないクラスを配置すると、Haxe が作るレキシカルスコープ内のパッケージオブジェクトに、TfCJS のグローバルスコープのオブジェクトが隠蔽されてしまい、コンパイルは通りますが実行時エラーが発生してしまいます。entern クラスのパッケージの最上位を window にする事でも回避可能ですが、あまりスマートなやり方ではない気がします。
TfCJS の設定で、出力される js で使用する名前空間を変更する事が可能ですので、もし競合する場合は必要に応じて設定を変えましょう。個人的には、TfCJS が使用する名前空間 lib と、Haxe で JavaScript のオブジェクトにアクセスするためのクラス js.Lib がオートコンプリート時に紛らわしいので、別の名前空間に変更したほうが良いと思います。
今回参考にさせて頂いたサイト様
CreateJS & Haxe : MovieClip.hx, Timeline.hx, Point.hx 修正・処理追加
http://www.dango-itimi.com/blog/archives/2013/001151.html