AS3 - Detection if you click on an object without clicking a mouse button

Well, in as3, when you click, the object on the highest layer will be clicked. I want someone to press the space bar and display objects on the screen to check if it touches the point.

So, I tried hittest first ...

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

Now the problem was that the objects behind the others thought they were โ€œpressedโ€.

Then, after disappointment, I used Google, could not find anything, so please help.

+4
source share
4 answers

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

The key is flash getObjectsUnderPoint .

+5
source
 DisplayObjectContainer.getObjectsUnderPoint() 

Be careful getObjectsUnderPoint does not return DisplayObjectContainers, as shown 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 the returned DisplayObjects to search for 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; } 
+2
source

This is a great question for which I have no ready-made solution. Exactly what comes first is one of those things that you take for granted when you get it for free as a MouseEvent target. The easy part is setting up all of your display objects to listen for a KeyboardEvent corresponding to a space bar, and to click the test with the mouse position at that moment.

The rest of your problem, the real problem, seems to come down to one definition that you need to make: A and B occupy the same screen space that is in front. In other words, once you have a list of all DisplayObjects for which hitTest is a hit, you need this comparison function to sort them from front to back. This is how I see what works:

To determine if DisplayObject A is in front of or next to DisplayObject B, you need to track their ancestors of the predicted list to their common ancestor, and then look down the next generation to see if - at the point where their pedigree diverges - the ancestor object is in front of or behind object B (i.e., their relative depth in the container of the common ancestor). Consider the mapping tree as follows:

  E / \ CD / \ AB 

E is a common ancestor. To determine if A is behind B, you need to check if C is behind D, which means you need to check the depths of C and D in container E (with DisplayObjectContainer.getChildIndex (child)). Obviously, in a complex user interface, a common ancestor may be many generations ago, but there will always be one, even if this is a stage.

EDIT:

How did I lose sight of the obvious ?! you donโ€™t want to click the mouse button, but you didnโ€™t say that you cannot use MouseEvents at all, right? Use the ROLL_OVER or MOUSE_OVER event to keep track of what you turned over, and hitTest with this object [pats his forehead in disgrace].

+1
source

Good question. I'll take a look around, but for now all I can think of is to have an array containing all of your objects (added in the same order as in the DisplayList), and then iterate in reverse order to find the first collision.

For example (and sorry for the laziest 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.

0
source

All Articles