4

さて、as3ではクリックすると最上位レイヤーのオブジェクトがクリックされます。誰かにスペースバーを押してもらい、画面上のオブジェクトが点に触れているかどうかを確認してもらいたいです。

だから私は最初にヒットテストを試しました...

if (this.hitTest(myPoint)){ play(); }

問題は、他のオブジェクトの背後にあるオブジェクトが、「クリック」されていると考えていたことです。

その後、イライラした後、Googleを使用しましたが、何も見つからなかったので、何か助けてください。

4

4 に答える 4

5

これがあなたが探しているコードだと思います:

stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e : KeyboardEvent) : void {
    if(e.keyCode == Keyboard.SPACE) {
        var objects : Array = stage.getObjectsUnderPoint(new Point(stage.mouseX, stage.mouseY));
        if (objects.length > 0) {
            var topmost : DisplayObject = objects[objects.length-1];
            trace(topmost.name);
        }
    }
});

キーはフラッシュのgetObjectsUnderPointメソッドです。

于 2011-04-29T08:48:59.847 に答える
2
DisplayObjectContainer.getObjectsUnderPoint()

getObjectsUnderPointここで証明されているように、DisplayObjectContainers を返さないことに注意してください。

var mc:MovieClip = new MovieClip();
var shape:Shape = new Shape();
    shape.graphics.beginFill(0);
    shape.graphics.drawRect(0,0,5,5);
mc.addChild(shape);
var shape2:Shape = new Shape();
    shape2.graphics.beginFill(0);
    shape2.graphics.drawRect(0,0,5,5);
mc.addChild(shape2);
addChild(mc);
getObjectsUnderPoint(new Point(1,1)); // returns [object Shape],[object Shape]

返された DisplayObjectsのプロパティを使用して、parentDisplayObjectContainer を見つけることができます...

var containerBeingLocated:Sprite;

for each (var obj:DisplayObject in objectsUnderPoint) {
    if (isWithin(obj, containerBeingLocated)) {
        trace('container located');
    }
}

function isWithin ($obj:DisplayObject, $container:DisplayObjectContainer):Boolean {
    while ($obj) {
        if ($obj === $container) {
            return true;
        } else {
            $obj = $obj.parent;
        }
    }
    return false;
}
于 2011-12-14T02:12:43.420 に答える
1

これは、すぐにコード化されたソリューションを持っていない優れた質問です。フォアグラウンドでクリックされる正確なものは、MouseEvent ターゲットとして無料で取得する場合に当然のことの 1 つです。簡単な部分は、すべての表示オブジェクトをセットアップして、スペースバーの押下に対応する KeyboardEvent をリッスンし、その時点でのマウス位置でテストをヒットすることです。

あなたの問題の残りの部分、本当の問題は、あなたがしなければならない 1 つの決定に要約されるように私には思えます。つまり、hitTest がヒットしたすべての DisplayObject のリストを取得したら、この比較関数を使用してそれらを前後に並べ替える必要があります。これがどのように機能するかを示しています。

DisplayObject A が DisplayObject B の前にあるか後ろにあるかを判断するには、表示リストの祖先を共通の祖先までさかのぼって追跡し、そこから次の世代を調べて、祖先がどこにあるかを確認する必要があります。分岐 - オブジェクト A の祖先がオブジェクト B の前または後ろにある (つまり、共通の祖先コンテナー内での相対的な深さ)。次のような表示ツリーを検討してください。

       E
      / \
     C   D
    /     \
   A       B

Eは共通祖先です。A が B の後ろにあるかどうかを判断するには、C が D の後ろにあるかどうかを確認する必要があります。つまり、E コンテナー内の C と D の深さを (DisplayObjectContainer.getChildIndex(child) を使用して) チェックする必要があります。明らかに、複雑な UI では、共通の祖先が何世代も前にある可能性がありますが、それがステージであっても、常に 1 つ存在します。

編集:

どうやって私は明白なことを見落としたのですか?! マウス ボタンをクリックしたくないのに、MouseEvents をまったく使用できないとは言いませんよね? ROLL_OVER または MOUSE_OVER イベントを使用して、何をロールオーバーしたかを追跡し、そのオブジェクトで HitTest を実行します [恥ずかしそうに額を叩きます]。

于 2011-04-29T00:59:37.983 に答える
0

いい質問です..見て回りますが、今のところ私が考えることができるのは、すべてのオブジェクトを含む配列を持ち (DisplayList に追加されたのと同じ順序で追加されます)、逆方向に反復して最初の衝突。

例 (非常に怠惰な例で申し訳ありません):

    var objs:Array = [];

/**
 * Returns an object at a point with the highest depth
 * @param at A Point to check at
 */
function checkForHighest(at:Point):DisplayObject
{
    var i:uint = objs.length-1;
    for(i; i>0; i--)
    {
        var j:DisplayObject = DisplayObject(objs[i]);

        if(objs.hitTest(at)) return objs[i];
    }

    return null;
}

最初に見つかった DisplayObject が、DisplayList の最上位になります。

于 2011-04-29T00:56:26.973 に答える