今回は、Starlingフレームワークに[ライブラリ]のビットマップからつくったインスタンスを置き、マウスでドラッグしてみる。どちらも少し定義済みActionScript 3.0の場合とは勝手が違う。ふたつに分けて進めていこう。
Starlingフレームワークに[ライブラリ]のビットマップを表示する
まずは準備として、[ライブラリ]のビットマップにクラス(Pen)を設定しておく(図1)。そして、インスタンスをFlashのタイムラインに動的に置くスクリプトから、先に確かめておこう。すでに第34回「3次元空間における回転」の「ビットマップのインスタンスを動的に配置する」で説明した処理のおさらいだ。
[ライブラリ]のビットマップ(クラスPen)は、ActionScript 3.0ではBitmapDataのサブクラスになる。そして、BitmapDataインスタンス(myBitmapData)はそのままタイムラインには置けない。そのため、Bitmapクラスのコンストラクタメソッドに引数として渡したうえで、Bitmapインスタンス(instance)をDisplayObjectContainer.addChild()メソッドでタイムラインに加えるのだった。
Starlingフレームワークではどうなるか。第1に、starling.display.DisplayObjectのサブクラスでなければ、Starlingのステージ(Stage3D)には置けない。そこで、Bitmapクラスに替えてStarlingのImageクラスを使う。コンストラクタメソッドの引数は、やはりビットマップイメージのオブジェクトだ。ただし第2に、BitmapDataオブジェクトは引数に使えない。Image()コンストラクタには、Textureクラスのオブジェクトを渡さなければならない(表1)。
表1 ビットマップイメージをステージに表示するために用いるクラス
役割 | クラス |
ActionScript 3.0定義済み | Starlingフレームワーク |
ビットマップイメージをもつ | flash.display.BitmapData | starling.textures.Texture |
ビットマップをステージに表示する | flash.display.Bitmap | starling.display.Image |
だが、使いたいのは[ライブラリ]のビットマップつまりBitmapDataインスタンスだ。この場合には、静的メソッドTexture.fromBitmapData()を用いればよい。引数のBitmapDataオブジェクトをTextureオブジェクトに変換して返してくれる。[ライブラリ]のビットマップをTextureオブジェクトに換え、Imageインスタンスに入れてStarlingフレームワークのステージに置くクラス定義(MySprite)がつぎのスクリプト1だ。
これで[ライブラリ]に納めたビットマップのイメージが、ステージ中央に表示される(図1)。前掲スクリプト1は、Imageインスタンスをつくるまでの処理を除けば、前回の「StarlingフレームワークでStage3Dを試す」で定義したクラスと基本的に変わらない。もちろん、前回述べたとおり、FLAファイルにはつぎのフレームアクションが書かれていて、[パブリッシュ設定]も正しく行われているものとする。
定義済みActionScript 3.0のフレームアクションによるドラッグ
ふたつ目の課題はマウスドラッグだ。これも、定義済みActionScript 3.0のフレームアクションによるスクリプティングを先に確かめておこう。タイムラインにはMovieCliipインスタンス(my_mc)が予めおかれているものとする。ドラッグは3つのマウスイベントを組合わせて扱う[1]。
- InteractiveObject.mouseDownイベント(定数MouseEvent.MOUSE_DOWN)のリスナー
- InteractiveObject.mouseMoveイベントにドラッグのためのリスナーを加える。
- InteractiveObject.mouseUpイベントにドラッグ終了のリスナーを加える。
- InteractiveObject.mouseMoveイベント(定数MouseEvent.MOUSE_MOVE)のリスナー
- インスタンスの位置をマウスポインタの座標に追随させる。
- InteractiveObject.mouseUpイベント(定数MouseEvent.MOUSE_UP)のリスナー
- InteractiveObject.mouseMoveイベントのリスナーを除く。
- InteractiveObject.mouseUpイベントのリスナーを除く。
3つのイベントリスナーで、タイムラインに置かれたインスタンス(my_mc)をドラッグできるように組立てたフレームアクションがつぎのスクリプト2だ。
スクリプト2について、ふたつ補っておこう。ひとつ目は、InteractiveObject.mouseMoveとInteractiveObject.mouseUpイベントのリスナーをStageオブジェクトに加えたことだ。これは、InteractiveObject.mouseDownイベントと異なり、マウスを素速く動かすと、イベントがドラッグしているインスタンスの外で起こってしまう場合に備えた。
ふたつ目は、InteractiveObject.mouseDownイベントのリスナー関数(xMouseDown)が、インスタンスから見たマウスポインタの座標を変数(nOffsetXとnOffsetY)にとっていることだ。なぜなら、InteractiveObject.mouseMoveイベントのリスナー(xDrag())がただマウス座標にインスタンスの位置を合わせれば、ポインタの先にインスタンスの基準点がきてしまう(図3)。そうならないためには、はじめにクリックしたインスタンス上の座標を覚えておき、ドラッグするときはその分を補正しなければならないのだ。
StarlingフレームワークのDisplayObject.touchイベントを用いたドラッグの扱い
Starlingフレームワークでは、マウス(タッチスクリーンも含めた)操作はすべてDisplayObject.touchイベント(定数TouchEvent.TOUCH)で捉える。それがどんな操作だったかは、リスナーが受取る引数のTouchEventオブジェクトからTouchオブジェクトを取出して、そのTouch.phaseプロパティで調べる。
Touch.phaseプロパティの値は文字列で、TouchPhaseクラスに定数として定められている。TouchPhaseクラスの定数とタッチスクリーンおよびマウスの操作は、つぎouchEventオブジェクト.の表2のとおりだ。
表2 TouchPhaseクラスの定数とタッチスクリーンおよびマウスの操作
TouchPhaseクラスの定数 | 操作 |
タッチスクリーン | マウス |
BEGAN | 画面に触れる | マウスボタンを押す |
ENDED | 画面から指を離す | マウスボタンを放す |
HOVER | - | マウスポインタを重ねる |
MOVED | 画面に触れた指を動かす | ボタンは押したままマウスを動かす |
STATIONARY | 画面に触れたまま動かさない | ボタンを押したままマウスは動かさない |
マウスをドラッグしているときのTouch.phaseプロパティの値はTouchPhase.MOVEDだ。しかも、ActionScript 3.0定義済みのInteractiveObject.mouseMoveイベントとは違い、インスタンスの上でマウスボタンを押したまま動かしていることを示す。つまり、この値だけでドラッグが捉えられ、別にマウスボタンを押したか放したかは気にしなくてよい。
さて、TouchEventオブジェクトからTouchオブジェクトを取出すのが、TouchEvent.getTouch()メソッドだ。引数はふたつある。
第1引数は、DisplayObject.touchイベントが起こったかどうか調べる対象のDisplayObjectインスタンスだ。インスタンスに子があれば(つまりDisplayObjectContainerのサブクラスなら)、その表示リストを下ってすべての子インスタンスが対象に含まれる。さらに第2引数のTouchPhaseクラス定数で、DisplayObject.touchイベントの操作を絞り込める。デフォルト値はnullで、すべてのマウスあるいはタッチスクリーン操作を調べる。そして、ふたつの引数で定まるTouchオブジェクトが見つかればそのオブジェクト、なければnullが返される。
すると、ドラッグのマウス操作は、前掲スクリプト1のクラス定義(MySprite)につぎのようなスクリプトを加えれば捉えられる。DisplayObject.touchイベントのリスナー関数(mouseOperated)で、TouchEvent.getTouch()メソッドによりTouch.phaseプロパティが定数TouchPhase.MOVEDのTouchオブジェクトを取出している。Touchオブジェクトが得られれば(nullでなければ)、ドラッグ操作が行われていることになる。後は、インスタンスをマウスポインタの位置に動かせばよい。
マウスポインタの座標はプロパティTouch.globalXとTouch.globalYで調べられる。ただし、座標がステージから見た値だということに気をつけなければならない[2]。それではドラッグの動きに使えないと思っただろうか。大丈夫だ、問題ない。Touchオブジェクトには、さらに前回のイベントのときのマウスポインタの座標がプロパティとして備わっている。Touch.previousGlobalXとTouch.previousGlobalYがそれだ。
すると、これら2種類のマウス座標プロパティの差を求めれば、イベントの間にマウスポインタがどれだけ動いたかわかる。その差の座標値をインスタンスの位置に加えれば、インスタンスはマウスポインタと同じだけ動く。前掲スクリプト2の定義済みActionScript 3.0の場合と違って、インスタンスが初めにクリックされた座標など覚えておかずに済む。
前掲スクリプト1にドラッグのための手を加たのが、以下のスクリプト3のクラス定義(MySprite)だ。もうとくに解説を補うには及ばないだろう。インスタンスをドラッグすると、マウスポインタと同じように動く(図4)。
Starlingフレームワークのドラッグの扱いは、定義済みActionScript 3.0より簡単だった。実は、単純なクリックがむしろやっかいだったりする。さて、いよいよ次回が本連載の最終回だ。Starlingフレームワークのクリックと当たり判定について解説する。最後までよろしくおつき合い願いたい。
今回解説した次のサンプルファイルがダウンロードできます。