AS3 - 检测您是否在不按下鼠标按钮的情况下单击了某个对象

发布于 2024-11-03 16:21:31 字数 213 浏览 4 评论 0原文

好的,在as3中,当您单击时,将单击最高层上的对象。我希望有人按空格键并将物体放在屏幕上检查它是否接触到某个点。

所以我首先尝试了 hittest...

if (this.hitTest(myPoint)){ 玩(); 现在

的问题是其他对象后面的对象认为它们被“点击”。

然后在沮丧之后我使用谷歌,找不到任何东西,所以请有帮助。

Okay, in as3 when you click, the object on the highest layer will be clicked on. I want someone to press the space bar and have the objects on the screen to check to see if it is touching a point.

So I first tried hittest...

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

Now the problem was objects behind other ones were thinking they were being "clicked" on.

Then after being frustrated I used Google, couldn't find anything so please anything helps.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

江湖正好 2024-11-10 16:21:31

我认为这是您正在寻找的代码:

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);
        }
    }
});

Key is flash's getObjectsUnderPoint 方法。

I think this is the code you are looking for:

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);
        }
    }
});

Key is flash's getObjectsUnderPoint method.

蓝天 2024-11-10 16:21:31
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 的 parent 属性来查找 DisplayObjectContainer...

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;
}
DisplayObjectContainer.getObjectsUnderPoint()

Be mindful getObjectsUnderPoint doesn't return DisplayObjectContainers, as evidenced here:

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]

You can use the parent property of returned DisplayObjects to find a DisplayObjectContainer...

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;
}
恋你朝朝暮暮 2024-11-10 16:21:31

这是一个很好的问题,但我没有现成的编码解决方案。当您免费获得它作为 MouseEvent 目标时,您认为理所当然的事情之一就是前台中的哪个东西被点击。简单的部分是设置所有显示对象以侦听与按下空格键相对应的 KeyboardEvent,并用当时的鼠标位置进行点击测试。

在我看来,你的其余问题,真正的问题,似乎可以归结为你需要做出的一个决定:A 和 B 占据相同的屏幕空间,哪一个在前面。换句话说,一旦您获得了 hitTest 命中的所有 DisplayObject 的列表,您就需要此比较函数对它们进行从前到后的排序。我的看法是这样的:

要确定 DisplayObject A 是在 DisplayObject B 的前面还是后面,您需要将它们的显示列表祖先追溯到它们的共同祖先,然后查看从此向下的下一代,看看是否--在它们的祖先分歧的点上--对象 A 的祖先位于对象 B 的前面或后面(即它们在共同祖先容器中的相对深度)。考虑这样的显示树:

       E
      / \
     C   D
    /     \
   A       B

E 是共同祖先。要确定 A 是否在 B 后面,您需要检查 C 是否在 D 后面,这意味着您需要检查 C 和 D 在 E 容器中的深度(使用 DisplayObjectContainer.getChildIndex(child))。显然,在复杂的 UI 中,共同的祖先可能是很多代以前的,但即使是舞台,也总会有一个。

编辑:

我怎么忽略了显而易见的事情?!你不想点击鼠标按钮,但并没有说你根本不能使用MouseEvents,对吗?使用 ROLL_OVER 或 MOUSE_OVER 事件来跟踪你翻过的对象并用该对象进行 hitTest [羞愧地拍打额头]。

That's an excellent question that I don't have a ready-coded solution for. Exactly which thing is in the foreground getting clicked on is one of those things you take for granted when you get it for free as a MouseEvent target. The easy part is setting up all your display objects to listen for the KeyboardEvent corresponding to pressing the spacebar, and to hit test with the mouse position at that time.

The rest of your problem, the real problem, seems to me to boil down to one determination you need to make: A and B occupy the same screen space, which one is in front. In other words, once you have a list of all the DisplayObjects for which the hitTest is a hit, you need this compare function to sort them front to back. Here is how I see that working:

To determine if DisplayObject A is in front of or behind DisplayObject B, you need to trace their display list ancestry back to their common ancestor, and then look at the next generation down from that, to see if--at the point where their ancestry diverges--object A's ancestor is in front of or behind object B's (i.e. their relative depths in the common ancestor container). Consider a display tree like this:

       E
      / \
     C   D
    /     \
   A       B

E is the common ancestor. To determine if A is behind B, you need to check if C is behind D, which means you need to check C and D's depths in the E container (with DisplayObjectContainer.getChildIndex(child)). Obviously, in a complex UI the common ancestor could be many generations back, but there will always be one even if it's the stage.

EDIT:

How did I overlook the obvious?! you don't want to click the mouse button, but didn't say you couldn't use MouseEvents at all, right? Use the ROLL_OVER or MOUSE_OVER event to keep track of what you've rolled over and hitTest with that object [slaps forehead in shame].

醉梦枕江山 2024-11-10 16:21:31

好问题..我会环顾四周,但现在我能想到的就是拥有一个包含所有对象的数组(以与 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 中最高的。

Nice question.. I'll have a look around, but for now all I can think of is having an array that contains all your objects (added in the same order as they were to the DisplayList) and then iterating through backwards to find the first collision.

Eg (and sorry for the very lazy example):

    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;
}

The first DisplayObject found will be the highest in the DisplayList.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文