ActionScript 3.0で始めるオブジェクト指向スクリプティング

第63回 Starlingフレームワークでインスタンスのクリックをどう扱うか

この記事を読むのに必要な時間:およそ 7 分

最終回の今回は,Starlingフレームワークでインスタンスのクリックをどう扱うか解説したい。インスタンスのクリックは,もっとも基本的なマウスインタラクションだ。ところが,この扱いというのが,定義済みActionScript 3.0と勝手が違うだけでなく,思いのほかやっかいだったりする。

マウスボタンを放す操作はTouchPhase.ENDED

前回の第62回Starlingフレームワークで動的に置いたビットマップをドラッグするでは,インスタンスのドラッグについて学んだ。このときのスクリプト3「Starlingフレームワークでインスタンスをドラッグする」図1を,クリックのサンプルに書替えてみよう。

図1 Starlingフレームワークでインスタンスをドラッグするルートクラスの定義

図1Starlingフレームワークでインスタンスをドラッグするルートクラスの定義

まず,マウスボタンを放す操作のTouch.phaseプロパティ値は,定数TouchPhase.ENDEDで定められる(再掲第62回表2)⁠すると,TouchEvent.getTouch()メソッドの第2引数にこの定数TouchPhase.ENDEDを渡せば,マウスボタンを放す操作が捉えられる(前掲図1参照)⁠

第62回表2 TouchPhaseクラスの定数とタッチスクリーンおよびマウスの操作(再掲)

TouchPhaseクラスの定数操作
タッチスクリーンマウス
BEGAN画面に触れるマウスボタンを押す
ENDED画面から指を離すマウスボタンを放す
HOVERマウスポインタを重ねる
MOVED画面に触れた指を動かすボタンは押したままマウスを動かす
STATIONARY画面に触れたまま動かさないボタンを押したままマウスは動かさない

インスタンスをクリックしたら,一定の角度回すことにしよう。すると,第62回スクリプト3のDisplayObject.touchイベント(定数TouchEvent.TOUCHのリスナーメソッド(mouseOperated())につぎのような手を加えればよさそうだ。

private var angle:Number = 15 * Math.PI / 180;

private function mouseOperated(eventObject:TouchEvent):void {
  // var myTouch:Touch = eventObject.getTouch(instance, TouchPhase.MOVED);
  var myTouch:Touch = eventObject.getTouch(instance, TouchPhase.ENDED);
  if (myTouch) {
    /*
    var nMoveX:Number = myTouch.globalX - myTouch.previousGlobalX;
    var nMoveY:Number = myTouch.globalY - myTouch.previousGlobalY;
    instance.x += nMoveX;
    instance.y += nMoveY;
    */
    instance.rotation += angle;
  }
}

試してみると,確かにインスタンスをクリックすれば回転する。ただし,TouchPhase.ENDEDというのは,マウスボタンを放すのがインスタンス上でなくともよい。つまり,外でマウスボタンを放してもインスタンスは回ってしまうのだ図2)⁠しかし,インスタンスの外でマウスボタンを放したのはクリックではない。

図2 インスタンスの外でマウスボタンを放してもTouchPhase.ENDEDとみなされる

図2 インスタンスの外でマウスボタンを放してもTouchPhase.ENDEDとみなされる 図2 インスタンスの外でマウスボタンを放してもTouchPhase.ENDEDとみなされる

マウスボタンがインスタンス上で放されたのかを調べる

マウスボタンをどこで放しても,TouchPhase.ENDEDが拾ってしまう。そのため,マウスボタンを放したときのポインタの座標が,インスタンス上かどうかは改めて確かめなければならない。このとき用いるのが,DisplayObject.hitTest()メソッドだ。

DisplayObjectオブジェクト.hitTest(Pointオブジェクト, マウス操作対象に限定)

第1引数には,参照するDisplayObjectオブジェクトから見た座標を,Pointオブジェクトで定める。第2引数にtrueを渡すと,マウス(またはタッチ)操作できる表示されたインスタンスだけを対象にして,座標の重なりが調べられる(デフォルト値はfalse)⁠戻り値は,座標と重なるDisplayObjectインスタンスだ。また,重なりはインスタンスの矩形領域(Rectangleオブジェクト)の内側かどうかで決まる。座標が重ならないときはnullが返される。

そこで,つぎのスクリプト1は,DisplayObject.touchイベントのリスナーメソッド(mouseOperated())で,マウスボタンを放したときのポインタの座標が,インスタンス上にあるかどうか調べるようにした。TouchPhase.ENDEDのTouchオブジェクトがTouchEvent.getTouch()メソッドで得られたら,さらにDisplayObject.hitTest()メソッドでマウスポインタの座標がインスタンス上にあるのを確かめたうえで,インスタンスを回している。Touch.getLocation()メソッドは,引数に渡したインスタンスから見たマウスポインタの座標を返す。

スクリプト1 Starlingフレームワークでインスタンスのクリックを扱う

// ActionScript 3.0クラス定義ファイル: MySprite.as
package {
  import flash.display.BitmapData;
  import starling.display.Sprite;
  import starling.display.Image;
  import starling.textures.Texture;
  import starling.events.Event;
  import starling.events.TouchEvent;
  import starling.events.Touch;
  import starling.events.TouchPhase;
  import flash.geom.Point;
  public class MySprite extends Sprite{
    private var instance:Image;
    private var angle:Number = 15 * Math.PI / 180;
    public function MySprite() {
      addEventListener(Event.ADDED_TO_STAGE, initialize);
    }
    private function initialize(eventObject:Event):void {
      var myBitmapData:BitmapData = new Pen();
      var myTexture:Texture = Texture.fromBitmapData(myBitmapData);
      instance = new Image(myTexture);
      addChild(instance);
      instance.addEventListener(TouchEvent.TOUCH, mouseOperated);
      instance.x = stage.stageWidth / 2;
      instance.y = stage.stageHeight / 2;
      instance.pivotX = instance.width / 2;
      instance.pivotY = instance.height / 2;
    }
    private function mouseOperated(eventObject:TouchEvent):void {
      var myTouch:Touch = eventObject.getTouch(instance, TouchPhase.ENDED);
      if (myTouch) {
        var mousePoint:Point = myTouch.getLocation(instance);
        if (instance.hitTest(mousePoint, true)) {
          instance.rotation += angle;
        }
      }
    }
  }
}

これで,マウスボタンをインスタンス上で押し,かつその上で放したとき,つまりクリックしたときだけインスタンスの角度が変わる。インスタンスが矩形であればこれでよい。しかし,前述のとおり,インスタンスのかたちにかかわらず,DisplayObject.hitTest()メソッドは矩形領域で座標との重なりを評価する。矩形でないインスタンスをどう扱えばよいか,次項で考えてみよう。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書

コメント

コメントの記入