【问题标题】:AS3 - Detecting if you clicked on an object without pressing the mouse buttonAS3 - 检测您是否在未按下鼠标按钮的情况下单击了对象
【发布时间】:2011-04-29 00:35:44
【问题描述】:

好的,在as3中点击的时候,最高层的对象会被点击。我希望有人按下空格键并让屏幕上的对象检查它是否接触到一个点。

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

如果 (this.hitTest(myPoint)){ 玩(); }

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

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

【问题讨论】:

  • 在那些不相关的对象上禁用鼠标事件会有所帮助吗? mouseEnabled=false 可能还有mouseChildren=false

标签: actionscript-3 object click point hittest


【解决方案1】:

我认为这是您要查找的代码:

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

关键是flash的getObjectsUnderPoint方法。

【讨论】:

    【解决方案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 的 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;
    }
    

    【讨论】:

      【解决方案3】:

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

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

      要确定 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 [羞愧地拍了拍额头]。

      【讨论】:

      • 我也这么认为 - 但我不确定问题是否暗示 Point 是否始终位于鼠标位置。
      • 确实,我不清楚所讨论的“点”是鼠标位置还是任意点。显然,翻转方法只有在我们谈论鼠标下方的内容并且只使用空格键时才有效,就像它是鼠标按钮一样。
      • 是的。不过想法不错。 +1
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-31
        相关资源
        最近更新 更多