NME もとい OpenFL に関して調査を行いました。OpenFL とは何かと言いますと、こちらの方の言葉をお借りするのであれば「DisplayObject のクロスプラットフォーム化ライブラリ」となります。Haxe で記述し、最近 NME という名前から OpenFL という名前に変わりました。
実際に利用してみて、どういったものなのか理解できた点を記述します。
OpenFL Get Started
https://github.com/openfl/openfl/wiki/Get-Started
外部 swf を組み込んでの開発が可能
Haxe で Flash コンテンツを制作する場合、外部 swf を利用しての開発(オーサリングツール Flash CC を起点とした開発)が可能となります。
OpenFL ではどうだろうかと調べてみたところ、同様に 外部 swf を利用しての開発が可能な事がわかりました。ただし利用するにあたって条件や制限事項があります。
出力ターゲット
OpenFL の出力対象は大きく以下の三つに分けられます。
・Flash(swf)
・native(windows, mac, ios, android, etc...)
・html5
Flash をターゲットとした出力は、Haxe で Flash コンテンツ開発を行うそのままの方法を採れます。開発もしやすく、外部 swf も内容そのままに利用できます。
一方 native, html5 をターゲットとした場合は、OpenFL の Assets 機能を利用して外部 swf 内データにアクセスする形となります。-swf-lib コンパイラオプション指定での swf の利用はできないようです。
NME Assets (NME 時代のドキュメントにつき情報が古いため注意)
http://www.nme.io/developer/documentation/key-concepts/assets/
もちろん Flash をターゲットとした出力の場合でも、native, html5 ターゲット出力と同じくAssets 機能からの外部 swf 利用も可能です。
Assets 機能
Assets 機能を利用するための Assets クラスの内容を見てみたところ、コンテンツ実行時 swf を読み込み バイナリ解析して swf 内の情報を再現する方法を採っているようです。どの位置に何が配置されていて、何ピクセルの線の太さで描画を行う、等など swf 内の構造が Flash 以外ののプラットフォーム向けに再構築される形となります。(完全にソースを解析したわけではないので、誤っていたらごめんなさい。)
こういったことから、swf 内情報の再現度は 100% ではなく、例えば native ターゲットでの出力の場合 ベクターデータが欠けてしまう、といった問題を確認しました。また、html5 をターゲットとした出力の場合 エラーでほとんど機能してくれないようです。
また、swf 内から情報を取り出す際 MovieClip として抽出されるため、MovieClip 内に配置した MovieClip にアクセスするためには MovieClip.getChildByName メソッドでアクセスする必要がある等、少々手間がかかります。詳細は後述します。
ベクターデータ欠け実例
丸や三角といった簡単な形状ではなく、複雑なベクターデータで検証を行なってみました。
最初の画像が元ベクターデータ、次の画像が OpenFL android 上で出力されたデータです。目の部分が欠けてしまってます。またアンチエイリアスがない状態で描画されています。
アンチエイリアスをかける方法(画質設定)は OpenFL のどこかの設定で行える可能性があります。ベクターデータ欠けに関しましては、ベクターデータを分解する、画像にする、あるいはベクターデータ自体に色々工夫をこらす事で解決できる事もあります。ここらへんは Flash 開発に長らく関わってきた人はおなじみの対処ともなりそうです。
ベクターデータが欠けてしまうとはいえ、swf バイナリ解析でここまで再現できてしまうとは、いやはやすごいものです。
html5 は Toolkit for CreateJS の利用を
html5 をターゲットとした出力の場合、外部 swf の利用はほとんど無理のようです。現在のところ Flash CC を用いて html5 canvas コンテンツを作成したい場合、Toolkit for CreateJS を利用するのがよしとなります。OpenFL の html5 出力機能は今後に期待といったところでしょうか。
その他 制限事項や不具合
まだちょっと検証しただけですが 以下の様な現象を確認しています。
・Flash CC 上で設定したテキストフィールドは再現されず
・MovieClip totalFrames が正常な値を返さない
数少ない NME 時代の日本語情報を見ても、その他 不具合があるようです。ただし、OpenFL になってからこの不具合解消はどんどん行われるのではないかと思います。開発者の人が丁寧にフォーラムや twitter 等の各所で対応されているのを見ます。
追記:2013年7月7日)
currentFrames, totalFrames が正常な値を返さないのは「Assets 機能を利用した Flash ターゲット出力」の場合となります。native ターゲット出力の場合、正常な値を返す事がわかりました。Assets 機能を利用して、なおかつ Flash ターゲット出力を行いたい場合、format.swf.instance.MovieClip 内にある get_currentFrame or get___totalFrames メソッドを利用すれば、正常な値を取得できます。これらメソッドは暫定的に用意されている可能性があります。
追記:2013年7月10日)
_ゴシックといったデバイスフォントを指定した場合、OpenFL でも利用できることがわかりました。他にも利用できる条件があるかもしれません。
クロスプラットフォーム向け処理作成
Flash API 準拠に
NME 時代では nme.display.Sprite といったパッケージ構造だったものが、OpenFL では flash.display.Sprite という Flash API 準拠になりました。今まで Haxe で Flash コンテンツを開発していた人がそのまま OpenFL に移行しやすい形となっています。
Assets 機能を利用した場合と そうでない場合との比較
そのまま OpenFL に移行しやすいとはいえ、native をターゲットとした出力を行いたい場合、Assets クラスを利用しての独特な記述による 外部 swf 内情報へのアクセスが必要となります。
例えば、外部 swf(view.swf) 内 test.View というリンケージ設定を行ったムービークリップを生成するには以下のような記述を行います。
var testView = Assets.getMovieClip("view:test.View");
testView インスタンスは test.View クラスとしてではなく MovieClip として抽出されるため、test.View 内に配置したムービークリップ testPoint にアクセスするためには、以下の様な方法を採ります。
var testPoint = cast(testView.getChildByName("testPoint"), MovieClip);
trace(testPoint.x, testPoint.y);
一方 Haxe で Flash コンテンツを作成する場合、以下の用に記述すればよしとなります。あらかじめ swf の情報を外部クラスとして出力し、-swf-lib パラメータによる外部 swf の埋め込みを利用します。
var testView = new test.View();
var testPoint = testView.testPoint;
trace(testPoint.x, testPoint.y);
native をターゲットとした出力を行いたい場合も、このようにシンプルな記述でムービークリップを生成し、ムービークリップ内のプロパティにアクセスしたいものです。生成するシンボルが多くなると、条件付きコンパイル指定等で処理を書き分けるのも大変です。
何か方法はないだろうかと考えた所次の方法を思いつきました。
Haxe の 抽象型(abstruct)を利用して処理共通化を図る
swf からクラス情報を出力した場合の test.View クラスの内容が以下だったとします。(自作 JSFL の FlashToHaxeConverter からの出力です。)
package test;
extern class View extends flash.display.Sprite{
var testPoint : flash.display.MovieClip;
}
対して、native ターゲット出力を行う場合、利用する test.View クラスが以下のように定義されていれば良しとなります。
package test;
import flash.display.MovieClip;
import openfl.Assets;
abstract View(MovieClip) {
public function new()
this = Assets.getMovieClip("view:test.View");
@:to public function getInstance():MovieClip
return this;
public var testPoint(get, never):MovieClip;
function get_testPoint(){
return cast(this.getChildByName("testPoint"), MovieClip);
}
}
Flash ターゲット出力の場合でも native ターゲット出力の場合でも、以下の記述で test.View クラス、test.View.testPoint プロパティにアクセスできます。
var testView = new test.View();
var testPoint = testView.testPoint;
trace(testPoint.x, testPoint.y);
Haxe の抽象型については以下に書かれています。
http://haxe.org/manual/abstracts
結構難解で、どういう場面で利用すればよいのかわからなかった抽象型ですが、試しに上記クラスを作ってみたら動いたので、なるほどこういう時に使えばよいのか、と何となく理解できた次第です。もっと上手い書き方はあるかもしれません。
FlashToHaxeConverter を OpenFL 対応に
test.View を抽象型クラスにする手順・方法はどうするのか、という話となります。swf 出力の度に毎回上記 抽象型クラスを手書きで作成するわけにもいきません。そこで JSFL の出番となります。
Flash コンテンツと CreateJS による html5 canvas コンテンツ並行開発用として以下の JSFL を公開していますが、これに OpenFL 用抽象型クラス出力機能を実装しようかと考えています。
FlashToHaxeConverter
https://github.com/siratama/Flash-To-Haxe-Converter
想定通りならば、Flash, html5 canvas 並行開発の作業そのままに、OpenFL による native コンテンツの並行開発も可能になりそうです。
抽象型クラスより もっとよい方法が見つかる可能性もありますし、抽象型クラスで問題が発生する可能性もあるため、もう少しの検証後に実装を予定したいと思います。
制限事項
abstract test.View クラスは MovieClip を親として定義されていないため、以下はエラーとなります。
var testView = new test.View(); //using abstract test.View
trace(testView.x); //error
よって一度キャストを行う必要があります。
var testView = new test.View();
var mc:MovieClip = cast testView;
trace(mc.x);
私が作成している Flash & CreateJS 並行開発用 Haxe ライブラリでの MovieClipUtil クラスでは、一度キャストを行うように作っているため、上記 abstract MovieClip の利用もそのまま行えそうではあります。
参考)Haxe Box2D を利用した html5, Flash 並行開発コンテンツサンプル
http://www.dango-itimi.com/blog/archives/2013/001178.html
追記:2013年7月7日)
抽象型クラスは Type.createInstance メソッド経由での生成が意図通り行えません。
var testView = Type.createInstance(test.View, []);
addChild(testView); //eror
クラスを引数にし、内部で Type.createInstance によるインスタンス生成を行うようなライブラリ等は利用できなくなるため注意が必要です。自作ライブラリの場合、あらかじめ外部でインスタンスを生成し、そのインスタンスを引数にして渡すような作りにする必要があります。
Adobe AIR を介さない 外部 swf を利用しての native アプリ開発が可能に
制限事項や不具合はまだあるものの、OpenFL を利用する事で、Flash CC はすでにクロスプラットフォーム向けのオーサリングツールになっている、と言えましょう。swf を素材ファイルとして Adobe AIR を利用する事無く、直で native(windows, mac, Android, iOS, etc)アプリが開発できてしまいます。
Flash コンテンツは Adobe AIR を用いれば、そのまま iOS, Android アプリに変換できましたが、懸念点がありました。Android アプリの場合、AIR ランタイムで間接的に動作するという事から、native アプリに比べ処理速度が遅くなってしまいます。
参考)box2dFlash v2.1a を用いた AIR アプリが nexus7 でどれくらいの動作速度になるかの検証
http://www.dango-itimi.com/blog/archives/2012/001136.html
AS3 の Box2D は C で書かれたものに対し四倍ほど遅くなるとのことです。
http://j15r.com/blog/2013/04/25/Box2d_Revisited
OpenFL ならば C++ によって Android アプリが出力されるため、Box2D も本来の威力を発揮してくれるのではないかと思います。
リスク
今まで不可能だと思えたことが可能になってしまった OpenFL ですが、まだまだ検証が足りていません。特に mac, iOS をターゲットとした出力は Xcode が必要であり、私は Mac を所持していないため検証ができていません。安く購入できるのであれば 検証用に一台欲しいところです。
OpenFL はどういうコンテンツ向けにまで対応できるかも考える必要があります。スマートフォンアプリ制作が可能だが、ここにカメラ機能を実装してほしい、と言われた時、可能なのかどうなのかもわからず、ネット上の英語の資料を探すしかありません。(Adobe AIR なら可能)
今後実際にサンプルコンテンツ制作を行なっていき、どれくらいのものなのかじっくりと見極めていきたいと思います。
別途 インストール設定等、android 出力設定に少々つまずいた箇所があるため後日記事にしたいと思います。
[ FLASH ]
[ tips ]
2013年07月05日 16:21
| コメント (0)
| トラックバック