矩形と矩形の衝突

矩形同士の衝突判定には Rectangle.intersects メソッドを使います。

var a:Rectangle = new Rectangle(0, 0, 100, 100);
var b:Rectangle = new Rectangle(0, 0, 100, 100);

trace(a.intersects(b)); // => true
// 逆にしても同じ
trace(b.intersects(a)); // => true

これを前提に、マウスでドラッグした範囲にある矩形が含まれるかをチェックしましょう。

まずはマウスイベントから。Flash の MouseEvent で取得できるマウスの座標は2種類あります。

  • localX, localY
    • オブジェクトの親から見た座標
  • stageX, stageY
    • ドキュメントルートから見た座標

ここで localX や localY はマウスがポイントしているオブジェクトを基準に値が変わってしまいます。そこで、どんな場合でも使えるように stageX と stageY を採用します。

次に配置されたオブジェクトから座標やサイズを矩形として求めるには getBounds 及び getRect メソッドを用います。

var sp:Sprite = new Sprite();
addChild(sp); 
// stage を基準に sp の座標を矩形として取得
var rect:Rectangle = sp.getRect(stage);

では、実際の例を確認します。サンプルとして、以下のような mxml ファイルを用います。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Canvas id="parentCanvas">
    <mx:Label x="0" y="0" width="100" height="30" />
    <mx:Label x="0" y="50" width="100" height="30" />
    <mx:Label x="0" y="100" width="100" height="30" />
    <mx:Label x="0" y="150" width="100" height="30" />
    <mx:Label x="0" y="200" width="100" height="30" />
  </mx:Canvas>
</mx:Application>

マウスのイベントを受け取るよう parentCanvas に以下のようなイベントを実装します。

import flash.events.*;
import flash.geom.*;

var startX:Number;
var startY:Number;
var destX:Number;
var destY:Number;

function init() {
  parentCanvas.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  parentCanvas.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}

private function mouseDownHandler(e:MouseEvent):void {
  startX = e.stageX;
  startY = e.stageY;
}

private function mouseUpHandler(e:MouseEvent):void {
  destX = e.stageX;
  destY = e.stageY;

  checkHit();
}

private function checkHit():void {
  // ここで先ほど取得した座標を Rectangle に変換
  // 本当は逆方向へのドラッグを考慮するべきなので、注意
  var region:Rectangle = new Rectangle(startX, startY, destX - startX, destY - startY);

  // 子オブジェクトをすべて取得して、チェックする
  var childern:Array = parentCanvas.getChildren();
  for(var i:int = 0; i < children.length; i ++) {
    // ここで、子の標示領域も stage からの座標による領域に変換
    var bound:Rectangle = children[i].getBounds(stage);
    // ドラッグされた領域と衝突するか?
    if(bound.intersects(region) == true) {
      // お好きなようにどうぞ
    }
  }
}

以上、ミニマムなサンプルでした。ドラッグによる領域に限らず stage からの領域に変換してしまえば比較可能なので、割合使えます。

追記、座標と矩形の衝突判定

上で行ったのは矩形と矩形でしたが、座標が衝突したかどうかは簡単に判定できます。

function init() {
  parentCanvas.addEventListener(MouseEvent.CLICK, clickHandler);
}

private function clickHandler(e:MouseEvent):void {
  var childern:Array = parentCanvas.getChildren();

  for(var i:int = 0; i < children.length; i ++) {
    if(children[i].hitTestPoint(e.stageX, e.stageY) == true) {
      // お好きなようにどうぞ
    }
  }
}

以上、 hitTestPoint メソッドを使えば終了。引数で渡す座標は stage からの座標なので、例によって stageX 及び stageY を使います。