ngCoreでクラスを定義
ぱっと見て気づくのは、今まで書いてきた関数ベースのソースコードとは違うということです。今回は“剣の軌跡を表示する”という部分をクラス化してあります。
exports.Trajectory = Core.MessageListener.subclass({
この行でTrajectoryクラスを定義しています。ここでは、TrajectoryクラスはCore.MessageListenerクラスを継承します、ということを宣言しています。ngCoreでは独自クラスシステムを構築していて、あるクラスを継承する場合、そのクラスのsubclassメソッドを呼び出すことで継承を実現します。subclassの引数には新しいクラスの定義そのものをオブジェクト型で渡します。
ngCoreのクラスシステムには、いくつか決まりがあります。initializeという名前のメソッドはコンストラクタとして扱われます。initializeの中身を見ていきましょう。
this._emitter.addListener( this, this.onTouch );
これは、先ほど紹介したタッチのハンドリングです。エミッターにリスナーを登録しています。TrajectoryクラスはCore.MessageListenerを継承しているので、自身をリスナーとして登録できます。ここではonTouchメソッドをハンドラとして登録しています。これでTrajectoryクラスはアプリケーション上でタッチが発生した場合、その通知を受け取ることができます。
GL2.Primitiveで多角形を描画する
LIST7は、描画に関する部分です。
var p = new GL2.Primitive(); p.setType( GL2.Primitive.Type.TriangleStrip ); for (var i=0; i < this._maxLength * 2; i++) { var v = new GL2.Primitive.Vertex([0, 0], [0, 0], [1, 0, 0]); p.pushVertex(v); } this._prim = p; this._node.addChild( this._prim );
新しいクラスが2つも出てきました。GL2.PrimitiveとGL2.Primitive.Vertexです。この2つのクラスは“剣の軌跡を表示する”クラスの中で最も重要なクラスになります。
GL2.Primitiveはポリゴンを描画するためのクラスです。OpenGLの低レベルな部分を使い、2Dの点(Vertex)のリストをもとに画面にポリゴンを描画します。GL2.Spriteでは表現できない特殊な形状や部分的な色合いの変化を実現できます。“剣の軌跡を表示する”というような、矩形ではない形をリアルタイムで、スムーズに動かしたいという時にはぴったりのクラスと言えます。
使い方はとても簡単です。pushVertexというメソッドが用意されているので、このメソッドに点(Vertex)の情報をどんどん追加していくだけです。
var v = new GL2.Primitive.Vertex([0, 0], [0, 0], [1, 0, 0]); p.pushVertex(v);
この時に、点の情報を表すクラスとしてGL2.Primitive.Vertexが用意されています。LIST8はGL2.Primitive.Vertexのコンストラクタのシグネチャです。
GL2.Primitive.Vertex(position, uv, color) The default constructor. Parameters: {Core.Vector|float[2]} position A location. {Core.Vector|float[2]} uv A texture coordinate. {Core.Color|float[3]} color An RGB color triplet.
このVertexのリストは何をもとに変化していくのでしょうか? そう、ユーザーのタッチ操作によって変化していきます。次は先ほどタッチエミッターに登録したonTouchの中身を見てみましょう(LIST9)。
onTouch: function( touch ) { var x = touch.getPosition().getX(); var y = touch.getPosition().getY(); this._isMoving = false; switch (touch.getAction()) { case touch.Action.Move: this._vertexList.unshift( {x:x, y:y} ); this._isMoving = true; break; case touch.Action.Start: case touch.Action.End: default: break; } if (this._vertexList.length > this._maxLength) { this._vertexList.pop(); } return touch.getAction() === touch.Action.Start; }
さて、onTouchの中では何をやっているのでしょうか? switch文の中身がメインの処理です。注目してみましょう。
エミッターから送られてきたtouchインスタンスのgetActionメソッドの返り値でスイッチしています。このメソッドはタッチがどのような状態で行われたのかを値として返します。ここではその値がAction.Moveだった時に処理を行っています。Action.Moveは画面上で指をスワイプするような操作をした場合に使われます。
this._vertexList.unshift( {x:x, y:y} );
処理の内容はとても単純です。this._vertexはコンストラクタで初期化している配列ですが、この配列にタッチされた位置を追加しているだけです。配列の中身を変更しているだけなので、まだ描画に影響はありません。実際に描画に影響のある処理を行っている部分は、Trajactoryクラスの中にあるonUpdateメソッドです。