swf から CreateJS-Haxe用 extern クラスを生成するアプリ制作 其ノ二
前回の記事
http://www.dango-itimi.com/blog/archives/2013/001168.html
上記アプリケーション制作がほぼ完了しました。残り作業は ドキュメント制作と github への公開となります。公開後は、アプリケーション説明図付きで再度 blog に記述したいと思います。
以下、今回のアプリケーション制作において考えが抜けていた点と、アプリケーションを用いての Flash + html5 開発を同時に行なってみた感想を記述します。
考えが抜けていた点と対処
今回のアプリケーションを用いれば結構完璧な形で、Toolkit for CreateJS を用いての html5 開発と Flash 同時開発を行えるのではないか?と考えていましたが、すみません考えが抜けていた点がありました。それは、先日記事にしたばかりの「Toolkit for CreateJSではプロパティ名に連番が付与されてしまう問題」についてです。
Toolkit for CreateJS: プロパティ名に連番が付与されてしまう問題への対処
http://www.dango-itimi.com/blog/archives/2013/001164.html
Flash 内構造をそのままに CreateJS-Haxe 用 hx ファイルに変換したとしても、肝心のクラス内プロパティが存在しない場合が発生してしまいます。例えば当アプリケーションを用いる事で以下のようなクラスファイルが出力される予定でした。(後のサンプル用として変換前のクラスも記述しておきます。)
変換前 Flash-Haxe 用 View クラス
package shooting.enemy; extern class View extends flash.display.MovieClip, implements Dynamic { var hitarea : flash.display.MovieClip; function new() : Void; }
変換後 CreateJS-Haxe 用 Viewクラス
package shooting.enemy; @:native("lib.shootingenemyView") extern class View extends createjs.easeljs.MovieClip, implements Dynamic { var area : createjs.easeljs.MovieClip; }
上記変換後の area プロパティは、Toolkit for CreateJS の連番付与により undefined になってしまう(javascript 上では area_1 というプロパティ名に変換されてしまう)可能性があります。確実性を重視するのであれば、View.area プロパティをそのまま利用する事はできず、「Toolkit for CreateJS: プロパティ名に連番が付与されてしまう問題への対処」記事内にある対処法を採るしかありません。
対処
その他のわずかばかりの対処としまして、当アプリケーションからは以下の様な形式で変換を行うことにしました。
package shooting.enemy; @:native("lib.shootingenemyView") extern class View extends createjs.easeljs.MovieClip, implements Dynamic { var area : createjs.easeljs.MovieClip; public static inline var areaOriginalPropertyName = "hitarea"; }
一つのプロパティに付き、以下の形式の String プロパティが追加されます。
オリジナルのプロパティ名 + OriginalPropertyName = "オリジナルプロパティ名";
これにより、「Toolkit for CreateJS: プロパティ名に連番が付与されてしまう問題への対処」は以下のように記述する事ができます。
var view = new View(); //var area = getProperty(view, "area"); //修正前 var area = getProperty(view, View.areaOriginalPropertyName); //修正後
意味合いの薄い対処ですが、エディタのコード補完が効くので多少は記述が楽になります。
Haxe による html5, Flash 同時開発感想: Haxe の条件付きコンパイル指定記述は利用に難あり
当アプリケーションから出力された CreateJS-Haxe 用クラスを用い、早速 html5 canvas 表示物と Flash 表示物、両方同時に開発を行なってみました。
まずは Haxe の「条件付きコンパイル指定」で、一つのソースコード内に javascript 用記述と AS3 用記述を行なうコーディング方法を試しました。
参考) Haxe: 条件付きコンパイル
http://haxe.org/ref/conditionals
すると、いくつか問題がある事に気づきました。エディタ(IntelliJ IDEA)側の問題ともなりますが、問題点は以下の通りです。
・条件付き記述で囲まれた行はコード補完が効かなくなる
・条件付き記述で囲まれた行はリファクタリングの対象とはならない
条件付き記述により多少はソースコード記述量は減らせますが、対するデメリットのほうが大きいかなあ、という印象です。
私は結局 Haxe の条件付き記述は行わず、従来採っていた 共通処理をまとめる親クラスと、プラットフォームごとの小クラス、という切り分けで開発を行う事になりそうです。
一例としまして、簡単な条件付きコンパイルでコーディングを行なってみたクラスと、プラットフォームごとに小クラスを用意したクラスは以下となります。
条件付きコンパイル記述で一つにまとめた例
package shooting.enemy; #if flash import flash.display.DisplayObjectContainer; #elseif js import createjs.easeljs.Container; #end class Enemy { private var view:View; public function new( #if flash layer:DisplayObjectContainer #elseif js layer:Container #end ){ view = new View(); view.x = 400; view.y = 200; layer.addChild(view); } public function run(){ view.x -= 1; } }
共通部分は親に書き プラットフォーム専用の処理は小クラスに記述する例
・親クラス
package shooting.enemy; class Enemy { private var view:View; public function new(){ view = new View(); view.x = 400; view.y = 200; } public function run(){ view.x -= 1; } }
・Flash用クラス
package shooting.enemy; import flash.display.DisplayObjectContainer; class EnemyForFlash extends Enemy{ public function new(layer:DisplayObjectContainer){ super(); layer.addChild(view); } }
・javascript用クラス
package shooting.enemy; import createjs.easeljs.Container; class EnemyForJS extends Enemy{ public function new(layer:Container){ super(); layer.addChild(view); } }
コード内で生成している上述でも挙げた View クラスは当アプリの変換によって、Flash 用と javascript 用共通のインターフェースを持つため、親クラスにまとめることが可能です。
後日公開予定のアプリケーションサンプルプログラムでは、条件付きコンパイル指定での html5, flash 両開発用ソースコードと、プラットフォームごとに小クラスを用意するソースコード 二つを用意していますので、詳しくはそちらを確認いただけたらと思います。