AS3 - Hit Test Object between two Movieclips in the same class file - actionscript-3

I'm wondering if there is a method to do a hit test object between two movieclips from the same class. The movieclips are being spawned into the stage using a for loop.
Is it possible to if(item(event.currentTarget).hitTestObeject(item(thats not being selected at the moment?))) I'm doing a drag and drop game and am trying to not let the items stack above each other when dragged to the snapping slots on the stage. If not is there other methods avaliable? Thanks in advance (:

first of all, detecting, whether two display objects (sprites, movieclips, etc.) hit each other, is independent of the fact, that the objects are instances of the same class. The important thing is, you have two instances and they are display objects, so you're good to go.
If you want to do hit tests, then i would do the following:
Create a helper class, that holds an Array of all the items, which have already been created.
That helper class needs to add itself as a listener to all the items for the event, that you start drag an item.
Once an item is dragged, the helper class adds itself as a listener to the mouse move event of that item
in the mouse move event handler, the helper class does a hit test from the currently dragged item to each item in its list of items (simple for loop)
if a hit test results with true, you save item you have currently tested against, as this is the one, that you dragged item is overlapping with.
Now you can do measurements (comparing positions, bounding boxes of the two items, etc) to figure out, where to position your dragged item, so that it does not overlap anymore.
Don't forget to remove the mouse move event listener in the event of the user ending to drag.

A few weeks ago I was working on a project wich had very specific dragging, so we've decided not to use the Flex DragManager. Our, so called, DragManager is not doing anything special. The thing that I think is related with your work is the presence of snap blocks. In our case the snap blocks were simple groups. Every snap block has a reference to the object wich was dropped into it(let's say it is droppedItem). When trying to drop an item, or even before triggering the snapping mechanism, there is a simple check in the snap block
if (droppedItem == null)
And this was the solution in our case.
I'm not sure what are your snapping slots, but I hope that our approach will help you.
Best regards, Ivan

Related

How does AS3's addChild works?

I'm aware that addChild (1) adds the object into a display container object, and (2) shows the object in the DisplayObjectContainer. What I want to know is what happens when an object is added into a DisplayObjectContainer?
To summarize my question is (are),
Is there any magic happens when addChild invoked? i.e. Something is happening in, for example, DisplayObjectContainer.
Let's say, I have MovieClip A and B. B has A as part of it. I called addChild (A) in B. In MainTimeline and Stage, I don't call addChild (B). Visually, since B hasn't been added, A won't be there too. However, does A is exist (e.g. the memory allocated), even though it's not on the Stage?
I have searched here and there in SO, but humongous amount of the questions asked related to mine are technical. I greatly appreciate any answer or pointer regarding my questions
Here is simplified explanation of what happens.
When you create MovieClip A (or any object) using the new keyword (or if using FlashPro an item that exists on the timeline where the playhead is), that object is in memory. So whether or not MovieClip A is on the display list, it is taking up memory in your application.
When you use addChild, here are some of those things that happen (not necessarily in order):
If the object being added already has parentage, it is removed from that parent (though scale and position are kept, and will now be relative to the new parent).
Events are dispatched on the new parent (and the old parent if applicable). Event.ADDED and Event.ADDED_TO_STAGE + Event.REMOVED / REMOVED_FROM_STAGE on the old parent.
The parent(s) of the newly added object, will now take into account the new child/grandchild. Things like hit tests, and bounds, and mouse overs etc.
On the next frame tick (the stage's refresh rate), that item will be drawn
All that said, once a movieClip is on the display list, there is performance drain VS just having that object in memory - so if an object doesn't need to be seen, it's more efficient to have it off the display list until it needs to be seen.
If using FlashPro/Animate, you should also be aware that if through code you do anything that manipulates the parentage of a timeline display object (addChild/removeChild/setChildIndex etc), that timeline object will no longer be managed by the timeline. That means that if you have an empty keyframe to remove an item from the timeline, that item will actually stay on the screen until you either explicitly remove it (removeChild(item)) or it's parent goes away.

AS3: bringing an object to front each frame

I have a UI object that, of course, should always be kept in front of all other objects. To do that, I decided to destroy and add it again each frame, like this:
removeChild(UI_Indicator)
addChild(UI_Indicator)
But nevertheless, objects that are created in it’s area still come on top of it. How is this even possible? I also tried the common
UI_Indicator.parent.setChildIndex(UI_Indicator,UI_Indicator.parent.numChildren - 1)
But it doesn’t work too. Any suggestions?
You are not destroying anything with removeChild(), you just stop displaying it. removeChild() isn't even necessary here. addChild() happily takes a DisplayObject that is already a child of the DisplayObjectContainer you called it on and re-adds the child again (to the top)
Instead of doing this readdChild()ing every frame, place your
allways-on-top DisplayObject on the display list once, then create
a DisplayObjectContainer, say a Sprite for example and add it
behind your indicator. Now add all your other DisplayObjects to
that container. This has the disadvantage of requiring you to add
everything to the container. The functionality breaks as soon as you
accidentally addChild() the regular way. This thought process
leads to the second solution below.
In your subclass of DisplayObjectContainer that includes the
indicator, override the methods that interact with the display list
(add/remove children, etc.) All those that could cause something to
get on top of your indicator. This puts you in full control of
what's going on when something is added to this container. You can
either incorporate solution 1 for simplicity's sake: delegate all
method calls to the inner container Sprite or, if you don't like
to have an internal container, do it without it and make sure that
no other child than your indicator is ever assigned the top most
index. You'd create an additional method to add the always-on-top child, like addTopChild() for example.

AS3 How can I solve the bug of setChildIndex

I've gathered all game pages on different frames of movieclip called game. in that game movieclip there are 4 different frames. on third frame I have some drag & drop functionality. When I drag one item, I want it to be on the front, I mean all other objects on that frame must not block the view of current dragging object. I used this.setChildIndex(currentDraggingObject,this.numChildren-1); but the problem is whenever I drag objects, when I change the frame, those objects are shown on that frames as well.
In short description: When I set an object's Index in MovieClip(game) , that object is seen in each frame of MovieClip(game) , how can I fix this?
I've searched the result online but couldn't find a solution.
Thank you
-Ozan
Instead of this:
this.setChildIndex(currentDraggingObject,this.numChildren-1);
You can simply use this:
this.addChild(currentDraggingObject); //shorter and clearer
If you have some object on a frame and you actually add it again, it indeed stays there in the other frames (I found this out too). The best/fastest solution would be to simple remove them before you are going to change the frame with this.removeChild(object)

as3 how can i prevent that a new instance is created by entering a frame?

i am working with several nested movieclip objects in a project. but i get into trouble with the buttons i created and implemented in the nested movieclips:
to describe it in a simple way:
I have a main movieclip with five frames, including two buttons with listeners to browse between the frames. Then inside of one Frame I have another movieclip with its own buttons. i instanciated it by hand not through code and gave it a specific name like "nestedMc".
Now I dont want to build the Listeners for those buttons inside the class of the nested movieclip class but in its parent class, which works fine until i then goto another frame in the main movieclips timeline and come back.
obviously every time flash enters a frame its contents get created anew (and therefore get new instance names). I could now try solve this through filling the frames via code.
But maybe there is another way to make sure the frame contains the same instance everytime i enter?
Timeline scripting is a dirty business, and really, a carry-over compatibility layer for Actionscript 2 projects. Whenever possible, I highly recommend not doing it, and simply keeping all of your code in your document class. As you're experiencing, timeline code causes headaches.
Consider instead just creating both states of your Stage (it sounds like that's what your two buttons are jumping between) and simply hiding them offstage or setting their alpha to zero and their mouseEnabled state to false. Furthermore, if the purpose of your frames is to play animation (a tween), consider instead switching to a much more powerful suite such as TweenLite. Moving an object over a hundred pixels (smoothly) can be as easy as:
TweenLite.to(redBall, 3, {x:100});
Now, if you're manually adding these items to the stage, as long as the object is a dynamic one, you can assign an instance name to it which will be saved between frame loads. Be aware the object name is not the same as the instanced name. For example:
var redBall:Ball = new Ball();
redBall.name = "bubbles";
The object's name is Ball, but it's represented as a variable called redBall. Its actual DisplayList name will likely be ambiguous (such as "Instance71"), and I can manually define it as "bubbles". 3 different names for the same object, all very different and necessary.
Even if you give the object a displayList name, you may not be able to reference it through code unless you enable Automatically declare stage instances, which basically creates on each object a pointer to the displayList object.
That said, you can always fetch the object by other means. Obviously, your buttons are always appearing, but you're trying to find a very specific object on the stage. At this point, we can use getChildByName() or getChildAt().
Hope that helps.
-Cheers

Has anyone experienced side effects (including performance issue) of using getObjectsUnderPoint?

Before I go making major change in my ongoing game project, I just want to hear from others if anyone has found any issues with getObjectsUnderPoint() function of the DisplayObject?
Update:
Not just the performance issue but any other limitations of using it (like it doesn't detect certain type of UIelements (just as example))
I will have three layers in my application (which an Isometric game)
Background -- This is just a background which stays in the bottom, has nothing to do with game
Middle Layer -- This is the playable area, Here all my game elements will be placed on this layer
Top Layer -- This is one dummy transparent layer covers entire playable area which interrupts all the mouse events. This is where I want to use the getObjectsUnderPoint()
So, player wants to click on the element, the top layer will interrupt the mouseevent and then check if there is something placed or just a plain background and take appropriate action like, notify the underneath object.
This really doesn't require to be done this way because I could simply add moues events for all those items placed on the map directly but because I would be using getObjectsUnderPoint() anyway to check if there is anything beneath the item.
If anyone can explain how this function works then it would be little easy for me to make a decision.
There was one annoying problem though. I don't know if they fixed it or not. At least it was there in 10.1 times.
If you have a container and you scaled it container.getObjectsUnderPoint will return wrong result. All the time. So everywhere where I needed getObjectsUnderPoint I had to call it from stage to get proper result.
It's an incomplete function. It returns graphical objects under the mouse, NOT all potential mouse targets for event or interaction purposes. It actually requires complex logic to examine the array returned by getObjectsUnderPoint to determine the mouse target, because the appropriate target (the one Flash would choose if you actually clicked that point) may not be in the list.
First you'd have to examine the object array in reverse, since the items are ordered back to front. You'd have to examine each object's entire parent chain, looking for a parent with mouseChildren = false that would cause it to intercept the event and become the target. Whether or not such an object is found, this final object you arrive at must have its mouseEnabled property set to true, otherwise you must skip it and move on to the next object in the array, which would be, for example, the next sprite or shape behind the one you initially checked. While going through the list, you must notice when the parent changes, at which point you need to assume that all children of that common parent had their mouseEnabled property set to false, in which case the parent would become the next candidate. This is actually extremely complicated, because you're working backwards in a bottom-up approach with an incomplete set of objects that was generated from the top-down.
To get actual potential mouse event targets, consistent with the default dispatching logic... it is actually easier to start from the stage in a top-down manner and walk backwards through the display hierarchy in a depth-first search, checking mouseChildren to determine whether you need to step into children, and checking mouseEnabled if it's to be a target, otherwise stepping into the container's children and repeating the process from back to front again. This is much more accurate, complete, and staightforward. The only problem is you have to code it yourself.