ShowCase UI サンプル作成と Haxe 利用のポイント
今後の制作物において必要になりそうな UI パーツ Showcase を作成しました。加えて Haxe を利用するポイントを記述します。
■ Showcase 動作サンプル
ボタン押しっぱなしで自動スクロールします。ボタン当たり判定は両側から画面中央近くまであります。
http://www.dango-itimi.com/blog/swf/227/
使用言語・環境
以下の環境で作成しています。
・Haxe/JavaScript
・JQuery
・SCSS
ソースコード一式は以下に公開しています。
https://github.com/siratama/ShowCaseDom
ポイント
DOM構造を処理側から判別可能になるファイル出力ツールがあると良さそう
今回のサンプルの html DOM 構造は以下となっています。
https://github.com/siratama/ShowCaseDom/blob/master/deploy/index.html
上記に対しクラスファイル Root.hx を用意しました。
https://github.com/siratama/ShowCaseDom/blob/master/src/showcase/dom/Root.hx
これにより、以下のようにプログラムから DOM 構造へアクセスできます。
var root = new Root(); var itemsElement:JQuery = root.showcase.screen.items;
難点は、Root.hx を作成するのは面倒であり、開発中 DOM 構造が変化するたびに Root.hx を書き換える必要があります。よって html の DOM 構造を解析して Root.hx を自動的に出力するようなツールがあると便利となりそうです。これは Flash コンテンツ開発でいうところの、swc ファイルに近いです。
※ファイル出力は行わずとも Haxe のマクロ機能で もしかしたらなんとかなるのかなあ、などとも考えています。
http://qiita.com/shohei909/items/c71f9a8774245319d182
近年では様々なフレームワークが出ており、JavaScript 側から DOM 構造を知ることができる仕組みが用意されているものもある、ようです。
描画処理の分離と enum の利用
今回の Showcase UI では、描画とそれ以外の処理は分離して作成しています。肝となるクラスファイルは以下の三点(MVC)です。
・Display.hx : View
・Operator.hx : Model
・Transmitter.hx: Controller
描画が分離していない処理とは 例えば以下となります。DOM の p エレメントを右に30px移動する処理です。(Haxe JQueryExtern を利用)
class View { public function move(){ var element = new JQuery("p"); var positionLeft = element.position().left; element.css({left: positionLeft + 30}); } }
描画処理を分離すると以下のようになります。実データ(描画位置を示す positionLeft)は Model で持ち、データの加工も Model で行います。
class Model { var positionLeft:Float; public function move(){ positionLeft += 30; } }
View は更新された内容を画面に反映するだけとなります。
class View { public function setPosition(positionLeft:Float){ new JQuery("p").css({left: positionLeft}); } }
Model から View へのデータ受け渡しは Controller を介して行います。Contoroller にて、Model 内どのデータに変更があったのか、あるいは View の どの表示更新を行えばよいか の判定を行うには enum を利用すると便利です。
例えば Model を以下のようにします。「どの変更があったのか」「変更されたデータは何であるか」を enum に設定します。
enum Event { NONE; MOVE(positionLeft:Float); } class Model { private var event:Event; public function getEvent():Event { var n = event; event = Event.NONE; return n; } var positionLeft:Float; public function new(){ event = Event.NONE; } public function move() { positionLeft += 30; event = Event.MOVE(positionLeft); } }
Controller は以下のようにします。Controller の update メソッドは随時呼び出されます。
class Controller { private var model:Model; private var view:View; ...初期化処理 略... public function update(){ switch(model.getEvent()) { case Event.NONE: return; case Event.MOVE(positionLeft): view.setPosition(positionLeft); } } }
今回 Showcase 用に作成した、Display.hx, Operator.hx, Transmitter.hx は上記 Model, View, Controller の形式で作成されています。
描画分離と Haxe
今回は HTML/JQuery で UI を作成しましたが、Flash Player ターゲットでも、HTML5 Canvas ターゲットでも、その他 Haxe が対応している言語であるならば何にでも Model をソースコードそのままで利用できます。出力ターゲットを変更するには、View の内容を変更すれば良しとなります。これがクロスプラットフォーム言語の面白いところでしょうか。
私は、ブラウザミニゲームは何の出力ターゲットで作ったらよいかなあ、と悩む事がありますが、先に Model だけ先行して作成してしまう、という開発手法も採る事ができ 少々悩みの種がとれたりします。
出力ターゲットを切り替えてのテスト
Haxe 用 UnitTest ライブラリの MassiveUnit では、JavaScript ターゲットや Flash Player ターゲット出力の場合 テストはブラウザを介す事で実行され、テスト結果はブラウザに表示されます。
ブラウザ表示により、テスト結果が html で色分けされて表示されるのはとても見やすい一方、テストの度にアプリケーションがブラウザに切り替わるのはやや面倒な場合もあります。
ここで、Model はどの環境でも利用できるという性質から、ブラウザを介す必要のないターゲット(neko等)でテストを行ってしまう方法が採れます。
コマンドラインツールの同梱している IDE(IntelliJ IDEA の Terminal 機能等)を用いる事で、JavaScript ターゲットのソースコード開発を行いながら テストは Terminal の neko ターゲットで行う、といった具合に、ロジック部分はブラウザ無しでの開発手法が可能です。(出力ターゲットによっては処理結果が異なる場合があるので、その点は注意が必要です。)