Starling では、指による操作も、マウスによる操作も、どちらも同じイベント (TouchEvent) として扱います。
Flash Player のマウスイベントとは異なり、イベントの種類は TouchEvent.TOUCH の 1 つだけです。そのため、触れた、移動した等の操作の状態は、イベントに含まれる Touch オブジェクトの属性から判断することになっています。
Starling の全ての表示オブジェクト (Sprite, Stage, Quad, ...) は、TouchEvent を扱えます。ただ、Button クラスは、内部的にタッチイベントを triggered イベントに変換しているため、独自のリスナを追加するのは、注意した方がよいかもです。
また、表示オブジェクト自身や親オブジェクトの touchable 属性が false の場合は、TouchEvent を受け取ることはできません。
ともあれ、Starling でタッチ操作を扱うには、とりあえず、表示オブジェクトに TouchEvent.TOUCH イベントのリスナを追加することになります。下は、そのサンプルです。
import starling.events.TouchEvent; myImage.addEventListener(TouchEvent.TOUCH, onTouch); private function onTouch(e:TouchEvent):void { trace(e.target); }
Starling のイベントは、表示リストを上にバブリングするため、下の階層のオブジェクトからのイベントも取得できます。 (注:仕様上、階層の上から下への伝播はしないはずですが、今の実装では Stage からのイベントが届くこともあるようです)
サンプル内で使用している target 属性や currentTarget 属性の使い方は、Flash Player 標準のイベントと同じです。その他、TouchEvent には、以下のような属性があります。全て読み取り専用です。
ctrlKey: イベント発生時にCtrlキーが押されていたかを示す shiftKey: イベント発生時にShiftキーが押されていたかを示す timestamp: アプリケーションが起動してからの時間(単位は秒) touches: 利用可能なTouchオブジェクトのベクター
最後の touches は、イベントに関連する 1 つ以上の Touch オブジェクトのベクターです。Touch オブジェクトは、イベント発生の元となった指やマウスによる操作の情報を保持しています。
Touch オブジェクトの取得
TouchEvent には、Touch オブジェクトを取得するためのメソッドが用意されています。
マルチタッチを使わない場合は、getTouch() というメソッドで Touch オブジェクトを取得できます。 (マルチタッチの場合は後述)
import starling.events.Touch; private function onTouch(e:TouchEvent):void { var touch:Touch = e.getTouch(stage); if (touch) trace(e.target, touch.target); }
getTouch() メソッドの第 1 引数は、取得する Touch オブジェクトを絞り込むための条件です。
操作のターゲットとなった表示オブジェクトが、引数に指定したオブジェクトと一致する、もしくは引数の階層下に含まれる場合に、getTouch() は値を返します。実際の操作のターゲットは、Touch オブジェクト取得後に target 属性から参照できます。(操作のターゲットとイベントのターゲットは必ずしも一致しない点に注意)
Touch オブジェクトには、target 以外にも、操作を識別するための属性がいくつか存在します。
target: タッチ操作の対象となった表示オブジェクト id: タッチを識別するための数字 timestamp: タッチ操作が行われた時間(アプリ開始からの秒数)
TouchPhase
前述の通り、Touch オブジェクトには操作の状態を示す属性があります。属性名は phase です。
phase: 現在のタッチ操作の状況
phase 属性に設定可能な値は TouchPhases クラスに定義されています。
良く使われる値は以下の 3 つです。
- BEGAN: 指が画面に触れた、または、マウスボタンが押された
- MOVED: 指が画面上を移動した、または、マウスのボタンが押されたまま移動した
- ENDED: 指が画面から離れた、または、マウスボタンから離れた
BEGAN が 1 つ、MOVED が 0 以上繰り返され、ENDED が 1 つというのが、基本的な流れです。
その他に、以下の状態もあります。
- STATIONARY: 指もしくはマウスが前回のフレームから移動しなかった
通常、この状態ではイベントが発行されないはずですが、マルチタッチ操作を扱う場合には、STATIONARY が含まれることがあります。
最後に、マウス利用のときだけに起こる状態です。
- HOVER: マウスのボタンが押されない状態で、表示オブジェクト上にポインターがある
指では (いまのところ) 触れずにポインターを移動させることができないため、OVER はあっても HOVER は無いということになります。
ポインターの位置の取得
Touch オブジェクトは、ステージ上の、現在の位置と、前回の位置を、属性として持っています。以下の 4 つです。型はいずれも Number です。
globalX: ステージの座標を基準とした現在の指先(ポインター)の x 座標 globalY: ステージの座標を基準とした現在の指先(ポインター)の y 座標 previousGlobalX: ステージの座標を基準とした前回の指先(ポインター)の x 座標 previousGlobalY: ステージの座標を基準とした前回の指先(ポインター)の y 座標
しかし、たいていの場合は、別の座標系での位置を計算することになるでしょう。というわけで、Touch クラスには、上の属性値を、特定のオブジェクトを基準とした座標値に変換するメソッドが提供されています。
public function getLocation(space:DisplayObject):Point public function getPreviousLocation(space:DisplayObject):Point
これら 2 つのメソッドは、引数のオブジェクトの座標を基準にした、現在の位置、または前回の位置を返します。
下は、Touch オブジェクトの位置情報を利用するサンプルです。
var touch:Touch = event.getTouch(this, TouchPhase.MOVED); if (touch) { // 親オブジェクトを基準に移動距離を計算する var currentPos:Point = touch.getLocation(parent); var previousPos:Point = touch.getPreviousLocation(parent); var delta:Point = currentPos.subtract(previousPos); // オブジェクトの位置を変更 x += delta.x; y += delta.y; }
getTouch() メソッドの第 2 引数には、取得したい状態を指定できます。上のサンプルでは、指の移動の情報を扱うために TouchPhase.MOVED を指定しています。
ダブルクリックの扱い方
Touch オブジェクトは、ダブルクリック等を検知できるように、tapCount 属性に、瞬間的にタップされた回数を保持しています。
この属性を使って、ダブルクリックに対応するコードを記述してみたのが、下の例です。
touch = event.getTouch(this, TouchPhase.ENDED); if (touch && touch.tapCount == 2) parent.addChild(this);
操作状態が ENDED の Touch オブジェクトが存在して、タップの回数が 2 回だった場合を検出しています。
マルチタッチ
Starling はマルチタッチにも対応します。マルチタッチを扱う場合は、Starling オブジェクトに以下の設定をします。
mStarling.simulateMultitouch = true;
この状態で、実際にマルチタッチが行われると、タッチ毎に Touch オブジェクトが作られます。そして TouchEvent に渡されます。
TouchEvent から複数の Touch オブジェクトを取得するには getTouches() メソッドを使います。下はそのサンプルです。
var touches:Vector.<Touch> = touchEvent.getTouches(this);
戻り値は Touch のベクターです。getTouch() と同様、第 2 引数に、取得したい状態を指定できます。
ちなみに、Ctrl キーを使うと、デスクトップ環境でも、マルチタッチをシミュレートできるようになっています。もちろん、実際のアプリでマルチタッチが使えるのは、指で操作したときだけです。
これは素晴らしい記事ですね。
Starlingを基礎から説明してくれるのはほんと助かります。
Stalingの描画精度はゲーム制作に使えそうなので期待しています。
この記事とは関係ないのですが、FlashCS5.5体験版でAir For Androidでゲーム作りました。
CS5.5で作るのはほぼ初めてだったのですが、アプリのタッチ精度がCS5の頃に比べびっくりするほど向上していました。
ネイティブ並の精度になってきたと思います。
Air For Androidが本格的に実用化できそうな感触を掴めました。
凄いスピードで進化し、ユーザーのニーズにきちんと応えてる所がFlashの良い所なのだと再認しました。
これからもFlashの進化を楽しみにしております。
AIR / Flashに関する情報、いつも参考にさせていただいております!
ところでStarlingのMultitouchの取得に関して、
AIRでは無く、iOSのシュミレーターや実機で動かす場合は
Starling.multitouchEnabled = true;
が必要なようです。実際に調べればスグにわかることですが、一応お伝えしておきますね。