好的,在as3中点击的时候,最高层的对象会被点击。我希望有人按下空格键并让屏幕上的对象检查它是否正在触摸一个点。
所以我首先尝试了hittest ...
if (this.hitTest(myPoint)){ play(); }
现在的问题是其他对象后面的对象认为他们被“点击”了。
然后在沮丧之后,我使用了谷歌,找不到任何东西,所以请任何帮助。
好的,在as3中点击的时候,最高层的对象会被点击。我希望有人按下空格键并让屏幕上的对象检查它是否正在触摸一个点。
所以我首先尝试了hittest ...
if (this.hitTest(myPoint)){ play(); }
现在的问题是其他对象后面的对象认为他们被“点击”了。
然后在沮丧之后,我使用了谷歌,找不到任何东西,所以请任何帮助。
我认为这是您正在寻找的代码:
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方法。
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]
您可以使用parent
返回的 DisplayObjects 的属性来查找 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;
}
这是一个很好的问题,我没有现成的编码解决方案。当您将它作为 MouseEvent 目标免费获得时,您认为前景中的确切内容是您认为理所当然的事情之一。简单的部分是设置所有显示对象以侦听与按下空格键相对应的键盘事件,并使用当时的鼠标位置进行点击测试。
剩下的问题,真正的问题,在我看来归结为你需要做出的一个决定: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 [羞愧地拍了拍前额]。
好问题..我会环顾四周,但现在我能想到的只是有一个包含所有对象的数组(按与 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 中最高的。